From f1fa94f3c4a48ec76e7f9eea435e3ba95475c4ce Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Tue, 25 Jul 2006 09:03:06 +0000 Subject: [PATCH] 2006-07-25 10:35 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/contrib/rdd_ads/ads1.c ! make GOTOP() when new index is open and is set as control one * harbour/include/hbcomp.h * harbour/include/hbstack.h * harbour/include/hbxvm.h * harbour/source/compiler/gencc.c * harbour/source/compiler/hblbl.c * harbour/source/vm/classes.c * harbour/source/vm/estack.c * harbour/source/vm/hvm.c * harbour/source/vm/itemapi.c * added automatic destructors for FOR EACH and WITH OBJECT statement * s_lWithObjectBase changed to lWithObjectBase hb_stack membera * added hb_stackWithObject*() functions/macros to manipulate WITH OBJECT offset/item * removed setting/restoring lForEach and lWithObject in functions preamble/postamble ! fixed restoring s_lRecoverBase on HB_QUIT_REQUESTED ! fixed possible GPF on enumerators copping * moved FOR EACH / WITH OBJECT massages suport from HVM to classy.c ! fixed access to first stack item in hb_vmIsLocalRef() * harbour/TODO - removed note about hb_objGetMethod() - it's already addressed --- harbour/TODO | 7 - harbour/contrib/rdd_ads/ads1.c | 1 + harbour/include/hbcomp.h | 2 - harbour/include/hbstack.h | 7 + harbour/include/hbxvm.h | 15 +- harbour/source/compiler/gencc.c | 26 +- harbour/source/compiler/hblbl.c | 22 +- harbour/source/vm/classes.c | 82 ++++++- harbour/source/vm/estack.c | 24 +- harbour/source/vm/hvm.c | 422 ++++++++++++++------------------ harbour/source/vm/itemapi.c | 4 + 11 files changed, 319 insertions(+), 293 deletions(-) diff --git a/harbour/TODO b/harbour/TODO index bea1da3a11..2b525156c5 100644 --- a/harbour/TODO +++ b/harbour/TODO @@ -223,13 +223,6 @@ Status...: Open. *** -Assign to: ??? -Detail...: Remove generation of runtime error inside 'hb_objGetMethod' - for built-in classes (GET, TBROWSE,...) -Status...: Open. - -*** - Assign to: Przemek Detail...: Clean RDD code to be safe for return from RT errors Status...: Open. diff --git a/harbour/contrib/rdd_ads/ads1.c b/harbour/contrib/rdd_ads/ads1.c index 2c62e63c3e..99ff6d9785 100644 --- a/harbour/contrib/rdd_ads/ads1.c +++ b/harbour/contrib/rdd_ads/ads1.c @@ -3068,6 +3068,7 @@ static ERRCODE adsOrderListAdd( ADSAREAP pArea, LPDBORDERINFO pOrderInfo ) if( !pArea->hOrdCurrent ) { pArea->hOrdCurrent = ahIndex[0]; + return SELF_GOTOP( ( AREAP ) pArea ); } return SUCCESS; diff --git a/harbour/include/hbcomp.h b/harbour/include/hbcomp.h index 35a8cc82a1..41e7dd47ea 100644 --- a/harbour/include/hbcomp.h +++ b/harbour/include/hbcomp.h @@ -259,8 +259,6 @@ typedef struct _HB_LABEL_INFO BOOL fVerbose; BOOL fSetSeqBegin; BOOL fCondJump; - BOOL fForEach; - BOOL fWithObject; ULONG * pulLabels; } HB_LABEL_INFO, * PHB_LABEL_INFO; diff --git a/harbour/include/hbstack.h b/harbour/include/hbstack.h index dc871eda89..adbdc0e7a0 100644 --- a/harbour/include/hbstack.h +++ b/harbour/include/hbstack.h @@ -75,6 +75,7 @@ typedef struct PHB_ITEM * pBase; /* stack frame position for the current function call */ PHB_ITEM * pEvalBase; /* stack frame position for the evaluated codeblock */ int iStatics; /* statics base for the current function call */ + LONG lWithObject; /* stack offset to base current WITH OBJECT item */ char szDate[ 9 ]; /* last returned date from _pards() yyyymmdd format */ } HB_STACK; @@ -104,6 +105,9 @@ typedef struct #define hb_stackGetStaticsBase( ) ( hb_stack.iStatics ) #define hb_stackSetStaticsBase( n ) do { hb_stack.iStatics = ( n ); } while ( 0 ) #define hb_stackItemBasePtr( ) ( &hb_stack.pItems ) +#define hb_stackWithObjectItem( ) ( hb_stack.lWithObject ? * ( hb_stack.pItems + hb_stack.lWithObject ) : NULL ) +#define hb_stackWithObjectOffset( n ) ( hb_stack.lWithObject ) +#define hb_stackWithObjectSetOffset( n ) do { hb_stack.lWithObject = ( n ); } while( 0 ) #define hb_stackAllocItem( ) ( ( ++hb_stack.pPos == hb_stack.pEnd ? \ hb_stackIncrease() : (void) 0 ), \ @@ -160,6 +164,9 @@ extern char * hb_stackDateBuffer( void ); extern void hb_stackSetStaticsBase( int iBase ); extern int hb_stackGetStaticsBase( void ); extern PHB_ITEM ** hb_stackItemBasePtr( void ); +extern PHB_ITEM hb_stackWithObjectItem( void ); +extern LONG hb_stackWithObjectOffset( void ); +extern void hb_stackWithObjectSetOffset( LONG ); extern void hb_stackDec( void ); /* pops an item from the stack without clearing it's contents */ extern void hb_stackPop( void ); /* pops an item from the stack */ diff --git a/harbour/include/hbxvm.h b/harbour/include/hbxvm.h index 948b5886da..0d5a62f9c9 100644 --- a/harbour/include/hbxvm.h +++ b/harbour/include/hbxvm.h @@ -75,17 +75,18 @@ HB_EXTERN_BEGIN extern HB_EXPORT void hb_xvmExitProc( ULONG ulPrivateBase ); extern HB_EXPORT void hb_xvmSeqBegin( void ); -extern HB_EXPORT BOOL hb_xvmSeqEnd( LONG * ); -extern HB_EXPORT BOOL hb_xvmSeqRecover( LONG * ); +extern HB_EXPORT BOOL hb_xvmSeqEnd( void ); +extern HB_EXPORT BOOL hb_xvmSeqEndTest( void ); +extern HB_EXPORT BOOL hb_xvmSeqRecover( void ); -extern HB_EXPORT BOOL hb_xvmEnumStart( BYTE, BYTE, LONG * ); /* prepare FOR EACH loop */ +extern HB_EXPORT BOOL hb_xvmEnumStart( BYTE, BYTE ); /* prepare FOR EACH loop */ extern HB_EXPORT BOOL hb_xvmEnumNext( void ); /* increment FOR EACH loop counter */ extern HB_EXPORT BOOL hb_xvmEnumPrev( void ); /* decrement FOR EACH loop counter */ -extern HB_EXPORT void hb_xvmEnumEnd( LONG * ); /* rewind the stack after FOR EACH loop counter */ +extern HB_EXPORT void hb_xvmEnumEnd( void ); /* rewind the stack after FOR EACH loop counter */ -extern HB_EXPORT void hb_xvmWithObjectStart( void ); /* prepare WITH OBJECT staement */ -extern HB_EXPORT void hb_xvmWithObjectEnd( void ); /* rewind the stack after normal WITH OBJECT */ -extern HB_EXPORT LONG hb_xvmWithObjectBase( LONG * ); /* get/restore previous WITH OBJECT stack frame */ +extern HB_EXPORT void hb_xvmWithObjectStart( void ); /* prepare WITH OBJECT statement */ +extern HB_EXPORT void hb_xvmWithObjectEnd( void ); /* rewind the stack after normal WITH OBJECT */ +extern HB_EXPORT void hb_xvmWithObjectMessage( PHB_SYMB ); /* send WITH OBJECT message to current WITH OBJECT control variable */ extern HB_EXPORT void hb_xvmSetLine( USHORT uiLine ); /* set .prg line number information */ diff --git a/harbour/source/compiler/gencc.c b/harbour/source/compiler/gencc.c index 8c4839cc09..288e698528 100644 --- a/harbour/source/compiler/gencc.c +++ b/harbour/source/compiler/gencc.c @@ -1253,11 +1253,9 @@ static HB_GENC_FUNC( hb_p_seqend ) HB_GENC_LABEL(); if( lOffset == 4 ) /* no RECOVER clasue */ - fprintf( cargo->yyc, "\t} while( 0 );\n\tif( hb_xvmSeqEnd( %s ) ) break;\n", - cargo->fForEach ? "&lForEachBase" : "NULL" ); + fprintf( cargo->yyc, "\t} while( 0 );\n\tif( hb_xvmSeqEnd() ) break;\n" ); else /* RECOVER exists */ - fprintf( cargo->yyc, "\tif( hb_xvmSeqEnd( %s ) ) break;\n\tgoto lab%05ld;\n\t} while( 0 );\n", - cargo->fForEach ? "&lForEachBase" : "NULL", + fprintf( cargo->yyc, "\tif( hb_xvmSeqEndTest() ) break;\n\tgoto lab%05ld;\n\t} while( 0 );\n", HB_GENC_GETLABEL( lPCodePos + lOffset ) ); return 4; } @@ -1266,8 +1264,7 @@ static HB_GENC_FUNC( hb_p_seqrecover ) { HB_GENC_LABEL(); - fprintf( cargo->yyc, "\tif( hb_xvmSeqRecover( %s ) ) break;\n", - cargo->fForEach ? "&lForEachBase" : "NULL" ); + fprintf( cargo->yyc, "\tif( hb_xvmSeqRecover() ) break;\n" ); return 1; } @@ -1380,7 +1377,7 @@ static HB_GENC_FUNC( hb_p_enumstart ) { HB_GENC_LABEL(); - fprintf( cargo->yyc, "\tif( hb_xvmEnumStart( %d, %d, &lForEachBase ) ) break;\n", + fprintf( cargo->yyc, "\tif( hb_xvmEnumStart( %d, %d ) ) break;\n", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); return 3; } @@ -1405,7 +1402,7 @@ static HB_GENC_FUNC( hb_p_enumend ) { HB_GENC_LABEL(); - fprintf( cargo->yyc, "\thb_xvmEnumEnd( &lForEachBase );\n" ); + fprintf( cargo->yyc, "\thb_xvmEnumEnd();\n" ); return 1; } @@ -1572,9 +1569,8 @@ static HB_GENC_FUNC( hb_p_withobjectmessage ) { HB_GENC_LABEL(); - fprintf( cargo->yyc, "\thb_xvmPushSymbol( symbols + %hu );\n", + fprintf( cargo->yyc, "\thb_xvmWithObjectMessage( symbols + %hu );\n", HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ) ); - fprintf( cargo->yyc, "\thb_vmPush( hb_stackItem( s_lWithObjectBase ) );\n" ); return 3; } @@ -1746,7 +1742,7 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) label_info.yyc = yyc; label_info.fVerbose = ( hb_comp_iGenCOutput == HB_COMPGENC_VERBOSE ); label_info.fSetSeqBegin = FALSE; - label_info.fCondJump = label_info.fForEach = label_info.fWithObject = FALSE; + label_info.fCondJump = FALSE; if( pFunc->lPCodePos == 0 ) label_info.pulLabels = NULL; else @@ -1758,10 +1754,6 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) fprintf( yyc, "{\n" ); fprintf( yyc, " ULONG ulPrivateBase = hb_memvarGetPrivatesBase();\n" ); - if( label_info.fForEach ) - fprintf( yyc, " LONG lForEachBase = 0;\n" ); - if( label_info.fWithObject ) - fprintf( yyc, " LONG lWithObjectBase = hb_xvmWithObjectBase(NULL);\n" ); if( label_info.fCondJump ) fprintf( yyc, " BOOL fValue;\n" ); fprintf( yyc, " do {\n" ); @@ -1769,10 +1761,6 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) hb_compPCodeEval( pFunc, ( HB_PCODE_FUNC_PTR * ) s_verbose_table, ( void * ) &label_info ); fprintf( yyc, " } while ( 0 );\n" ); - if( label_info.fForEach ) - fprintf( yyc, " while( lForEachBase )\n {\n\thb_stackRemove( lForEachBase );\n\thb_xvmEnumEnd( &lForEachBase );\n }\n" ); - if( label_info.fWithObject ) - fprintf( yyc, " hb_xvmWithObjectBase( &lWithObjectBase );\n" ); fprintf( yyc, " hb_xvmExitProc( ulPrivateBase );\n" ); fprintf( yyc, "}\n" ); diff --git a/harbour/source/compiler/hblbl.c b/harbour/source/compiler/hblbl.c index 2d90719fd0..01bf7dadb3 100644 --- a/harbour/source/compiler/hblbl.c +++ b/harbour/source/compiler/hblbl.c @@ -166,24 +166,6 @@ static HB_LABEL_FUNC( hb_p_seqend ) return 4; } -static HB_LABEL_FUNC( hb_p_enumstart ) -{ - HB_SYMBOL_UNUSED( pFunc ); - HB_SYMBOL_UNUSED( lPCodePos ); - - cargo->fForEach = TRUE; - return 3; -} - -static HB_LABEL_FUNC( hb_p_withobjectstart ) -{ - HB_SYMBOL_UNUSED( pFunc ); - HB_SYMBOL_UNUSED( lPCodePos ); - - cargo->fWithObject = TRUE; - return 1; -} - /* NOTE: The order of functions have to match the order of opcodes * mnemonics */ @@ -320,7 +302,7 @@ static PHB_LABEL_FUNC s_GenLabelFuncTable[ HB_P_LAST_PCODE ] = NULL, /* HB_P_LOCALNEARADDINT, */ NULL, /* HB_P_MACROPUSHREF */ NULL, /* HB_P_PUSHLONGLONG */ - hb_p_enumstart, /* HB_P_ENUMSTART */ + NULL, /* HB_P_ENUMSTART */ NULL, /* HB_P_ENUMNEXT */ NULL, /* HB_P_ENUMPREV */ NULL, /* HB_P_ENUMEND */ @@ -335,7 +317,7 @@ static PHB_LABEL_FUNC s_GenLabelFuncTable[ HB_P_LAST_PCODE ] = NULL, /* HB_P_MINUSEQ */ NULL, /* HB_P_MULTEQ */ NULL, /* HB_P_DIVEQ */ - hb_p_withobjectstart, /* HB_P_WITHOBJECTSTART */ + NULL, /* HB_P_WITHOBJECTSTART */ NULL, /* HB_P_WITHOBJECTMESSAGE */ NULL /* HB_P_WITHOBJECTEND */ }; diff --git a/harbour/source/vm/classes.c b/harbour/source/vm/classes.c index e379a4815a..60c8f0ec7d 100644 --- a/harbour/source/vm/classes.c +++ b/harbour/source/vm/classes.c @@ -199,6 +199,7 @@ static HARBOUR hb___msgEvalInline( void ); static HARBOUR hb___msgVirtual( void ); static HARBOUR hb___msgSuper( void ); static HARBOUR hb___msgNoMethod( void ); +static HARBOUR hb___msgNull( void ); static HARBOUR hb___msgClsH( void ); static HARBOUR hb___msgClsName( void ); @@ -259,6 +260,14 @@ static HB_SYMB s___msgEval = { "EVAL", {HB_FS_MESSAGE}, {hb___m static HB_SYMB s___msgClsParent = { "ISDERIVEDFROM", {HB_FS_MESSAGE}, {hb___msgClsParent}, NULL }; static HB_SYMB s___msgClass = { "CLASS", {HB_FS_MESSAGE}, {hb___msgClass}, NULL }; */ +/* Default enumerator methods (FOR EACH) */ +static HB_SYMB s___msgEnumIndex = { "__ENUMINDEX", {HB_FS_MESSAGE}, {hb___msgNull}, NULL }; +static HB_SYMB s___msgEnumBase = { "__ENUMBASE", {HB_FS_MESSAGE}, {hb___msgNull}, NULL }; +static HB_SYMB s___msgEnumValue = { "__ENUMVALUE", {HB_FS_MESSAGE}, {hb___msgNull}, NULL }; + +/* WITH OBJECT base value access/asign methods (:__withobject) */ +static HB_SYMB s___msgWithObjectPush = { "__WITHOBJECT", {HB_FS_MESSAGE}, {hb___msgNull}, NULL }; +static HB_SYMB s___msgWithObjectPop = { "___WITHOBJECT", {HB_FS_MESSAGE}, {hb___msgNull}, NULL }; static PCLASS s_pClasses = NULL; static USHORT s_uiClasses = 0; @@ -369,6 +378,12 @@ void hb_clsInit( void ) s___msgClsParent.pDynSym = hb_dynsymGetCase( s___msgClsParent.szName ); s___msgClass.pDynSym = hb_dynsymGetCase( s___msgClass.szName ); */ + s___msgEnumIndex.pDynSym = hb_dynsymGetCase( s___msgEnumIndex.szName ); + s___msgEnumBase.pDynSym = hb_dynsymGetCase( s___msgEnumBase.szName ); + s___msgEnumValue.pDynSym = hb_dynsymGetCase( s___msgEnumValue.szName ); + + s___msgWithObjectPush.pDynSym = hb_dynsymGetCase( s___msgWithObjectPush.szName ); + s___msgWithObjectPop.pDynSym = hb_dynsymGetCase( s___msgWithObjectPop.szName ); } /* @@ -887,7 +902,7 @@ PHB_SYMB hb_objGetMethod( PHB_ITEM pObject, PHB_SYMB pMessage, BOOL * pfPopSuper pMsg = pMessage->pDynSym; - if( pObject->type == HB_IT_ARRAY ) + if( HB_IS_ARRAY( pObject ) ) { USHORT uiClass = pObject->item.asArray.value->uiClass; @@ -921,16 +936,70 @@ PHB_SYMB hb_objGetMethod( PHB_ITEM pObject, PHB_SYMB pMessage, BOOL * pfPopSuper } } } - else if( pObject->type == HB_IT_BLOCK ) + else if( HB_IS_BLOCK( pObject ) ) { if( pMessage == &hb_symEval ) return pMessage; else if( pMsg == s___msgEval.pDynSym ) return &hb_symEval; } + else if( HB_IS_BYREF( pObject ) ) + { + /* method of enumerator variable from FOR EACH statement + */ + PHB_ITEM pEnum = hb_itemUnRefOnce( pObject ); + + if( HB_IS_ENUM( pEnum ) ) + { + /* + * Do actions here - we alrady have unreferences pEnum so + * it will be a little bit faster but in the future it' + * s possible that I'll move it to separate funcions when + * I'll add enumerators overloading. [druzus] + */ + if( pMsg == s___msgEnumIndex.pDynSym ) + { + hb_itemPutNL( hb_stackReturnItem(), pEnum->item.asEnum.offset ); + return &s___msgEnumIndex; + } + else if( pMsg == s___msgEnumBase.pDynSym ) + { + hb_itemCopy( hb_stackReturnItem(), pEnum->item.asEnum.basePtr ); + return &s___msgEnumBase; + } + else if( pMsg == s___msgEnumValue.pDynSym ) + { + hb_itemCopy( hb_stackReturnItem(), hb_itemUnRefOnce( pEnum ) ); + return &s___msgEnumValue; + } + } + } /* Default messages here */ - if( pMsg == s___msgClassName.pDynSym ) + + if( pMsg == s___msgWithObjectPush.pDynSym ) + { + PHB_ITEM pItem = hb_stackWithObjectItem(); + if( pItem ) + { + /* push current WITH OBJECT object */ + hb_itemCopy( hb_stackReturnItem(), pItem ); + return &s___msgWithObjectPush; + } + } + else if( pMsg == s___msgWithObjectPop.pDynSym ) + { + PHB_ITEM pItem = hb_stackWithObjectItem(); + if( pItem ) + { + /* replace current WITH OBJECT object */ + hb_itemCopy( pItem, hb_stackItemFromBase( 1 ) ); + hb_itemCopy( hb_stackReturnItem(), pItem ); + return &s___msgWithObjectPop; + } + } + + else if( pMsg == s___msgClassName.pDynSym ) return &s___msgClassName; else if( pMsg == s___msgClassH.pDynSym ) @@ -949,7 +1018,7 @@ PHB_SYMB hb_objGetMethod( PHB_ITEM pObject, PHB_SYMB pMessage, BOOL * pfPopSuper else if( pMsg == s___msgClass.pDynSym ) return &s___msgClass; */ - else if( pfPopSuper ) + if( pfPopSuper ) { if( pClass && pClass->pFunError ) return pClass->pFunError; @@ -2612,6 +2681,11 @@ static HARBOUR hb___msgVirtual( void ) ; } +static HARBOUR hb___msgNull( void ) +{ + ; +} + /* NOTE: Used by the preprocessor to implement Classy compatibility to Harbour Receive an variable number of param and return an array of it. diff --git a/harbour/source/vm/estack.c b/harbour/source/vm/estack.c index d14026136c..8a0e2342b6 100644 --- a/harbour/source/vm/estack.c +++ b/harbour/source/vm/estack.c @@ -357,6 +357,25 @@ void hb_stackSetStaticsBase( int iBase ) hb_stack.iStatics = iBase; } +#undef hb_stackWithObjectItem +PHB_ITEM hb_stackWithObjectItem( void ) +{ + return hb_stack.lWithObject ? + * ( hb_stack.pItems + hb_stack.lWithObject ) : NULL; +} + +#undef hb_stackWithObjectOffset +LONG hb_stackWithObjectOffset( void ) +{ + return hb_stack.lWithObject; +} + +#undef hb_stackWithObjectSetOffset +void hb_stackWithObjectSetOffset( LONG lOffset ) +{ + hb_stack.lWithObject = lOffset; +} + #undef hb_stackItemBasePtr PHB_ITEM ** hb_stackItemBasePtr( void ) { @@ -497,12 +516,13 @@ void hb_vmIsLocalRef( void ) { /* the eval stack is not cleared yet */ HB_ITEM_PTR * pItem = hb_stack.pPos - 1; - while( pItem != hb_stack.pItems ) + + do { if( HB_IS_GCITEM( *pItem ) ) hb_gcItemRef( *pItem ); - --pItem; } + while( --pItem >= hb_stack.pItems ); } } diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index bd26466a44..8e1175b1a1 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -122,10 +122,11 @@ static void hb_vmGreater( void ); /* checks if the latest - 1 value i static void hb_vmGreaterEqual( void ); /* checks if the latest - 1 value is greater than or equal the latest, removes both and leaves result */ static void hb_vmInstring( void ); /* check whether string 1 is contained in string 2 */ static void hb_vmForTest( void ); /* test for end condition of for */ -static LONG hb_vmEnumStart( BYTE, BYTE, LONG ); /* prepare FOR EACH loop */ +static void hb_vmWithObjectStart( void ); /* prepare WITH OBJECT block */ +static void hb_vmEnumStart( BYTE, BYTE ); /* prepare FOR EACH loop */ static void hb_vmEnumNext( void ); /* increment FOR EACH loop counter */ static void hb_vmEnumPrev( void ); /* decrement FOR EACH loop counter */ -static LONG hb_vmEnumEnd( void ); /* rewind the stack after FOR EACH loop counter */ +static void hb_vmEnumEnd( void ); /* rewind the stack after FOR EACH loop counter */ static LONG hb_vmSwitch( const BYTE * pCode, LONG, USHORT ); /* make a SWITCH statement */ /* Operators (logical) */ @@ -221,11 +222,6 @@ BOOL hb_bTracePrgCalls = FALSE; /* prg tracing is off */ /* virtual machine state */ HB_SYMB hb_symEval = { "__EVAL", {HB_FS_PUBLIC}, {hb_vmDoBlock}, NULL }; /* symbol to evaluate codeblocks */ -HB_SYMB hb_symEnumIndex = { "__ENUMINDEX", {HB_FS_MESSAGE}, {NULL}, NULL }; -HB_SYMB hb_symEnumBase = { "__ENUMBASE", {HB_FS_MESSAGE}, {NULL}, NULL }; -HB_SYMB hb_symEnumValue = { "__ENUMVALUE", {HB_FS_MESSAGE}, {NULL}, NULL }; -HB_SYMB hb_symWithObjectPush = { "__WITHOBJECT", {HB_FS_MESSAGE}, {NULL}, NULL }; -HB_SYMB hb_symWithObjectPop = { "___WITHOBJECT", {HB_FS_MESSAGE}, {NULL}, NULL }; static HB_ITEM s_aStatics; /* Harbour array to hold all application statics variables */ @@ -264,9 +260,6 @@ static LONG s_lRecoverBase; #define HB_RECOVER_ADDRESS -3 #define HB_RECOVER_VALUE -4 -/* Stores the position on the stack of current WITH OBJECT envelope */ -static LONG s_lWithObjectBase = 0; - /* Stores level of procedures call stack */ static ULONG s_ulProcLevel = 0; @@ -414,11 +407,6 @@ HB_EXPORT void hb_vmInit( BOOL bStartMainProc ) hb_errInit(); hb_dynsymNew( &hb_symEval ); /* initialize dynamic symbol for evaluating codeblocks */ - hb_dynsymNew( &hb_symEnumIndex ); - hb_dynsymNew( &hb_symEnumBase ); - hb_dynsymNew( &hb_symEnumValue ); - hb_dynsymNew( &hb_symWithObjectPush ); - hb_dynsymNew( &hb_symWithObjectPop ); hb_setInitialize(); /* initialize Sets */ hb_conInit(); /* initialize Console */ @@ -595,10 +583,8 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) { LONG w = 0; BOOL bCanRecover = FALSE; - LONG lForEachBase = 0; /* Stores the position on the stack of current FOR EACH envelope */ ULONG ulPrivateBase; BOOL bDynCode = pSymbols == NULL || ( pSymbols->scope.value & HB_FS_DYNCODE ) != 0; - LONG lWithObjectBase = s_lWithObjectBase; #ifndef HB_NO_PROFILER ULONG ulLastOpcode = 0; /* opcodes profiler support */ ULONG ulPastClock = 0; /* opcodes profiler support */ @@ -854,7 +840,7 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) break; case HB_P_ENUMSTART: - lForEachBase = hb_vmEnumStart( pCode[ w + 1 ], pCode[ w + 2 ], lForEachBase ); + hb_vmEnumStart( pCode[ w + 1 ], pCode[ w + 2 ] ); w += 3; break; @@ -869,7 +855,7 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) break; case HB_P_ENUMEND: - lForEachBase = hb_vmEnumEnd(); + hb_vmEnumEnd(); w++; break; @@ -1847,26 +1833,18 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) case HB_P_WITHOBJECTMESSAGE: hb_vmPushSymbol( pSymbols + HB_PCODE_MKUSHORT( &( pCode[ w + 1 ] ) ) ); - hb_vmPush( hb_stackItem( s_lWithObjectBase ) ); + hb_vmPush( hb_stackWithObjectItem() ); w += 3; break; case HB_P_WITHOBJECTSTART: - { - /* The object is pushed directly before this pcode */ - /* store position of current WITH OBJECT frame */ - HB_ITEM_PTR pItem = hb_stackAllocItem(); - pItem->type = HB_IT_LONG; - pItem->item.asLong.value = s_lWithObjectBase; - s_lWithObjectBase = hb_stackTopOffset() - 2; - w += 1; - } + hb_vmWithObjectStart(); + w++; break; case HB_P_WITHOBJECTEND: - s_lWithObjectBase = ( hb_stackItemFromTop( -1 ) )->item.asLong.value; - hb_stackDec(); - hb_stackPop(); /* remove implicit object */ + hb_stackPop(); /* remove with object envelope */ + hb_stackPop(); /* remove implicit object */ w += 1; break; @@ -1901,27 +1879,6 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) * There is the BEGIN/END sequence defined in current * procedure/function - use it to continue opcodes execution */ - while( lForEachBase > s_lRecoverBase || s_lWithObjectBase >= s_lRecoverBase ) - { - if( lForEachBase > s_lWithObjectBase ) - { - /* remove FOR EACH stack frame so there is no orphan - * item pointers hanging - */ - hb_stackRemove( lForEachBase ); - lForEachBase = hb_vmEnumEnd(); - } - else if( lForEachBase < s_lWithObjectBase ) - { - /* BREAK was issued inside the WITH OBJECT - * restore previous frame - */ - hb_stackRemove( s_lWithObjectBase + 2 ); - s_lWithObjectBase = ( hb_stackItemFromTop( -1 ) )->item.asLong.value; - hb_stackDec(); - } - } - /* * remove all items placed on the stack after BEGIN code */ @@ -1940,26 +1897,25 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) break; } else if( s_uiActionRequest & HB_QUIT_REQUESTED ) + { + while( bCanRecover ) + { + hb_stackRemove( s_lRecoverBase ); + /* 4) Restore previous recovery state */ + bCanRecover = hb_stackItemFromTop( -1 )->item.asLogical.value; + hb_stackDec(); + /* 3) Restore previous RECOVER base */ + s_lRecoverBase = hb_stackItemFromTop( -1 )->item.asLong.value; + hb_stackDec(); + /* skip other steps */ + } break; + } } } - while( lForEachBase ) - { - /* remove FOR EACH stack frame so there is no orphan - * item pointers hanging - */ - hb_stackRemove( lForEachBase ); - lForEachBase = hb_vmEnumEnd(); - } - if( pSymbols ) hb_memvarSetPrivatesBase( ulPrivateBase ); - - /* Restore previous WITH OBJECT frame if the RETURN statement - * was placed inside WITH OBJECT/END - */ - s_lWithObjectBase = lWithObjectBase; } /* ------------------------------- */ @@ -3097,12 +3053,54 @@ static void hb_vmForTest( void ) /* Test to check the end point of the FO #endif } +/* With object auto destructor */ +static HB_GARBAGE_FUNC( hb_withObjectDestructor ) +{ + LONG * plWithObjectBase = ( LONG * ) Cargo; + hb_stackWithObjectSetOffset( * plWithObjectBase ); +} + +static void hb_vmWithObjectStart( void ) +{ + LONG * plWithObjectBase; + PHB_ITEM pItem; + + HB_TRACE(HB_TR_DEBUG, ("hb_vmWithObjectStart()")); + + pItem = hb_stackAllocItem(); + plWithObjectBase = ( LONG * ) hb_gcAlloc( sizeof( LONG ), + hb_withObjectDestructor ); + * plWithObjectBase = hb_stackWithObjectOffset(); + pItem->type = HB_IT_POINTER; + pItem->item.asPointer.value = plWithObjectBase; + pItem->item.asPointer.collect = pItem->item.asPointer.single = TRUE; + /* The object is pushed directly before this pcode */ + /* store position of current WITH OBJECT frame */ + hb_stackWithObjectSetOffset( hb_stackTopOffset() - 2 ); +} + +typedef struct _HB_ENUMHOLDER +{ + PHB_ITEM pOldValue; + PHB_ITEM pEnumRef; +} HB_ENUMHOLDER, * PHB_ENUMHOLDER; + +static HB_GARBAGE_FUNC( hb_enumHolderRelease ) +{ + PHB_ENUMHOLDER pHolder = ( PHB_ENUMHOLDER ) Cargo; + + hb_itemMove( hb_itemUnRefOnce( pHolder->pEnumRef ), pHolder->pOldValue ); + hb_itemRelease( pHolder->pOldValue ); + hb_itemRelease( pHolder->pEnumRef ); +} + + /* At this moment the eval stack should store: * -2 -> * -1 -> */ /* Test to check the start point of the FOR EACH loop */ -static LONG hb_vmEnumStart( BYTE nVars, BYTE nDescend, LONG lOldBase ) +static void hb_vmEnumStart( BYTE nVars, BYTE nDescend ) { HB_ITEM_PTR pItem; ULONG ulMax; @@ -3120,20 +3118,45 @@ static LONG hb_vmEnumStart( BYTE nVars, BYTE nDescend, LONG lOldBase ) else { hb_errRT_BASE( EG_ARG, 1068, NULL, hb_langDGetErrorDesc( EG_ARRACCESS ), 1, pItem ); - return lOldBase; + return; } for( i = ( int ) nVars << 1; i > 0; i -= 2 ) { - HB_ITEM_PTR pValueRef, pEnum; + HB_ITEM_PTR pValue, pOldValue, pEnum, pEnumRef; + PHB_ENUMHOLDER pHolder; - pValueRef = hb_stackItemFromTop( -i ); - /* copy value to iterate */ - pItem = hb_itemNew( hb_itemUnRef( pValueRef ) ); + pValue = hb_stackItemFromTop( -i ); + /* copy value to iterate and clear the stack item for enumerator destructor */ + if( HB_IS_BYREF( pValue ) ) + pItem = hb_itemNew( hb_itemUnRef( pValue ) ); + else + pItem = hb_itemNew( pValue ); + if( HB_IS_COMPLEX( pValue ) ) + hb_itemClear( pValue ); + + /* store the reference to control variable */ + pEnumRef = hb_itemNew( hb_stackItemFromTop( -i + 1 ) ); /* the control variable */ - pEnum = hb_itemUnRefOnce( hb_stackItemFromTop( -i + 1 ) ); + pEnum = hb_itemUnRefOnce( pEnumRef ); /* store the old value of control variable and clear it */ - hb_itemMove( pValueRef, pEnum ); + pOldValue = hb_itemNew( NULL ); + hb_itemMove( pOldValue, pEnum ); + + /* create enumerator destructor */ + /* + * Here is a place for optimization - instead of allocating three new + * items we can keep them all in GC block and add mark/sweep function. + * I'll do that in the future when we will have final interface for it + * in our GC and mark/swap functions registered for extended + * HB_IT_POINTER items not allocated for each memory block. [druzus] + */ + pHolder = ( PHB_ENUMHOLDER ) hb_gcAlloc( sizeof( HB_ENUMHOLDER ), hb_enumHolderRelease ); + pHolder->pOldValue = pOldValue; + pHolder->pEnumRef = pEnumRef; + pValue->type = HB_IT_POINTER; + pValue->item.asPointer.value = pHolder; + pValue->item.asPointer.collect = pValue->item.asPointer.single = TRUE; /* set the iterator value */ pEnum->type = HB_IT_BYREF | HB_IT_ENUM; @@ -3167,30 +3190,25 @@ static LONG hb_vmEnumStart( BYTE nVars, BYTE nDescend, LONG lOldBase ) } hb_vmPushLong( nVars ); /* number of iterators */ - hb_vmPushLong( lOldBase ); /* previous FOREACH frame */ - /* empty array/string - do not start enumerations loop */ hb_vmPushLogical( ulMax != 0 ); - - return hb_stackTopOffset() - 1; } /* Enumeration in ascending order * At this moment the eval stack should store: - * -4 -> - * -3 -> - * -2 -> - * -1 -> + * -3 -> + * -2 -> + * -1 -> */ static void hb_vmEnumNext( void ) { HB_ITEM_PTR pEnum; int i; - for( i = ( int ) hb_stackItemFromTop( -2 )->item.asLong.value; i > 0; --i ) + for( i = ( int ) hb_stackItemFromTop( -1 )->item.asLong.value; i > 0; --i ) { - pEnum = hb_itemUnRefOnce( hb_stackItemFromTop( -( i << 1 ) - 1 ) ); + pEnum = hb_itemUnRefOnce( hb_stackItemFromTop( -( i << 1 ) ) ); if( HB_IS_ARRAY( pEnum->item.asEnum.basePtr ) ) { if( ( ULONG ) ++pEnum->item.asEnum.offset > @@ -3216,19 +3234,18 @@ static void hb_vmEnumNext( void ) /* Enumeration in descending order * At this moment the eval stack should store: - * -4 -> - * -3 -> - * -2 -> - * -1 -> + * -3 -> + * -2 -> + * -1 -> */ static void hb_vmEnumPrev( void ) { HB_ITEM_PTR pEnum; int i; - for( i = hb_stackItemFromTop( -2 )->item.asLong.value; i > 0; --i ) + for( i = hb_stackItemFromTop( -1 )->item.asLong.value; i > 0; --i ) { - pEnum = hb_itemUnRefOnce( hb_stackItemFromTop( -( i << 1 ) - 1 ) ); + pEnum = hb_itemUnRefOnce( hb_stackItemFromTop( -( i << 1 ) ) ); if( HB_IS_ARRAY( pEnum->item.asEnum.basePtr ) ) { if( --pEnum->item.asEnum.offset == 0 ) @@ -3252,33 +3269,23 @@ static void hb_vmEnumPrev( void ) /* Enumeration in descending order * At this moment the eval stack should store: - * -4 -> - * -3 -> - * -2 -> - * -1 -> + * -3 -> + * -2 -> + * -1 -> */ -static LONG hb_vmEnumEnd( void ) +static void hb_vmEnumEnd( void ) { - LONG lOldBase; LONG lVars; - /* restore stack frame offset of previous FOREACH loop */ - lOldBase = hb_stackItemFromTop( -1 )->item.asLong.value; - hb_stackDec(); - /* remove number of iterators */ lVars = hb_stackItemFromTop( -1 )->item.asLong.value; hb_stackDec(); while( --lVars >= 0 ) { - /* restore the value of variable before the FOREACH loop */ - hb_itemMove( hb_itemUnRefOnce( hb_stackItemFromTop( -1 ) ), hb_stackItemFromTop( -2 ) ); hb_stackPop(); - hb_stackDec(); + hb_stackPop(); } - - return lOldBase; } static LONG hb_vmSwitch( const BYTE * pCode, LONG offset, USHORT casesCnt ) @@ -3990,10 +3997,11 @@ HB_EXPORT void hb_vmSend( USHORT uiParams ) { PHB_ITEM pItem; PHB_SYMB pSym; + PHB_SYMB pExecSym; HB_STACK_STATE sStackState; PHB_ITEM pSelf; BOOL bDebugPrevState; - BOOL bNotHandled = TRUE; + BOOL lPopSuper; #ifndef HB_NO_PROFILER ULONG ulClock = 0; void * pMethod = NULL; @@ -4031,84 +4039,39 @@ HB_EXPORT void hb_vmSend( USHORT uiParams ) bDebugPrevState = s_bDebugging; s_bDebugging = FALSE; - if( HB_IS_BYREF( pSelf ) ) + pExecSym = hb_objGetMethod( pSelf, pSym, &lPopSuper ); + if( pExecSym && pExecSym->value.pFunPtr ) { - /* method of enumerator variable from FOR EACH statement - */ - HB_ITEM_PTR pEnum = hb_itemUnRefOnce( pSelf ); +#ifndef HB_NO_PROFILER + if( bProfiler ) + pMethod = hb_mthRequested(); +#endif + if( hb_bTracePrgCalls ) + HB_TRACE(HB_TR_ALWAYS, ("Calling: %s:%s", hb_objGetClsName( pSelf ), pSym->szName)); - if( HB_IS_ENUM( pEnum ) ) - { - if( pSym->pDynSym == hb_symEnumIndex.pDynSym ) - { - hb_itemPutNL( hb_stackReturnItem(), pEnum->item.asEnum.offset ); - bNotHandled = FALSE; - } - else if( pSym->pDynSym == hb_symEnumBase.pDynSym ) - { - hb_itemCopy( hb_stackReturnItem(), pEnum->item.asEnum.basePtr ); - bNotHandled = FALSE; - } - else if( pSym->pDynSym == hb_symEnumValue.pDynSym ) - { - hb_itemCopy( hb_stackReturnItem(), hb_itemUnRefOnce( pEnum ) ); - bNotHandled = FALSE; - } - } - } - - if( bNotHandled ) - { - if( pSym->pDynSym == hb_symWithObjectPush.pDynSym && s_lWithObjectBase ) - { - /* push current WITH OBJECT object */ - hb_itemCopy( &hb_stack.Return, hb_stackItem( s_lWithObjectBase ) ); - } - else if( pSym->pDynSym == hb_symWithObjectPop.pDynSym && s_lWithObjectBase ) - { - /* replace current WITH OBJECT object */ - hb_itemCopy( hb_stackItem( s_lWithObjectBase ), hb_stackItemFromBase( 1 ) ); - hb_itemCopy( &hb_stack.Return, hb_stackItem( s_lWithObjectBase ) ); - } + if( pExecSym->scope.value & HB_FS_PCODEFUNC ) + /* Running pCode dynamic function from .HRB */ + hb_vmExecute( pExecSym->value.pCodeFunc->pCode, + pExecSym->value.pCodeFunc->pSymbols ); else - { - PHB_SYMB pExecSym; - BOOL lPopSuper; - - pExecSym = hb_objGetMethod( pSelf, pSym, &lPopSuper ); - if( pExecSym && pExecSym->value.pFunPtr ) - { -#ifndef HB_NO_PROFILER - if( bProfiler ) - pMethod = hb_mthRequested(); -#endif - if( hb_bTracePrgCalls ) - HB_TRACE(HB_TR_ALWAYS, ("Calling: %s:%s", hb_objGetClsName( pSelf ), pSym->szName)); - - if( pExecSym->scope.value & HB_FS_PCODEFUNC ) - /* Running pCode dynamic function from .HRB */ - hb_vmExecute( pExecSym->value.pCodeFunc->pCode, - pExecSym->value.pCodeFunc->pSymbols ); - else - pExecSym->value.pFunPtr(); + pExecSym->value.pFunPtr(); #ifndef HB_NO_PROFILER - if( bProfiler ) - hb_mthAddTime( pMethod, clock() - ulClock ); + if( bProfiler ) + hb_mthAddTime( pMethod, clock() - ulClock ); #endif - } - else if( pSym->szName[ 0 ] == '_' ) - hb_errRT_BASE_SubstR( EG_NOVARMETHOD, 1005, NULL, pSym->szName + 1, HB_ERR_ARGS_SELFPARAMS ); - else - hb_errRT_BASE_SubstR( EG_NOMETHOD, 1004, NULL, pSym->szName, HB_ERR_ARGS_SELFPARAMS ); - - if( lPopSuper ) - hb_objPopSuperCast( pSelf ); - } } + else if( pSym->szName[ 0 ] == '_' ) + hb_errRT_BASE_SubstR( EG_NOVARMETHOD, 1005, NULL, pSym->szName + 1, HB_ERR_ARGS_SELFPARAMS ); + else + hb_errRT_BASE_SubstR( EG_NOMETHOD, 1004, NULL, pSym->szName, HB_ERR_ARGS_SELFPARAMS ); + + if( lPopSuper ) + hb_objPopSuperCast( pSelf ); if( s_bDebugging ) hb_vmDebuggerEndProc(); + hb_stackOldFrame( &sStackState ); s_bDebugging = bDebugPrevState; @@ -4163,8 +4126,8 @@ HB_ITEM_PTR hb_vmEvalBlock( HB_ITEM_PTR pBlock ) * ulArgCount = number of arguments passed to a codeblock * ... = the list of arguments of type PHB_ITEM * - *for example: - * retVal = hb_vmEvalBlockV( pBlock, 2, pParam1, pParam2 ); + * for example: + * retVal = hb_vmEvalBlockV( pBlock, 2, pParam1, pParam2 ); */ HB_ITEM_PTR hb_vmEvalBlockV( HB_ITEM_PTR pBlock, ULONG ulArgCount, ... ) { @@ -6068,31 +6031,8 @@ HB_EXPORT void hb_xvmSeqBegin( void ) s_lRecoverBase = hb_stackTopOffset(); } -HB_EXPORT BOOL hb_xvmSeqEnd( LONG * plForEachBase ) +HB_EXPORT BOOL hb_xvmSeqEnd( void ) { - if( plForEachBase ) - { - while( *plForEachBase > s_lRecoverBase || s_lWithObjectBase >= s_lRecoverBase ) - { - if( *plForEachBase > s_lWithObjectBase ) - { - /* remove FOR EACH stack frame so there is no orphan - * item pointers hanging - */ - hb_stackRemove( *plForEachBase ); - *plForEachBase = hb_vmEnumEnd(); - } - else if( *plForEachBase < s_lWithObjectBase ) - { - /* BREAK was issued inside the WITH OBJECT - * restore previous frame - */ - hb_stackRemove( s_lWithObjectBase + 1 ); - s_lWithObjectBase = ( hb_stackItemFromTop(-1) )->item.asLong.value; - hb_stackDec(); - } - } - } /* * remove all items placed on the stack after BEGIN code */ @@ -6121,23 +6061,41 @@ HB_EXPORT BOOL hb_xvmSeqEnd( LONG * plForEachBase ) return FALSE; } -HB_EXPORT BOOL hb_xvmSeqRecover( LONG * plForEachBase ) +HB_EXPORT BOOL hb_xvmSeqEndTest( void ) +{ + if( ( s_uiActionRequest & + ( HB_ENDPROC_REQUESTED | HB_BREAK_REQUESTED | HB_QUIT_REQUESTED ) ) != 0 ) + return TRUE; + + /* + * remove all items placed on the stack after BEGIN code + */ + hb_stackRemove( s_lRecoverBase ); + + /* + * Remove the SEQUENCE envelope + * This is executed either at the end of sequence or as the + * response to the break statement if there is no RECOVER clause + */ + + /* 4) Restore previous recovery state - not used in C code */ + hb_stackDec(); + /* 3) Restore previous RECOVER base */ + s_lRecoverBase = hb_stackItemFromTop( -1 )->item.asLong.value; + hb_stackDec(); + /* 2) Remove RECOVER address - not used in C code */ + hb_stackDec(); + /* 1) Discard the value returned by BREAK statement */ + hb_stackPop(); + return FALSE; +} + +HB_EXPORT BOOL hb_xvmSeqRecover( void ) { /* * Execute the RECOVER code */ - if( plForEachBase ) - { - while( *plForEachBase > s_lRecoverBase ) - { - /* remove FOR EACH stack frame so there is no orphan - * item pointers hanging - */ - hb_stackRemove( *plForEachBase ); - *plForEachBase = hb_vmEnumEnd(); - } - } /* * remove all items placed on the stack after BEGIN code */ @@ -6159,11 +6117,11 @@ HB_EXPORT BOOL hb_xvmSeqRecover( LONG * plForEachBase ) return FALSE; } -HB_EXPORT BOOL hb_xvmEnumStart( BYTE nVars, BYTE nDescend, LONG * plForEachBase ) +HB_EXPORT BOOL hb_xvmEnumStart( BYTE nVars, BYTE nDescend ) { - HB_TRACE(HB_TR_DEBUG, ("hb_xvmEnumStart(%d,%d,%p)", nVars, nDescend, plForEachBase)); + HB_TRACE(HB_TR_DEBUG, ("hb_xvmEnumStart(%d,%d)", nVars, nDescend)); - *plForEachBase = hb_vmEnumStart( nVars, nDescend, *plForEachBase ); + hb_vmEnumStart( nVars, nDescend ); HB_XVM_RETURN } @@ -6186,11 +6144,11 @@ HB_EXPORT BOOL hb_xvmEnumPrev( void ) HB_XVM_RETURN } -HB_EXPORT void hb_xvmEnumEnd( LONG * plForEachBase ) +HB_EXPORT void hb_xvmEnumEnd( void ) { - HB_TRACE(HB_TR_DEBUG, ("hb_xvmEnumEnd(%p)", plForEachBase)); + HB_TRACE(HB_TR_DEBUG, ("hb_xvmEnumEnd()")); - *plForEachBase = hb_vmEnumEnd(); + hb_vmEnumEnd(); } HB_EXPORT void hb_xvmSetLine( USHORT uiLine ) @@ -7886,32 +7844,32 @@ HB_EXPORT BOOL hb_xvmMacroText( void ) HB_EXPORT void hb_xvmWithObjectStart( void ) { - HB_ITEM_PTR pItem; - HB_TRACE(HB_TR_DEBUG, ("hb_xvmWithObjectStart()")); - - /* The object is pushed directly before this pcode */ - /* store position of current WITH OBJECT frame */ - pItem = hb_stackAllocItem(); - pItem->type = HB_IT_LONG; - pItem->item.asLong.value = s_lWithObjectBase; - s_lWithObjectBase = hb_stackTopOffset() - 2; + + hb_vmWithObjectStart(); } HB_EXPORT void hb_xvmWithObjectEnd( void ) { HB_TRACE(HB_TR_DEBUG, ("hb_xvmWithObjectEnd()")); - s_lWithObjectBase = ( hb_stackItemFromTop( -1 ) )->item.asLong.value; - hb_stackDec(); + hb_stackPop(); /* remove with object envelope */ hb_stackPop(); /* remove implicit object */ } +HB_EXPORT void hb_xvmWithObjectMessage( PHB_SYMB pSymbol ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_xvmWithObjectMessage(%p)", pSymbol)); + + hb_vmPushSymbol( pSymbol ); + hb_vmPush( hb_stackWithObjectItem() ); +} + HB_EXPORT LONG hb_xvmWithObjectBase( LONG * plWithObjectBase ) { if( plWithObjectBase ) - s_lWithObjectBase = *plWithObjectBase; - return s_lWithObjectBase; + hb_stackWithObjectSetOffset( *plWithObjectBase ); + return hb_stackWithObjectOffset(); } /* ------------------------------------------------------------------------ */ /* The debugger support functions */ diff --git a/harbour/source/vm/itemapi.c b/harbour/source/vm/itemapi.c index 30ed42d627..0c046535ed 100644 --- a/harbour/source/vm/itemapi.c +++ b/harbour/source/vm/itemapi.c @@ -1337,6 +1337,10 @@ HB_EXPORT void hb_itemCopy( PHB_ITEM pDest, PHB_ITEM pSource ) hb_gcRefInc( pSource->item.asPointer.value ); } } + else if( HB_IS_ENUM( pSource ) ) /* enumerators cannnot be copied */ + { + pDest->type = HB_IT_NIL; + } } }