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
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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" );
|
||||
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 -> <array for traverse>
|
||||
* -1 -> <the reference to enumerate variable>
|
||||
*/
|
||||
/* 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 -> <old value of enumerator variable>
|
||||
* -3 -> <the reference to enumerate variable>
|
||||
* -2 -> <number of iterators>
|
||||
* -1 -> <previous FOREACH frame>
|
||||
* -3 -> <old value of enumerator variable>
|
||||
* -2 -> <the reference to enumerate variable>
|
||||
* -1 -> <number of iterators>
|
||||
*/
|
||||
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 -> <old value of enumerator variable>
|
||||
* -3 -> <the reference to enumerate variable>
|
||||
* -2 -> <number of iterators>
|
||||
* -1 -> <previous FOREACH frame>
|
||||
* -3 -> <old value of enumerator variable>
|
||||
* -2 -> <the reference to enumerate variable>
|
||||
* -1 -> <number of iterators>
|
||||
*/
|
||||
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 -> <old value of enumerator variable>
|
||||
* -3 -> <the reference to enumerate variable>
|
||||
* -2 -> <number of iterators>
|
||||
* -1 -> <previous FOREACH frame>
|
||||
* -3 -> <old value of enumerator variable>
|
||||
* -2 -> <the reference to enumerate variable>
|
||||
* -1 -> <number of iterators>
|
||||
*/
|
||||
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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user