From ab3f6109c1b8087b60ed88eb5cea5cdba2e0d318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Czerpak?= Date: Wed, 3 Jul 2013 12:14:50 +0200 Subject: [PATCH] 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 --- ChangeLog.txt | 25 +++++ include/hbapidbg.h | 3 +- src/debug/dbgentry.c | 94 +++++++++++----- src/debug/debugger.prg | 238 +++++++++++++++++++++++------------------ 4 files changed, 224 insertions(+), 136 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index b17cd05eaa..4b3800fa1d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -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 diff --git a/include/hbapidbg.h b/include/hbapidbg.h index 98190d5fc7..ceaa79dc46 100644 --- a/include/hbapidbg.h +++ b/include/hbapidbg.h @@ -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 ); diff --git a/src/debug/dbgentry.c b/src/debug/dbgentry.c index d5bdfb4d07..3d13a0c569 100644 --- a/src/debug/dbgentry.c +++ b/src/debug/dbgentry.c @@ -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 ), diff --git a/src/debug/debugger.prg b/src/debug/debugger.prg index e20029e10b..bf8fdfefb0 100644 --- a/src/debug/debugger.prg +++ b/src/debug/debugger.prg @@ -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 ] + " : " + __dbgValToStr( uValue ) - CASE cType == "L" ; RETURN aVar[ VAR_NAME ] + " : " + __dbgValToStr( uValue ) - CASE cType == "S" ; RETURN aVar[ VAR_NAME ] + " : " + __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 ] + " : " + __dbgValToStr( uValue ) + CASE "L" ; RETURN aVar[ VAR_NAME ] + " : " + __dbgValToStr( uValue ) + CASE "S" ; RETURN aVar[ VAR_NAME ] + " : " + __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"