2013-07-03 12:14 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)

* include/hbapidbg.h
  * src/debug/dbgentry.c
  * src/debug/debugger.prg
    + added new C function hb_dbgGetModuleName() - it returns module name
      used to register module in HVM. In current version it only strips
      path part though in the future it may use some more advanced code
      which allow to debug modules with the same name but different paths
      in single application and such extension will be local to core debug
      code if upper level debugger uses hb_dbgGetModuleName()
    + added new PRG function __DBGGETMODULENAME() - it's wrapper to
      hb_dbgGetModuleName()
    + added new PRG function __DBGMODULEMATCH()
    ! use __DBGMODULEMATCH() instead of hb_FileMatch() and strip_path()
    ! eliminated strip_path() from PRG code and use hb_dbgGetModuleName()
      in C code in places where it's necessary
    ! replaced few strcmp() used to compare module names with
      FILENAME_EQUAL()
    ; above modification may fix few potential problem with breakpoints
      in debugger on some platforms if user uses different paths for
      debugger and compilers.
    ! eliminated hack with memvar/field name copy in watch points,
      it also fixes memory leak when fields are used in watch points.
    % replaced few DO CASE with SWITCH
This commit is contained in:
Przemysław Czerpak
2013-07-03 12:14:50 +02:00
parent 96e7b0159c
commit ab3f6109c1
4 changed files with 224 additions and 136 deletions

View File

@@ -10,6 +10,31 @@
* Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment
*/
2013-07-03 12:14 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* include/hbapidbg.h
* src/debug/dbgentry.c
* src/debug/debugger.prg
+ added new C function hb_dbgGetModuleName() - it returns module name
used to register module in HVM. In current version it only strips
path part though in the future it may use some more advanced code
which allow to debug modules with the same name but different paths
in single application and such extension will be local to core debug
code if upper level debugger uses hb_dbgGetModuleName()
+ added new PRG function __DBGGETMODULENAME() - it's wrapper to
hb_dbgGetModuleName()
+ added new PRG function __DBGMODULEMATCH()
! use __DBGMODULEMATCH() instead of hb_FileMatch() and strip_path()
! eliminated strip_path() from PRG code and use hb_dbgGetModuleName()
in C code in places where it's necessary
! replaced few strcmp() used to compare module names with
FILENAME_EQUAL()
; above modification may fix few potential problem with breakpoints
in debugger on some platforms if user uses different paths for
debugger and compilers.
! eliminated hack with memvar/field name copy in watch points,
it also fixes memory leak when fields are used in watch points.
% replaced few DO CASE with SWITCH
2013-06-21 14:58 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* contrib/gtqtc/gtqtc.h
* contrib/gtqtc/gtqtc1.cpp

View File

@@ -67,7 +67,8 @@ extern HB_EXPORT PHB_ITEM hb_dbg_vmVarGGet( int nGlobal, int nOffset );
/* internal debugger function */
extern HB_EXPORT void hb_dbgEntry( int nMode, int nLine, const char * szName, int nIndex, PHB_ITEM pFrame );
extern HB_EXPORT void hb_dbgAddBreak( void * handle, const char * cModule, int nLine, const char * szFunction );
extern HB_EXPORT const char * hb_dbgGetModuleName( void * handle, const char * szName );
extern HB_EXPORT void hb_dbgAddBreak( void * handle, const char * szModule, int nLine, const char * szFunction );
extern HB_EXPORT void hb_dbgAddWatch( void * handle, const char * szExpr, HB_BOOL bTrace );
extern HB_EXPORT void hb_dbgDelBreak( void * handle, int nBreak );
extern HB_EXPORT void hb_dbgDelWatch( void * handle, int nWatch );

View File

@@ -103,8 +103,8 @@ typedef struct
typedef struct
{
char * szName;
char cType;
const char * szName;
char cType;
union
{
int num;
@@ -178,6 +178,7 @@ typedef struct
HB_BOOL bInitGlobals;
HB_BOOL bInitStatics;
HB_BOOL bInitLines;
PHB_DYNS pDbgEntry;
} HB_DEBUGINFO;
static HB_DBGCOMMONINFO s_common = { 0, NULL, NULL };
@@ -206,14 +207,19 @@ static void hb_dbgVarSet( HB_VARINFO * scope, PHB_ITEM xNewValue );
static void hb_dbgActivate( HB_DEBUGINFO * info )
{
PHB_DYNS pDynSym = hb_dynsymFind( "__DBGENTRY" );
if( pDynSym && hb_dynsymIsFunction( pDynSym ) )
if( ! info->pDbgEntry )
{
info->pDbgEntry = hb_dynsymFind( "__DBGENTRY" );
if( info->pDbgEntry && ! hb_dynsymIsFunction( info->pDbgEntry ) )
info->pDbgEntry = NULL;
}
if( info->pDbgEntry )
{
int i;
PHB_ITEM aCallStack = hb_itemArrayNew( info->nCallStackLen );
PHB_ITEM aModules;
PHB_ITEM aBreak;
int i;
for( i = 0; i < info->nCallStackLen; i++ )
{
@@ -241,7 +247,7 @@ static void hb_dbgActivate( HB_DEBUGINFO * info )
aModules = hb_dbgActivateModuleArray();
aBreak = hb_dbgActivateBreakArray( info );
hb_vmPushDynSym( pDynSym );
hb_vmPushDynSym( info->pDbgEntry );
hb_vmPushNil();
hb_vmPushLong( HB_DBG_ACTIVATE );
hb_vmPushPointer( info );
@@ -569,6 +575,7 @@ void hb_dbgAddBreak( void * handle, const char * szModule, int nLine, const char
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
HB_BREAKPOINT * pBreak;
szModule = hb_dbgStripModuleName( szModule );
pBreak = ARRAY_ADD( HB_BREAKPOINT, info->aBreak, info->nBreakPoints );
pBreak->szModule = hb_strdup( szModule );
pBreak->nLine = nLine;
@@ -613,7 +620,7 @@ static void hb_dbgAddModule( const char * szName )
szModuleName = hb_strndup( szName, iLen );
HB_DBGCOMMON_LOCK();
if( ! s_common.nModules || strcmp( s_common.aModules[ s_common.nModules - 1 ].szModule, szModuleName ) )
if( ! s_common.nModules || !FILENAME_EQUAL( s_common.aModules[ s_common.nModules - 1 ].szModule, szModuleName ) )
{
HB_MODULEINFO * pModule;
@@ -636,8 +643,11 @@ static void hb_dbgAddStack( HB_DEBUGINFO * info, const char * szName, int nProcL
{
char szBuff[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ];
HB_CALLSTACKINFO * top;
const char * szFunction = strrchr( szName, ':' );
const char * szFunction;
szName = hb_dbgStripModuleName( szName );
szFunction = strrchr( szName, ':' );
if( szFunction )
szFunction++;
@@ -662,8 +672,6 @@ static void hb_dbgAddStack( HB_DEBUGINFO * info, const char * szName, int nProcL
}
}
szName = hb_dbgStripModuleName( szName );
if( szFunction )
top->szModule = hb_strndup( szName, szFunction - szName - 1 );
else
@@ -735,7 +743,7 @@ static void hb_dbgAddStopLines( PHB_ITEM pItem )
{
PHB_ITEM pLines = hb_arrayGetItemPtr( s_common.pStopLines, j );
if( ! strcmp( hb_arrayGetCPtr( pLines, 1 ), szModule ) )
if( FILENAME_EQUAL( hb_arrayGetCPtr( pLines, 1 ), szModule ) )
{
/* Merge stopline info */
HB_ISIZ nOrigMin = hb_arrayGetNS( pLines, 2 );
@@ -797,8 +805,7 @@ static void hb_dbgAddVar( int * nVars, HB_VARINFO ** aVars, const char * szName,
HB_VARINFO * var;
var = ARRAY_ADD( HB_VARINFO, *aVars, *nVars );
/* TODO/TOFIX: value should be duplicated here and then released */
var->szName = ( char * ) szName;
var->szName = szName;
var->cType = cType;
var->nIndex = nIndex;
if( cType == 'S' )
@@ -972,11 +979,6 @@ static PHB_ITEM hb_dbgEval( HB_DEBUGINFO * info, HB_WATCHPOINT * watch )
hb_itemRelease( aVars );
hb_itemRelease( aNewVars );
for( i = 0; i < watch->nVars; i++ )
{
if( watch->aScopes[ i ].cType == 'M' )
hb_xfree( watch->aScopes[ i ].szName );
}
if( watch->nVars )
hb_xfree( watch->aScopes );
}
@@ -1061,18 +1063,14 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch )
c = watch->szExpr[ j ];
}
nLen = j - i;
szWord = hb_strndup( watch->szExpr + i, nLen );
i = j;
if( c )
{
while( watch->szExpr[ i ] && watch->szExpr[ i ] == ' ' )
while( watch->szExpr[ i ] == ' ' )
i++;
if( watch->szExpr[ i ] == '(' )
{
hb_xfree( szWord );
continue;
}
if( watch->szExpr[ i ] == '-' && watch->szExpr[ i + 1 ] == '>' )
{
@@ -1081,11 +1079,10 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch )
while( ( c = watch->szExpr[ i ] ) != '\0' && IS_IDENT_CHAR( c ) )
i++;
hb_xfree( szWord );
continue;
}
}
hb_strupr( szWord );
szWord = hb_strupr( hb_strndup( watch->szExpr + nStart, nLen ) );
i = hb_dbgEvalSubstituteVar( watch, szWord, nStart, nLen );
bAfterId = HB_TRUE;
continue;
@@ -1213,7 +1210,7 @@ static PHB_ITEM hb_dbgEvalResolve( HB_DEBUGINFO * info, HB_WATCHPOINT * watch )
for( i = 0; i < s_common.nModules; i++ )
{
if( ! strcmp( s_common.aModules[ i ].szModule, top->szModule ) )
if( FILENAME_EQUAL( s_common.aModules[ i ].szModule, top->szModule ) )
{
module = &s_common.aModules[ i ];
break;
@@ -1306,7 +1303,7 @@ static PHB_ITEM hb_dbgEvalResolve( HB_DEBUGINFO * info, HB_WATCHPOINT * watch )
}
scopes[ i ].cType = 'M';
scopes[ i ].szName = hb_strdup( name );
scopes[ i ].szName = hb_dynsymGetSymbol( name )->szName;
pItem = hb_dbgVarGet( &scopes[ i ] );
@@ -1383,6 +1380,8 @@ static HB_BOOL hb_dbgIsBreakPoint( HB_DEBUGINFO * info, const char * szModule, i
{
int i;
/* szModule has stripped path here */
for( i = 0; i < info->nBreakPoints; i++ )
{
HB_BREAKPOINT * point = &info->aBreak[ i ];
@@ -1404,6 +1403,8 @@ HB_BOOL hb_dbgIsValidStopLine( void * handle, const char * szModule, int nLine )
/* HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; */
HB_SYMBOL_UNUSED( handle );
szModule = hb_dbgStripModuleName( szModule );
HB_DBGCOMMON_LOCK();
nModules = hb_itemSize( s_common.pStopLines );
for( i = 1; i <= nModules; i++ )
@@ -1426,6 +1427,18 @@ HB_BOOL hb_dbgIsValidStopLine( void * handle, const char * szModule, int nLine )
}
const char * hb_dbgGetModuleName( void * handle, const char * szName )
{
/* HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; */
HB_SYMBOL_UNUSED( handle );
if( szName )
szName = hb_dbgStripModuleName( szName );
return szName;
}
static void hb_dbgQuit( HB_DEBUGINFO * info )
{
while( info->nWatchPoints )
@@ -1524,6 +1537,8 @@ void hb_dbgSetToCursor( void * handle, const char * szModule, int nLine )
{
HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
szModule = hb_dbgStripModuleName( szModule );
info->bToCursor = HB_TRUE;
info->szToCursorModule = hb_strdup( szModule );
info->nToCursorLine = nLine;
@@ -1771,6 +1786,29 @@ HB_FUNC( __DBGSETWATCH )
hb_dbgSetWatch( ptr, hb_parni( 2 ), hb_parc( 3 ), hb_parl( 4 ) );
}
HB_FUNC( __DBGGETMODULENAME )
{
void * ptr = hb_parptr( 1 );
if( ptr )
hb_retc( hb_dbgGetModuleName( ptr, hb_parc( 2 ) ) );
}
HB_FUNC( __DBGMODULEMATCH )
{
void * ptr = hb_parptr( 1 );
if( ptr )
{
const char * szModule1 = hb_parc( 2 ),
* szModule2 = hb_parc( 3 );
hb_retl( szModule1 && szModule2 &&
FILENAME_EQUAL( hb_dbgStripModuleName( szModule1 ),
hb_dbgStripModuleName( szModule2 ) ) );
}
}
HB_FUNC( __DBGSENDMSG )
{
hb_dbg_objSendMessage( hb_parnl( 1 ), hb_param( 2, HB_IT_ANY ),

View File

@@ -131,12 +131,8 @@ PROCEDURE __dbgEntry( nMode, uParam1, uParam2, uParam3, uParam4, uParam5 )
LOCAL lStartup
DO CASE
CASE nMode == HB_DBG_GETENTRY
__dbgSetEntry()
CASE nMode == HB_DBG_ACTIVATE
SWITCH nMode
CASE HB_DBG_ACTIVATE
IF ( lStartup := ( t_oDebugger == NIL ) )
t_oDebugger := HBDebugger():New()
@@ -154,8 +150,13 @@ PROCEDURE __dbgEntry( nMode, uParam1, uParam2, uParam3, uParam4, uParam5 )
ENDIF
t_oDebugger:lGo := .F.
t_oDebugger:Activate()
RETURN
ENDCASE
CASE HB_DBG_GETENTRY
__dbgSetEntry()
ENDSWITCH
RETURN
@@ -268,6 +269,7 @@ CREATE CLASS HBDebugger
METHOD FindPrevious()
METHOD GetExprValue( xExpr, lValid )
METHOD GetSourceFiles()
METHOD ModuleMatch( cModuleName1, cModuleName2 )
METHOD Global()
@@ -564,52 +566,62 @@ METHOD CallStackProcessKey( nKey ) CLASS HBDebugger
LOCAL nSkip
LOCAL lUpdate := .F.
DO CASE
CASE nKey == K_HOME .OR. nKey == K_CTRL_PGUP .OR. nKey == K_CTRL_HOME
SWITCH nKey
CASE K_HOME
CASE K_CTRL_PGUP
CASE K_CTRL_HOME
IF ::oBrwStack:Cargo > 1
::oBrwStack:GoTop()
::oBrwStack:ForceStable()
lUpdate := .T.
ENDIF
EXIT
CASE nKey == K_END .OR. nKey == K_CTRL_PGDN .OR. nKey == K_CTRL_END
CASE K_END
CASE K_CTRL_PGDN
CASE K_CTRL_END
IF ::oBrwStack:Cargo < Len( ::aProcStack )
::oBrwStack:GoBottom()
::oBrwStack:ForceStable()
lUpdate := .T.
ENDIF
EXIT
CASE nKey == K_UP
CASE K_UP
IF ::oBrwStack:Cargo > 1
::oBrwStack:Up()
::oBrwStack:ForceStable()
lUpdate := .T.
ENDIF
EXIT
CASE nKey == K_DOWN
CASE K_DOWN
IF ::oBrwStack:Cargo < Len( ::aProcStack )
::oBrwStack:Down()
::oBrwStack:ForceStable()
lUpdate := .T.
ENDIF
EXIT
CASE nKey == K_PGUP
CASE K_PGUP
::oBrwStack:PageUp()
::oBrwStack:ForceStable()
lUpdate := .T.
EXIT
CASE nKey == K_PGDN
CASE K_PGDN
::oBrwStack:PageDown()
::oBrwStack:ForceStable()
lUpdate := .T.
EXIT
CASE nKey == K_LBUTTONDOWN
CASE K_LBUTTONDOWN
IF ( nSkip := MRow() - ::oWndStack:nTop - ::oBrwStack:RowPos ) != 0
IF nSkip > 0
@@ -626,8 +638,9 @@ METHOD CallStackProcessKey( nKey ) CLASS HBDebugger
::oBrwStack:ForceStable()
ENDIF
lUpdate := .T.
EXIT
ENDCASE
ENDSWITCH
IF lUpdate
IF ::oWndVars != NIL .AND. ::oWndVars:lVisible
@@ -663,15 +676,20 @@ METHOD CodeWindowProcessKey( nKey ) CLASS HBDebugger
IF ::oBrwText != NIL
DO CASE
CASE nKey == K_HOME .OR. nKey == K_CTRL_PGUP .OR. nKey == K_CTRL_HOME
SWITCH nKey
CASE K_HOME
CASE K_CTRL_PGUP
CASE K_CTRL_HOME
::oBrwText:GoTop()
IF ::oWndCode:lFocused
SetCursor( SC_SPECIAL1 )
ENDIF
EXIT
CASE nKey == K_END .OR. nKey == K_CTRL_PGDN .OR. nKey == K_CTRL_END
CASE K_END
CASE K_CTRL_PGDN
CASE K_CTRL_END
::oBrwText:GoBottom()
::oBrwText:nCol := ::oWndCode:nLeft + 1
@@ -680,26 +698,33 @@ METHOD CodeWindowProcessKey( nKey ) CLASS HBDebugger
IF ::oWndCode:lFocused
SetCursor( SC_SPECIAL1 )
ENDIF
EXIT
CASE nKey == K_LEFT
CASE K_LEFT
::oBrwText:Left()
EXIT
CASE nKey == K_RIGHT
CASE K_RIGHT
::oBrwText:Right()
EXIT
CASE nKey == K_UP
CASE K_UP
::oBrwText:Up()
EXIT
CASE nKey == K_DOWN
CASE K_DOWN
::oBrwText:Down()
EXIT
CASE nKey == K_PGUP
CASE K_PGUP
::oBrwText:PageUp()
EXIT
CASE nKey == K_PGDN
CASE K_PGDN
::oBrwText:PageDown()
EXIT
ENDCASE
ENDSWITCH
ENDIF
RETURN NIL
@@ -872,7 +897,7 @@ METHOD DoCommand( cCommand ) CLASS HBDebugger
ELSE
cParam1 := ::cPrgName
ENDIF
::ToggleBreakPoint( Val( cParam ), strip_path( cParam1 ) )
::ToggleBreakPoint( Val( cParam ), cParam1 )
ELSE
::ToggleBreakPoint()
ENDIF
@@ -1202,6 +1227,10 @@ METHOD GetSourceFiles() CLASS HBDebugger
RETURN __dbgGetSourceFiles( ::pInfo )
METHOD ModuleMatch( cModuleName1, cModuleName2 ) CLASS HBDebugger
RETURN __dbgModuleMatch( ::pInfo, cModuleName1, cModuleName2 )
METHOD Global() CLASS HBDebugger
::lShowGlobals := ! ::lShowGlobals
@@ -1537,11 +1566,12 @@ METHOD InputBox( cMsg, uValue, bValid, lEditable ) CLASS HBDebugger
DO WHILE ! lExit
Inkey( 0 )
DO CASE
CASE LastKey() == K_ESC
SWITCH LastKey()
CASE K_ESC
lExit := .T.
EXIT
CASE LastKey() == K_ENTER
CASE K_ENTER
IF cType == "A"
IF Len( uValue ) == 0
__dbgAlert( "Array is empty" )
@@ -1562,10 +1592,12 @@ METHOD InputBox( cMsg, uValue, bValid, lEditable ) CLASS HBDebugger
ELSE
__dbgAlert( "Value cannot be edited" )
ENDIF
EXIT
OTHERWISE
__dbgAlert( "Value cannot be edited" )
ENDCASE
ENDSWITCH
ENDDO
ENDIF
@@ -1736,7 +1768,7 @@ METHOD LoadVars() CLASS HBDebugger // updates monitored variables
cName := ::aProcStack[ ::oBrwStack:Cargo ][ CSTACK_MODULE ]
FOR n := 1 TO Len( ::aModules )
IF ! ::lShowAllGlobals
IF ! hb_FileMatch( ::aModules[ n ][ MODULE_NAME ], cName )
IF ! ::ModuleMatch( ::aModules[ n ][ MODULE_NAME ], cName )
LOOP
ENDIF
ENDIF
@@ -1755,7 +1787,7 @@ METHOD LoadVars() CLASS HBDebugger // updates monitored variables
IF ::lShowStatics
cName := ::aProcStack[ ::oBrwStack:Cargo ][ CSTACK_MODULE ]
n := AScan( ::aModules, {| a | hb_FileMatch( a[ MODULE_NAME ], cName ) } )
n := AScan( ::aModules, {| a | ::ModuleMatch( a[ MODULE_NAME ], cName ) } )
IF n > 0
aVars := ::aModules[ n ][ MODULE_STATICS ]
FOR m := 1 TO Len( aVars )
@@ -2083,7 +2115,7 @@ METHOD RedisplayBreakPoints() CLASS HBDebugger
LOCAL n
FOR n := 1 TO Len( ::aBreakpoints )
IF hb_FileMatch( ::aBreakpoints[ n ][ 2 ], strip_path( ::cPrgName ) )
IF ::ModuleMatch( ::aBreakpoints[ n ][ 2 ], ::cPrgName )
::oBrwText:ToggleBreakPoint( ::aBreakpoints[ n ][ 1 ], .T. )
ENDIF
NEXT
@@ -2493,7 +2525,7 @@ METHOD ShowCodeLine( nProc ) CLASS HBDebugger
IF ! Empty( cPrgName )
IF ! hb_FileMatch( strip_path( cPrgName ), strip_path( ::cPrgName ) ) .OR. ;
IF ! ::ModuleMatch( cPrgName, ::cPrgName ) .OR. ;
::oBrwText == NIL
IF ! hb_FileExists( cPrgName ) .AND. ! Empty( ::cPathForFiles )
@@ -2728,8 +2760,8 @@ METHOD Step() CLASS HBDebugger
METHOD ToCursor() CLASS HBDebugger
IF ::IsValidStopLine( strip_path( ::cPrgName ), ::oBrwText:RowPos )
__dbgSetToCursor( ::pInfo, strip_path( ::cPrgName ), ::oBrwText:RowPos )
IF ::IsValidStopLine( ::cPrgName, ::oBrwText:RowPos )
__dbgSetToCursor( ::pInfo, ::cPrgName, ::oBrwText:RowPos )
::RestoreAppScreen()
::RestoreAppState()
::Exit()
@@ -2751,7 +2783,7 @@ METHOD ToggleBreakPoint( nLine, cFileName ) CLASS HBDebugger
ENDIF
IF nLine == NIL
cFileName := strip_path( ::cPrgName )
cFileName := ::cPrgName
nLine := ::oBrwText:RowPos
ENDIF
@@ -2760,18 +2792,18 @@ METHOD ToggleBreakPoint( nLine, cFileName ) CLASS HBDebugger
ENDIF
nAt := AScan( ::aBreakPoints, {| aBreak | aBreak[ 1 ] == nLine ;
.AND. hb_FileMatch( aBreak[ 2 ], cFileName ) } )
.AND. ::ModuleMatch( aBreak[ 2 ], cFileName ) } )
IF nAt == 0
AAdd( ::aBreakPoints, { nLine, cFileName } ) // it was nLine
__dbgAddBreak( ::pInfo, cFileName, nLine )
IF hb_FileMatch( cFileName, strip_path( ::cPrgName ) )
IF ::ModuleMatch( cFileName, ::cPrgName )
::oBrwText:ToggleBreakPoint( nLine, .T. )
ENDIF
ELSE
hb_ADel( ::aBreakPoints, nAt, .T. )
__dbgDelBreak( ::pInfo, nAt - 1 )
IF hb_FileMatch( cFileName, strip_path( ::cPrgName ) )
IF ::ModuleMatch( cFileName, ::cPrgName )
::oBrwText:ToggleBreakPoint( nLine, .F. )
ENDIF
ENDIF
@@ -2816,15 +2848,14 @@ METHOD TracepointAdd( cExpr ) CLASS HBDebugger
METHOD VarGetInfo( aVar ) CLASS HBDebugger
LOCAL cType := Left( aVar[ VAR_TYPE ], 1 )
LOCAL uValue := ::VarGetValue( aVar )
DO CASE
CASE cType == "G" ; RETURN aVar[ VAR_NAME ] + " <Global, " + ValType( uValue ) + ">: " + __dbgValToStr( uValue )
CASE cType == "L" ; RETURN aVar[ VAR_NAME ] + " <Local, " + ValType( uValue ) + ">: " + __dbgValToStr( uValue )
CASE cType == "S" ; RETURN aVar[ VAR_NAME ] + " <Static, " + ValType( uValue ) + ">: " + __dbgValToStr( uValue )
OTHERWISE ; RETURN aVar[ VAR_NAME ] + " <" + aVar[ VAR_TYPE ] + ", " + ValType( uValue ) + ">: " + __dbgValToStr( uValue )
ENDCASE
SWITCH Left( aVar[ VAR_TYPE ], 1 )
CASE "G" ; RETURN aVar[ VAR_NAME ] + " <Global, " + ValType( uValue ) + ">: " + __dbgValToStr( uValue )
CASE "L" ; RETURN aVar[ VAR_NAME ] + " <Local, " + ValType( uValue ) + ">: " + __dbgValToStr( uValue )
CASE "S" ; RETURN aVar[ VAR_NAME ] + " <Static, " + ValType( uValue ) + ">: " + __dbgValToStr( uValue )
OTHERWISE; RETURN aVar[ VAR_NAME ] + " <" + aVar[ VAR_TYPE ] + ", " + ValType( uValue ) + ">: " + __dbgValToStr( uValue )
ENDSWITCH
// ; Never reached
@@ -2833,14 +2864,12 @@ METHOD VarGetInfo( aVar ) CLASS HBDebugger
METHOD VarGetValue( aVar ) CLASS HBDebugger
LOCAL cType := Left( aVar[ VAR_TYPE ], 1 )
DO CASE
CASE cType == "G" ; RETURN __dbgVMVarGGet( aVar[ VAR_LEVEL ], aVar[ VAR_POS ] )
CASE cType == "L" ; RETURN __dbgVMVarLGet( __dbgProcLevel() - aVar[ VAR_LEVEL ], aVar[ VAR_POS ] )
CASE cType == "S" ; RETURN __dbgVMVarSGet( aVar[ VAR_LEVEL ], aVar[ VAR_POS ] )
OTHERWISE ; RETURN aVar[ VAR_POS ] // Public or Private
ENDCASE
SWITCH Left( aVar[ VAR_TYPE ], 1 )
CASE "G" ; RETURN __dbgVMVarGGet( aVar[ VAR_LEVEL ], aVar[ VAR_POS ] )
CASE "L" ; RETURN __dbgVMVarLGet( __dbgProcLevel() - aVar[ VAR_LEVEL ], aVar[ VAR_POS ] )
CASE "S" ; RETURN __dbgVMVarSGet( aVar[ VAR_LEVEL ], aVar[ VAR_POS ] )
OTHERWISE; RETURN aVar[ VAR_POS ] // Public or Private
ENDSWITCH
// ; Never reached
@@ -2850,24 +2879,23 @@ METHOD VarGetValue( aVar ) CLASS HBDebugger
METHOD VarSetValue( aVar, uValue ) CLASS HBDebugger
LOCAL nProcLevel
LOCAL cType := Left( aVar[ VAR_TYPE ], 1 )
IF cType == "G"
SWITCH Left( aVar[ VAR_TYPE ], 1 )
CASE "G"
__dbgVMVarGSet( aVar[ VAR_LEVEL ], aVar[ VAR_POS ], uValue )
ELSEIF cType == "L"
EXIT
CASE "L"
nProcLevel := __dbgProcLevel() - aVar[ VAR_LEVEL ] // skip debugger stack
__dbgVMVarLSet( nProcLevel, aVar[ VAR_POS ], uValue )
ELSEIF cType == "S"
EXIT
CASE "S"
__dbgVMVarSSet( aVar[ VAR_LEVEL ], aVar[ VAR_POS ], uValue )
ELSE
EXIT
OTHERWISE
// Public or Private
aVar[ VAR_POS ] := uValue
&( aVar[ VAR_NAME ] ) := uValue
ENDIF
ENDSWITCH
RETURN Self
@@ -3179,32 +3207,38 @@ METHOD WndVarsLButtonDown( nMRow, nMCol ) CLASS HBDebugger
STATIC PROCEDURE SetsKeyPressed( nKey, oBrwSets, nSets, oWnd, cCaption, bEdit )
DO CASE
CASE nKey == K_UP
SWITCH nKey
CASE K_UP
oBrwSets:up()
EXIT
CASE nKey == K_DOWN
CASE K_DOWN
oBrwSets:down()
EXIT
CASE nKey == K_HOME .OR. nKey == K_CTRL_PGUP .OR. nKey == K_CTRL_HOME
CASE K_HOME
CASE K_CTRL_PGUP
CASE K_CTRL_HOME
oBrwSets:goTop()
EXIT
CASE nKey == K_END .OR. nKey == K_CTRL_PGDN .OR. nKey == K_CTRL_END
CASE K_END
CASE K_CTRL_PGDN
CASE K_CTRL_END
oBrwSets:goBottom()
EXIT
CASE nKey == K_PGDN
CASE K_PGDN
oBrwSets:pageDown()
EXIT
CASE nKey == K_PGUP
CASE K_PGUP
oBrwSets:pageUp()
EXIT
CASE nKey == K_ENTER
CASE K_ENTER
IF bEdit != NIL
Eval( bEdit )
@@ -3213,8 +3247,9 @@ STATIC PROCEDURE SetsKeyPressed( nKey, oBrwSets, nSets, oWnd, cCaption, bEdit )
IF LastKey() == K_ENTER
hb_keyPut( K_DOWN )
ENDIF
EXIT
ENDCASE
ENDSWITCH
RefreshVarsS( oBrwSets )
@@ -3282,19 +3317,6 @@ STATIC FUNCTION starts( cLine, cStart )
RETURN cStart == Left( cLine, Len( cStart ) )
/* Strip path from filename */
STATIC FUNCTION strip_path( cFileName )
LOCAL cName
LOCAL cExt
hb_default( @cFileName, "" )
hb_FNameSplit( cFileName, NIL, @cName, @cExt )
RETURN cName + cExt
FUNCTION __dbgInput( nRow, nCol, nWidth, cValue, bValid, cColor, nSize )
LOCAL nOldCursor := SetCursor( SC_NORMAL )
@@ -3371,21 +3393,23 @@ FUNCTION __dbgAlert( cMessage )
FUNCTION __dbgValToStr( uVal )
LOCAL cType := ValType( uVal )
DO CASE
CASE uVal == NIL ; RETURN "NIL"
CASE cType == "B" ; RETURN "{|| ... }"
CASE cType == "A" ; RETURN "{ ... }"
CASE cType $ "CM" ; RETURN '"' + uVal + '"'
CASE cType == "L" ; RETURN iif( uVal, ".T.", ".F." )
CASE cType == "D" ; RETURN DToC( uVal )
CASE cType == "T" ; RETURN hb_TToC( uVal )
CASE cType == "N" ; RETURN Str( uVal )
CASE cType == "O" ; RETURN "Class " + uVal:ClassName() + " object"
CASE cType == "H" ; RETURN "Hash of " + hb_ntos( Len( uVal ) ) + " elements"
CASE cType == "P" ; RETURN "Pointer"
ENDCASE
SWITCH ValType( uVal )
CASE "B" ; RETURN "{|| ... }"
CASE "A" ; RETURN "{ ... }"
CASE "C"
CASE "M" ; RETURN '"' + uVal + '"'
CASE "L" ; RETURN iif( uVal, ".T.", ".F." )
CASE "D" ; RETURN DToC( uVal )
CASE "T" ; RETURN hb_TToC( uVal )
CASE "N" ; RETURN Str( uVal )
CASE "O" ; RETURN "Class " + uVal:ClassName() + " object"
CASE "H" ; RETURN "Hash of " + hb_ntos( Len( uVal ) ) + " elements"
CASE "P" ; RETURN "Pointer"
OTHERWISE
IF uVal == NIL
RETURN "NIL"
ENDIF
ENDSWITCH
RETURN "U"