diff --git a/ChangeLog.txt b/ChangeLog.txt index 0f2d41dc6d..c7739f10d3 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,44 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2014-09-09 20:49 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * include/hbvm.h + * src/vm/hvm.c + + added new HVM function: hb_vmTryEval() + This function tries to execute given block or function + inside BEGIN SEQUENCE / RECOVER oErr / END SEQUENCE statement. + It return HB_TRUE if it was executed without any problem and + HB_FALSE otherwise. Result or RTE object is stored in 1-st + parameter and should be freed by the caller using hb_itemRelese() + + * src/debug/dbgentry.c + ! use hb_vmTryEval() instead of hb_itemDo() to evaluate trace point + expressions. Now debugger does not crash when user sets tracepoint + expression which cannot be evaluated in executed context. + ! allow to use expressions with more then 99 variables + ! added missing protections against GPF when wrong parameters are + passed to __dbg*() functions + * keep original trace and watch point expression for farther + processing + * replaced IS_IDENT_*() macros with HB_IS*IDCHAR() + + added new debuger function: + __dbgGetWatchPoints() -> + contains subarrays describing trace and watch + points: + { , , , } + It was the last function necessary to extract all information + about debugged context from core internals. Now it's possible + to create fully functional standalone debugger without storing + and updating locally any information about debugger state. + All such information can be accessed at any time using __dbg*() + functions. + It should greatly simplify creating 3-rd party debuggers like + HWDebug or HBQTDebug. + + * src/debug/debugger.prg + ! fixed callstack window updating during tracing and stepping. + Tanks to Rolf for reporting the problem. + 2014-09-08 23:40 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * contrib/hbct/ctwin.c ! fixed typo in window area checking when current window is 0 diff --git a/include/hbvm.h b/include/hbvm.h index b31049b3e6..0b7e201ee3 100644 --- a/include/hbvm.h +++ b/include/hbvm.h @@ -127,6 +127,7 @@ extern HB_EXPORT HB_USHORT hb_vmRequestQuery( void ); extern HB_EXPORT HB_BOOL hb_vmRequestReenter( void ); extern HB_EXPORT void hb_vmRequestRestore( void ); extern HB_EXPORT HB_BOOL hb_vmRequestReenterExt( void ); +extern HB_EXPORT HB_BOOL hb_vmTryEval( PHB_ITEM * pResult, PHB_ITEM pItem, HB_ULONG ulPCount, ... ); extern HB_EXPORT HB_BOOL hb_vmIsActive( void ); extern HB_EXPORT HB_BOOL hb_vmIsReady( void ); diff --git a/src/debug/dbgentry.c b/src/debug/dbgentry.c index cd1fe91826..d1f98608cb 100644 --- a/src/debug/dbgentry.c +++ b/src/debug/dbgentry.c @@ -286,6 +286,35 @@ static PHB_ITEM hb_dbgActivateBreakArray( HB_DEBUGINFO * info ) } +static PHB_ITEM hb_dbgActivateWatchArray( HB_DEBUGINFO * info ) +{ + int i, j; + PHB_ITEM pArray = hb_itemArrayNew( info->nWatchPoints ); + + for( i = 0; i < info->nWatchPoints; i++ ) + { + PHB_ITEM pWatch = hb_arrayGetItemPtr( pArray, i + 1 ), xValue; + + for( j = 0; j < info->nTracePoints; j++ ) + { + if( info->aTrace[ j ].nIndex == i ) + break; + } + xValue = hb_dbgEval( info, &info->aWatch[ i ] ); + hb_arrayNew( pWatch, 4 ); + hb_arraySetC( pWatch, 1, info->aWatch[ i ].szExpr ); + hb_arraySetL( pWatch, 2, j < info->nTracePoints ); + hb_arraySetL( pWatch, 3, xValue != NULL ); + if( xValue ) + { + hb_arraySetForward( pWatch, 4, xValue ); + hb_itemRelease( xValue ); + } + } + return pArray; +} + + static PHB_ITEM hb_dbgActivateModuleArray( void ) { PHB_ITEM pArray; @@ -568,20 +597,23 @@ static const char * hb_dbgStripModuleName( const char * szName ) void hb_dbgAddBreak( void * handle, const char * szModule, int nLine, const char * szFunction ) { - HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; - HB_BREAKPOINT * pBreak; + if( szModule || szFunction ) + { + HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; + HB_BREAKPOINT * pBreak; - pBreak = ARRAY_ADD( HB_BREAKPOINT, info->aBreak, info->nBreakPoints ); - if( szModule ) - pBreak->szModule = hb_strdup( hb_dbgStripModuleName( szModule ) ); - else - pBreak->szModule = NULL; - pBreak->nLine = nLine; + pBreak = ARRAY_ADD( HB_BREAKPOINT, info->aBreak, info->nBreakPoints ); + if( szModule ) + pBreak->szModule = hb_strdup( hb_dbgStripModuleName( szModule ) ); + else + pBreak->szModule = NULL; + pBreak->nLine = nLine; - if( szFunction ) - pBreak->szFunction = hb_strdup( szFunction ); - else - pBreak->szFunction = NULL; + if( szFunction ) + pBreak->szFunction = hb_strdup( szFunction ); + else + pBreak->szFunction = NULL; + } } @@ -815,20 +847,23 @@ static void hb_dbgAddVar( int * nVars, HB_VARINFO ** aVars, const char * szName, void hb_dbgAddWatch( void * handle, const char * szExpr, HB_BOOL bTrace ) { - HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; - HB_WATCHPOINT * pWatch; - - pWatch = ARRAY_ADD( HB_WATCHPOINT, info->aWatch, info->nWatchPoints ); - pWatch->szExpr = hb_strdup( szExpr ); - pWatch->pBlock = NULL; - pWatch->nVars = 0; - - if( bTrace ) + if( szExpr ) { - HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints ); + HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; + HB_WATCHPOINT * pWatch; - pTrace->nIndex = info->nWatchPoints - 1; - pTrace->xValue = hb_dbgEval( info, pWatch ); + pWatch = ARRAY_ADD( HB_WATCHPOINT, info->aWatch, info->nWatchPoints ); + pWatch->szExpr = hb_strdup( szExpr ); + pWatch->pBlock = NULL; + pWatch->nVars = 0; + + if( bTrace ) + { + HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints ); + + pTrace->nIndex = info->nWatchPoints - 1; + pTrace->xValue = hb_dbgEval( info, pWatch ); + } } } @@ -981,7 +1016,11 @@ static PHB_ITEM hb_dbgEval( HB_DEBUGINFO * info, HB_WATCHPOINT * watch ) int i; info->bInside = HB_TRUE; - xResult = hb_itemDo( watch->pBlock, 1, aNewVars ); + if( ! hb_vmTryEval( &xResult, watch->pBlock, 1, aNewVars ) ) + { + hb_itemRelease( xResult ); + xResult = NULL; + } info->bInside = bInside; for( i = 0; i < watch->nVars; i++ ) @@ -1022,13 +1061,14 @@ static PHB_ITEM hb_dbgEvalMacro( const char * szExpr, PHB_ITEM pItem ) } -#define IS_IDENT_START( c ) HB_ISFIRSTIDCHAR( ( HB_UCHAR ) ( c ) ) -#define IS_IDENT_CHAR( c ) HB_ISNEXTIDCHAR( ( HB_UCHAR ) ( c ) ) - -static int hb_dbgEvalSubstituteVar( HB_WATCHPOINT * watch, char * szWord, int nStart, int nLen ) +static int hb_dbgEvalSubstituteVar( HB_WATCHPOINT * watch, + char * szWord, int nStart, int nLen, + char ** pszOrig ) { + char buf[ 16 ]; + char * szExpr; + HB_SIZE n; int j; - char * t; for( j = 0; j < watch->nVars; j++ ) { @@ -1041,16 +1081,20 @@ static int hb_dbgEvalSubstituteVar( HB_WATCHPOINT * watch, char * szWord, int nS else hb_xfree( szWord ); - t = ( char * ) hb_xgrab( strlen( watch->szExpr ) - nLen + 9 + 1 ); - memmove( t, watch->szExpr, nStart ); - memmove( t + nStart, "__dbg[", 6 ); - t[ nStart + 6 ] = '0' + ( char ) ( ( j + 1 ) / 10 ); - t[ nStart + 7 ] = '0' + ( char ) ( ( j + 1 ) % 10 ); - t[ nStart + 8 ] = ']'; - hb_strncpy( t + nStart + 9, watch->szExpr + nStart + nLen, strlen( watch->szExpr ) - nLen - nStart ); - hb_xfree( watch->szExpr ); - watch->szExpr = t; - return nStart + 9; + n = strlen( watch->szExpr ); + j = hb_snprintf( buf, sizeof( buf ), "__dbg[%d]", j + 1 ); + szExpr = ( char * ) hb_xgrab( n - nLen + j + 1 ); + memcpy( szExpr, watch->szExpr, nStart ); + memcpy( szExpr + nStart, buf, j ); + memcpy( szExpr + nStart + j, watch->szExpr + nStart + nLen, n - nLen - nStart ); + szExpr[ n + j - nLen ] = '\0'; + if( * pszOrig == NULL ) + * pszOrig = watch->szExpr; + else + hb_xfree( watch->szExpr ); + watch->szExpr = szExpr; + + return nStart + j; } @@ -1059,7 +1103,7 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch ) int i = 0; PHB_ITEM pBlock; HB_BOOL bAfterId = HB_FALSE; - char * s; + char * szBlock, * szOrig = NULL; HB_ISIZ buffsize; watch->nVars = 0; @@ -1067,13 +1111,13 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch ) { char c = watch->szExpr[ i ]; - if( IS_IDENT_START( c ) ) + if( HB_ISFIRSTIDCHAR( c ) ) { int nStart = i, nLen; int j = i; char * szWord; - while( c && IS_IDENT_CHAR( c ) ) + while( c && HB_ISNEXTIDCHAR( c ) ) c = watch->szExpr[ ++j ]; nLen = j - i; @@ -1091,14 +1135,14 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch ) { i += 2; - while( ( c = watch->szExpr[ i ] ) != '\0' && IS_IDENT_CHAR( c ) ) + while( ( c = watch->szExpr[ i ] ) != '\0' && HB_ISNEXTIDCHAR( c ) ) i++; continue; } } szWord = hb_strupr( hb_strndup( watch->szExpr + nStart, nLen ) ); - i = hb_dbgEvalSubstituteVar( watch, szWord, nStart, nLen ); + i = hb_dbgEvalSubstituteVar( watch, szWord, nStart, nLen, &szOrig ); bAfterId = HB_TRUE; continue; } @@ -1128,11 +1172,11 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch ) } if( c == ':' || ( c == '-' && watch->szExpr[ i + 1 ] == '>' && - IS_IDENT_START( watch->szExpr[ i + 2 ] ) ) ) + HB_ISFIRSTIDCHAR( watch->szExpr[ i + 2 ] ) ) ) { if( c == ':' && watch->szExpr[ i + 1 ] == ':' ) { - i = hb_dbgEvalSubstituteVar( watch, hb_strdup( "SELF" ), i, 1 ); + i = hb_dbgEvalSubstituteVar( watch, hb_strdup( "SELF" ), i, 1, &szOrig ); bAfterId = HB_TRUE; continue; } @@ -1142,7 +1186,7 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch ) i++; - while( watch->szExpr[ i ] && IS_IDENT_CHAR( watch->szExpr[ i ] ) ) + while( watch->szExpr[ i ] && HB_ISNEXTIDCHAR( watch->szExpr[ i ] ) ) i++; bAfterId = HB_TRUE; @@ -1189,18 +1233,24 @@ static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch ) buffsize = 8 + strlen( watch->szExpr ) + 1; - s = ( char * ) hb_xgrab( buffsize + 1 ); - hb_strncpy( s, "{|__dbg|", buffsize ); - hb_strncat( s, watch->szExpr, buffsize ); - hb_strncat( s, "}", buffsize ); + szBlock = ( char * ) hb_xgrab( buffsize + 1 ); + hb_strncpy( szBlock, "{|__dbg|", buffsize ); + hb_strncat( szBlock, watch->szExpr, buffsize ); + hb_strncat( szBlock, "}", buffsize ); pBlock = hb_itemNew( NULL ); - if( ! hb_dbgEvalMacro( s, pBlock ) ) + if( ! hb_dbgEvalMacro( szBlock, pBlock ) ) { hb_itemRelease( pBlock ); pBlock = NULL; } - hb_xfree( s ); + hb_xfree( szBlock ); + + if( szOrig != NULL ) + { + hb_xfree( watch->szExpr ); + watch->szExpr = szOrig; + } return pBlock; } @@ -1417,34 +1467,38 @@ static int hb_dbgIsBreakPoint( HB_DEBUGINFO * info, const char * szModule, int n HB_BOOL hb_dbgIsValidStopLine( void * handle, const char * szModule, int nLine ) { HB_BOOL fResult = HB_FALSE; - HB_ISIZ nModules; - HB_ISIZ i; + + if( szModule ) + { + HB_ISIZ nModules; + HB_ISIZ i; #if 0 - HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; + HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; #endif - HB_SYMBOL_UNUSED( handle ); + HB_SYMBOL_UNUSED( handle ); - szModule = hb_dbgStripModuleName( szModule ); + szModule = hb_dbgStripModuleName( szModule ); - HB_DBGCOMMON_LOCK(); - nModules = hb_itemSize( s_common.pStopLines ); - for( i = 1; i <= nModules; i++ ) - { - PHB_ITEM pEntry = hb_arrayGetItemPtr( s_common.pStopLines, i ); - - if( FILENAME_EQUAL( hb_arrayGetCPtr( pEntry, 1 ), szModule ) ) + HB_DBGCOMMON_LOCK(); + nModules = hb_itemSize( s_common.pStopLines ); + for( i = 1; i <= nModules; i++ ) { - int nMin = hb_arrayGetNL( pEntry, 2 ); - int nOfs = nLine - nMin; + PHB_ITEM pEntry = hb_arrayGetItemPtr( s_common.pStopLines, i ); - if( nOfs >= 0 && ( HB_SIZE ) ( nOfs >> 3 ) < hb_arrayGetCLen( pEntry, 3 ) ) - fResult = ( hb_arrayGetCPtr( pEntry, 3 )[ nOfs >> 3 ] & ( 1 << ( nOfs & 0x07 ) ) ) != 0; + if( FILENAME_EQUAL( hb_arrayGetCPtr( pEntry, 1 ), szModule ) ) + { + int nMin = hb_arrayGetNL( pEntry, 2 ); + int nOfs = nLine - nMin; - break; + if( nOfs >= 0 && ( HB_SIZE ) ( nOfs >> 3 ) < hb_arrayGetCLen( pEntry, 3 ) ) + fResult = ( hb_arrayGetCPtr( pEntry, 3 )[ nOfs >> 3 ] & ( 1 << ( nOfs & 0x07 ) ) ) != 0; + + break; + } } + HB_DBGCOMMON_UNLOCK(); } - HB_DBGCOMMON_UNLOCK(); return fResult; } @@ -1559,11 +1613,14 @@ void hb_dbgSetToCursor( void * handle, const char * szModule, int nLine ) { HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; - szModule = hb_dbgStripModuleName( szModule ); + if( szModule ) + { + szModule = hb_dbgStripModuleName( szModule ); - info->bToCursor = HB_TRUE; - info->szToCursorModule = hb_strdup( szModule ); - info->nToCursorLine = nLine; + info->bToCursor = HB_TRUE; + info->szToCursorModule = hb_strdup( szModule ); + info->nToCursorLine = nLine; + } } @@ -1579,31 +1636,35 @@ void hb_dbgSetTrace( void * handle ) void hb_dbgSetWatch( void * handle, int nWatch, const char * szExpr, HB_BOOL bTrace ) { HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; - HB_WATCHPOINT * pWatch = &info->aWatch[ nWatch ]; - int i; - hb_dbgClearWatch( pWatch ); - pWatch->szExpr = hb_strdup( szExpr ); - pWatch->pBlock = NULL; - for( i = 0; i < info->nTracePoints; i++ ) + if( nWatch >= 0 && nWatch < info->nWatchPoints && szExpr ) { - HB_TRACEPOINT * pTrace = &info->aTrace[ i ]; + HB_WATCHPOINT * pWatch = &info->aWatch[ nWatch ]; + int i; - if( pTrace->nIndex == nWatch ) + hb_dbgClearWatch( pWatch ); + pWatch->szExpr = hb_strdup( szExpr ); + pWatch->pBlock = NULL; + for( i = 0; i < info->nTracePoints; i++ ) { - if( pTrace->xValue ) - hb_itemRelease( pTrace->xValue ); + HB_TRACEPOINT * pTrace = &info->aTrace[ i ]; - ARRAY_DEL( HB_TRACEPOINT, info->aTrace, info->nTracePoints, i ); - break; + if( pTrace->nIndex == nWatch ) + { + if( pTrace->xValue ) + hb_itemRelease( pTrace->xValue ); + + ARRAY_DEL( HB_TRACEPOINT, info->aTrace, info->nTracePoints, i ); + break; + } } - } - if( bTrace ) - { - HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints ); + if( bTrace ) + { + HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints ); - pTrace->nIndex = nWatch; - pTrace->xValue = hb_dbgEval( info, pWatch ); + pTrace->nIndex = nWatch; + pTrace->xValue = hb_dbgEval( info, pWatch ); + } } } @@ -1738,9 +1799,9 @@ HB_FUNC( __DBGGETEXPRVALUE ) PHB_ITEM pItem; if( HB_ISCHAR( 2 ) ) - pItem = hb_dbgGetExpressionValue( hb_parptr( 1 ), hb_parc( 2 ) ); + pItem = hb_dbgGetExpressionValue( ptr, hb_parc( 2 ) ); else - pItem = hb_dbgGetWatchValue( hb_parptr( 1 ), hb_parni( 2 ) - 1 ); + pItem = hb_dbgGetWatchValue( ptr, hb_parni( 2 ) - 1 ); if( pItem ) { @@ -1787,10 +1848,11 @@ HB_FUNC( __DBGDELBREAK ) HB_FUNC( __DBGISBREAK ) { void * ptr = hb_parptr( 1 ); + const char * szModule = hb_parc( 2 ); - if( ptr ) + if( ptr && szModule ) hb_retni( hb_dbgIsBreakPoint( ( HB_DEBUGINFO * ) ptr, - hb_dbgStripModuleName( hb_parc( 2 ) ), + hb_dbgStripModuleName( szModule ), hb_parni( 3 ) ) ); } @@ -1834,6 +1896,14 @@ HB_FUNC( __DBGCNTWATCH ) hb_retni( hb_dbgCountWatch( ptr ) ); } +HB_FUNC( __DBGGETWATCHPOINTS ) +{ + void * ptr = hb_parptr( 1 ); + + if( ptr ) + hb_itemReturnRelease( hb_dbgActivateWatchArray( ( HB_DEBUGINFO * ) ptr ) ); +} + HB_FUNC( __DBGGETMODULENAME ) { void * ptr = hb_parptr( 1 ); diff --git a/src/debug/debugger.prg b/src/debug/debugger.prg index bc7cdc5f34..0ba4143193 100644 --- a/src/debug/debugger.prg +++ b/src/debug/debugger.prg @@ -444,6 +444,9 @@ METHOD PROCEDURE Activate() CLASS HBDebugger ENDIF lFirst := .T. ENDIF + IF ::lShowCallStack + ::oWndStack:Show() + ENDIF ::LoadVars() ::ShowVars() diff --git a/src/vm/hvm.c b/src/vm/hvm.c index fdcd4d32a2..5008c444d2 100644 --- a/src/vm/hvm.c +++ b/src/vm/hvm.c @@ -93,6 +93,7 @@ HB_FUNC_EXTERN( SYSINIT ); +HB_FUNC_EXTERN( BREAK ); /* PCode functions */ @@ -255,7 +256,9 @@ static const char * s_vm_pszLinkedMain = NULL; /* name of startup function set b /* virtual machine state */ -HB_SYMB hb_symEval = { "EVAL", { HB_FS_PUBLIC }, { hb_vmDoBlock }, NULL }; /* symbol to evaluate codeblocks */ +HB_SYMB hb_symEval = { "EVAL", { HB_FS_PUBLIC }, { hb_vmDoBlock }, NULL }; /* symbol to evaluate codeblocks */ +static HB_SYMB s_symBreak = { "BREAK", { HB_FS_PUBLIC }, { HB_FUNCNAME( BREAK ) }, NULL }; /* symbol to generate break */ +static PHB_ITEM s_breakBlock = NULL; static HB_BOOL s_fHVMActive = HB_FALSE; /* is HVM ready for PCODE executing */ static HB_BOOL s_fDoExitProc = HB_TRUE; /* execute EXIT procedures */ @@ -282,6 +285,41 @@ static PHB_FUNC_LIST s_InitFunctions = NULL; static PHB_FUNC_LIST s_ExitFunctions = NULL; static PHB_FUNC_LIST s_QuitFunctions = NULL; +static PHB_ITEM hb_breakBlock( void ) +{ + if( s_breakBlock == NULL ) + { + static const HB_BYTE s_pCode[ 8 ] = { + HB_P_PUSHFUNCSYM, 0, 0, /* BREAK */ + HB_P_PUSHLOCALNEAR, 1, /* oErr */ + HB_P_FUNCTIONSHORT, 1, + HB_P_ENDBLOCK }; + + s_breakBlock = hb_itemNew( NULL ); + s_breakBlock->item.asBlock.value = + hb_codeblockNew( s_pCode, /* pcode buffer */ + 0, /* number of referenced local variables */ + NULL, /* table with referenced local variables */ + &s_symBreak, + sizeof( s_pCode ) ); + s_breakBlock->type = HB_IT_BLOCK; + s_breakBlock->item.asBlock.paramcnt = 1; + s_breakBlock->item.asBlock.lineno = 0; + s_breakBlock->item.asBlock.hclass = 0; + s_breakBlock->item.asBlock.method = 0; + } + return s_breakBlock; +} + +static void hb_breakBlockRelease( void ) +{ + if( s_breakBlock != NULL ) + { + hb_itemRelease( s_breakBlock ); + s_breakBlock = NULL; + } +} + static void hb_vmAddModuleFunction( PHB_FUNC_LIST * pLstPtr, HB_INIT_FUNC pFunc, void * cargo ) { PHB_FUNC_LIST pLst = ( PHB_FUNC_LIST ) hb_xgrab( sizeof( HB_FUNC_LIST ) ); @@ -1010,10 +1048,13 @@ void hb_vmInit( HB_BOOL bStartMainProc ) hb_cmdargUpdate(); hb_clsInit(); /* initialize Classy/OO system */ - hb_errInit(); - /* initialize dynamic symbol for evaluating codeblocks */ + hb_errInit(); + hb_breakBlock(); + + /* initialize dynamic symbol for evaluating codeblocks and break function */ hb_symEval.pDynSym = hb_dynsymGetCase( hb_symEval.szName ); + s_symBreak.pDynSym = hb_dynsymGetCase( s_symBreak.szName ); hb_conInit(); @@ -1188,6 +1229,7 @@ int hb_vmQuit( void ) /* release thread specific data */ hb_stackDestroyTSD(); + hb_breakBlockRelease(); hb_errExit(); hb_clsReleaseAll(); @@ -8947,6 +8989,84 @@ HB_BOOL hb_vmRequestReenterExt( void ) return HB_TRUE; } +HB_BOOL hb_vmTryEval( PHB_ITEM * pResult, PHB_ITEM pItem, HB_ULONG ulPCount, ... ) +{ + HB_BOOL fResult; + + HB_TRACE( HB_TR_DEBUG, ( "hb_vmTryEval(%p, %lu)", pItem, ulPCount ) ); + + fResult = HB_FALSE; + *pResult = NULL; + if( s_fHVMActive ) + { + PHB_SYMB pSymbol = NULL; + + if( HB_IS_STRING( pItem ) ) + { + PHB_DYNS pDynSym = hb_dynsymFindName( pItem->item.asString.value ); + + if( pDynSym ) + { + pSymbol = pDynSym->pSymbol; + pItem = NULL; + } + } + else if( HB_IS_SYMBOL( pItem ) ) + { + pSymbol = pItem->item.asSymbol.value; + pItem = NULL; + } + else if( HB_IS_BLOCK( pItem ) ) + { + pSymbol = &hb_symEval; + } + + if( pSymbol && hb_vmRequestReenter() ) + { + hb_xvmSeqBegin(); + hb_vmPush( hb_breakBlock() ); + hb_vmSeqBlock(); + + hb_vmPushSymbol( pSymbol ); + if( pItem ) + hb_vmPush( pItem ); + else + hb_vmPushNil(); + + if( ulPCount ) + { + HB_ULONG ulParam; + va_list va; + va_start( va, ulPCount ); + for( ulParam = 1; ulParam <= ulPCount; ulParam++ ) + hb_vmPush( va_arg( va, PHB_ITEM ) ); + va_end( va ); + } + if( pItem ) + hb_vmSend( ( HB_USHORT ) ulPCount ); + else + hb_vmProc( ( HB_USHORT ) ulPCount ); + + hb_stackPop(); + if( hb_xvmSeqEndTest() ) + { + hb_xvmSeqRecover(); + *pResult = hb_itemNew( NULL ); + hb_itemMove( *pResult, hb_stackItemFromTop( -1 ) ); + hb_stackDec(); + hb_stackSetActionRequest( 0 ); + } + else + { + *pResult = hb_itemNew( hb_stackReturnItem() ); + fResult = HB_TRUE; + } + hb_vmRequestRestore(); + } + } + return fResult; +} + HB_BOOL hb_vmIsActive( void ) { HB_TRACE( HB_TR_DEBUG, ( "hb_vmIsActive()" ) );