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:
Przemyslaw Czerpak
2006-07-25 09:03:06 +00:00
parent b7ee44b737
commit f1fa94f3c4
11 changed files with 319 additions and 293 deletions

View File

@@ -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.

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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" );

View File

@@ -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 */
};

View File

@@ -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.

View File

@@ -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 );
}
}

View File

@@ -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 */

View File

@@ -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;
}
}
}