diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 3f85200177..296592e3bb 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,56 @@ +20000115-15:15 GMT+1 Ryszard Glab + + *include/pcode.h + * added new pcodes: + HB_P_PUSHALIASEDVAR + HB_P_POPALIASEDVAR + HB_P_MPUSHALIASEDVAR + HB_P_MPOPALIASEDVAR + +NOTE: All sources HAVE TO be recompiled!!! + + *include/macro.h + * added new constant: + HB_MACRO_GEN_PUSH 4 /* generate PUSH pcodes */ + HB_MACRO_GEN_POP 8 /* generate POP pcodes */ + HB_MACRO_GEN_ALIASED 16 /* force aliased variable */ + + *include/extend.h + * added declaration of + hb_macroPopAliasedValue + hb_macroPushAliasedValue + + *source/macro/macro.c + *source/compiler/harbour.c + * corrected handling of aliased variables in case when an alias + is determined at runtime (the field variable was assumed previously + but now the virtual machine checks the value of passed alias and + used either a memvar or a field) + for example: + alias := "M" + ? ( alias )->var + The value of memvar named "var" should be printed + + *include/hbexpr.c + *source/compiler/expropt.c + * finished support for aliased macro expressions + + *source/macro/macro.c + * finished support for aliased macro expressions + + *source/vm/hvm.c + *source/compiler/genc.c + *source/compiler/genhrb.c + *source/compiler/genjava.c + * added support for new pcodes: + HB_P_PUSHALIASEDVAR + HB_P_POPALIASEDVAR + HB_P_MPUSHALIASEDVAR + HB_P_MPOPALIASEDVAR + + *source/compiler/harbour.y + * removed 'macro support' from the TODO list :) + 2000-01-14 12:20 GMT-5 David G. Holm * ngdoc/ft_helpc.prg diff --git a/harbour/include/extend.h b/harbour/include/extend.h index b4d05ac56f..2a6ba9de6b 100644 --- a/harbour/include/extend.h +++ b/harbour/include/extend.h @@ -463,6 +463,8 @@ extern HB_MACRO_PTR hb_macroCompile( char * ); extern void hb_macroDelete( HB_MACRO_PTR ); extern char * hb_macroTextSubst( char *, ULONG * ); extern BOOL hb_macroIsIdent( char * ); +extern void hb_macroPopAliasedValue( HB_ITEM_PTR, HB_ITEM_PTR ); +extern void hb_macroPushAliasedValue( HB_ITEM_PTR, HB_ITEM_PTR ); /* misc */ extern char * hb_version( USHORT uiMode ); diff --git a/harbour/include/hbexpr.c b/harbour/include/hbexpr.c index fb593c476e..aeb8be6aed 100644 --- a/harbour/include/hbexpr.c +++ b/harbour/include/hbexpr.c @@ -2634,7 +2634,12 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) case HB_EA_DELETE: hb_compExprDelete( pSelf->value.asAlias.pAlias ); - /* NOTE: variable name is not released now */ +#ifdef HB_MACRO_SUPPORT + if( pSelf->value.asAlias.pVar ) + hb_compExprDelete( pSelf->value.asAlias.pVar ); +#else + /* NOTE: variable name is not released now */ +#endif break; } return pSelf; @@ -2728,7 +2733,11 @@ static HB_EXPR_FUNC( hb_compExprUseAlias ) case HB_EA_POP_PCODE: case HB_EA_PUSH_POP: case HB_EA_STATEMENT: + break; case HB_EA_DELETE: +#ifdef HB_MACRO_SUPPORT + hb_xfree( pSelf->value.asSymbol ); +#endif break; } return pSelf; @@ -2803,11 +2812,35 @@ static HB_EXPR_FUNC( hb_compExprUseVariable ) case HB_EA_LVALUE: break; case HB_EA_PUSH_PCODE: - hb_compGenPushVar( pSelf->value.asSymbol ); - break; - case HB_EA_POP_PCODE: - hb_compGenPopVar( pSelf->value.asSymbol ); - break; + +#ifdef HB_MACRO_SUPPORT + /* NOTE: When the following syntax is used: + * ( any_expr )->&var2 + * then macro compiler is compiling the right side of alias + * operator only (if 'any_expr' is not a string) - an alias value + * is placed on the eval stack before macro compilation. + * The HB_MACRO_GEN_ALIASED flag is used to signal that we have to + * genearate alias aware pcode even if we known a variable part only. + */ + if( HB_MACRO_DATA->Flags & HB_MACRO_GEN_ALIASED ) + hb_compGenPushAliasedVar( pSelf->value.asSymbol, FALSE, NULL, 0 ); + else + hb_compGenPushVar( pSelf->value.asSymbol ); +#else + hb_compGenPushVar( pSelf->value.asSymbol ); +#endif + break; + + case HB_EA_POP_PCODE: +#ifdef HB_MACRO_SUPPORT + if( HB_MACRO_DATA->Flags & HB_MACRO_GEN_ALIASED ) + hb_compGenPopAliasedVar( pSelf->value.asSymbol, FALSE, NULL, 0 ); + else + hb_compGenPopVar( pSelf->value.asSymbol ); +#else + hb_compGenPopVar( pSelf->value.asSymbol ); +#endif + break; case HB_EA_PUSH_POP: case HB_EA_STATEMENT: diff --git a/harbour/include/macro.h b/harbour/include/macro.h index 016e2fe4ed..2b59503959 100644 --- a/harbour/include/macro.h +++ b/harbour/include/macro.h @@ -59,6 +59,9 @@ #define HB_MACRO_OK 0 /* macro compiled successfully */ #define HB_MACRO_FAILURE 1 /* syntax error */ #define HB_MACRO_TOO_COMPLEX 2 /* compiled expression is too complex */ +#define HB_MACRO_GEN_PUSH 4 /* generate PUSH pcodes */ +#define HB_MACRO_GEN_POP 8 /* generate POP pcodes */ +#define HB_MACRO_GEN_ALIASED 16 /* force aliased variable */ /* Global functions diff --git a/harbour/include/pcode.h b/harbour/include/pcode.h index d930a4bf72..e37d0e9796 100644 --- a/harbour/include/pcode.h +++ b/harbour/include/pcode.h @@ -81,9 +81,11 @@ typedef enum /* start: pcodes generated by the macro compiler - the symbol address is used */ HB_P_MMESSAGE, HB_P_MPOPALIASEDFIELD, + HB_P_MPOPALIASEDVAR, HB_P_MPOPFIELD, HB_P_MPOPMEMVAR, HB_P_MPUSHALIASEDFIELD, + HB_P_MPUSHALIASEDVAR, HB_P_MPUSHBLOCK, HB_P_MPUSHFIELD, HB_P_MPUSHMEMVAR, @@ -102,6 +104,7 @@ typedef enum HB_P_POP, /* removes the latest value from the stack */ HB_P_POPALIAS, /* pops the item from the eval stack and selects the current workarea */ HB_P_POPALIASEDFIELD, /* pops aliased field */ + HB_P_POPALIASEDVAR, /* pops aliased variable (either a field or a memvar) */ HB_P_POPFIELD, /* pops unaliased field */ HB_P_POPLOCAL, /* pops the contains of the virtual machine stack onto a local variable */ HB_P_POPMEMVAR, /* pops the contains of a memvar variable to the virtual machine stack */ @@ -110,6 +113,7 @@ typedef enum HB_P_POWER, /* calculates the power of the two values on the stack, removing them and leaving there the result */ HB_P_PUSHALIAS, /* saves the current workarea number on the eval stack */ HB_P_PUSHALIASEDFIELD, /* pushes aliased field */ + HB_P_PUSHALIASEDVAR, /* pushes aliased variable (either a field or a memvar) */ HB_P_PUSHBLOCK, /* start of a codeblock definition */ HB_P_PUSHFIELD, /* pushes unaliased field */ HB_P_PUSHINT, /* places an integer number on the virtual machine stack */ diff --git a/harbour/source/compiler/genc.c b/harbour/source/compiler/genc.c index b354f31572..91694f6ca5 100644 --- a/harbour/source/compiler/genc.c +++ b/harbour/source/compiler/genc.c @@ -554,6 +554,21 @@ void hb_compGenCCode( PHB_FNAME pFileName ) /* generates the C language ou } break; + case HB_P_POPALIASEDVAR: + { + USHORT wFixPos; + + wVar = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; + wFixPos = hb_compSymbolFixPos( wVar ); + fprintf( yyc, "\tHB_P_POPALIASEDVAR, %i, %i,", + HB_LOBYTE( wFixPos ), + HB_HIBYTE( wFixPos ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compSymbolGetPos( wVar )->szName ); + fprintf( yyc, "\n" ); + lPCodePos += 3; + } + break; + case HB_P_POPFIELD: { USHORT wFixPos; @@ -682,6 +697,22 @@ void hb_compGenCCode( PHB_FNAME pFileName ) /* generates the C language ou } break; + case HB_P_PUSHALIASEDVAR: + { + USHORT wFixPos; + + wVar = pFunc->pCode[ lPCodePos + 1 ] + + pFunc->pCode[ lPCodePos + 2 ] * 256; + wFixPos = hb_compSymbolFixPos( wVar ); + fprintf( yyc, "\tHB_P_PUSHALIASEDVAR, %i, %i,", + HB_LOBYTE( wFixPos ), + HB_HIBYTE( wFixPos ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compSymbolGetPos( wVar )->szName ); + fprintf( yyc, "\n" ); + lPCodePos += 3; + } + break; + case HB_P_PUSHBLOCK: ++iNestedCodeblock; diff --git a/harbour/source/compiler/genhrb.c b/harbour/source/compiler/genhrb.c index 911922cd43..62682f68c2 100644 --- a/harbour/source/compiler/genhrb.c +++ b/harbour/source/compiler/genhrb.c @@ -275,6 +275,8 @@ void hb_compGenPortObj( PHB_FNAME pFileName ) case HB_P_PUSHFIELD: case HB_P_POPALIASEDFIELD: case HB_P_PUSHALIASEDFIELD: + case HB_P_POPALIASEDVAR: + case HB_P_PUSHALIASEDVAR: fputc( pFunc->pCode[ lPCodePos ], yyc ); wVar = hb_compSymbolFixPos( pFunc->pCode[ lPCodePos + 1 ] + 256 * pFunc->pCode[ lPCodePos + 2 ] ); fputc( HB_LOBYTE( wVar ), yyc ); diff --git a/harbour/source/compiler/genjava.c b/harbour/source/compiler/genjava.c index b6595afa36..00dbd196a0 100644 --- a/harbour/source/compiler/genjava.c +++ b/harbour/source/compiler/genjava.c @@ -297,6 +297,8 @@ void hb_compGenJava( PHB_FNAME pFileName ) case HB_P_PUSHFIELD: case HB_P_POPALIASEDFIELD: case HB_P_PUSHALIASEDFIELD: + case HB_P_POPALIASEDVAR: + case HB_P_PUSHALIASEDVAR: hb_fputc( pFunc->pCode[ lPCodePos ], yyc ); wVar = hb_compSymbolFixPos( pFunc->pCode[ lPCodePos + 1 ] + 256 * pFunc->pCode[ lPCodePos + 2 ] ); hb_fputc( HB_LOBYTE( wVar ), yyc ); diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index 5518a3bfab..05e862d355 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -1491,8 +1491,11 @@ void hb_compGenPopAliasedVar( char * szVarName, } } else - /* Alias is already placed on stack */ - hb_compGenVarPCode( HB_P_POPALIASEDFIELD, szVarName ); + /* Alias is already placed on stack + * NOTE: An alias will be determined at runtime then we cannot decide + * here if passed name is either a field or a memvar + */ + hb_compGenVarPCode( HB_P_POPALIASEDVAR, szVarName ); } /* generates the pcode to push a nonaliased variable value to the virtual @@ -1718,8 +1721,11 @@ void hb_compGenPushAliasedVar( char * szVarName, } } else - /* Alias is already placed on stack */ - hb_compGenVarPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + /* Alias is already placed on stack + * NOTE: An alias will be determined at runtime then we cannot decide + * here if passed name is either a field or a memvar + */ + hb_compGenVarPCode( HB_P_PUSHALIASEDVAR, szVarName ); } void hb_compGenPushLogical( int iTrueFalse ) /* pushes a logical value on the virtual machine stack */ diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index c5a76b594e..885f44f16a 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -36,9 +36,8 @@ /* TODO list * 1) jumps longer then 2^15 bytes - * 2) macro support - * 3) Change the pcode generated by ::cVar from Self:cVar to QSELF():cVar - * 4) Support this syntax: nPtr := @Hello() + * 2) Change the pcode generated by ::cVar from Self:cVar to QSELF():cVar + * 3) Support this syntax: nPtr := @Hello() */ #include diff --git a/harbour/source/macro/macro.c b/harbour/source/macro/macro.c index 7152f3368b..1e97ee931d 100644 --- a/harbour/source/macro/macro.c +++ b/harbour/source/macro/macro.c @@ -45,6 +45,8 @@ static BOOL hb_comp_bShortCuts = TRUE; /* .and. & .or. expressions shortcuts */ static BOOL hb_comp_bUseName10 = FALSE; /* names limited to 10 characters */ +static void hb_macroUseAliased( HB_ITEM_PTR, HB_ITEM_PTR, int ); + /* ************************************************************************* */ /* Compile passed string into a pcode buffer @@ -285,7 +287,7 @@ char * hb_macroTextSubst( char * szString, ULONG *pulStringLen ) /* number of characters left on the right side of a variable name */ ulCharsLeft = ulResStrLen - ( pHead - szResult ); - /* NOTE: + /* NOTE: * if a replacement string is shorter then the variable * name then we don't have to reallocate the result buffer: * 'ulResStrLen' stores the current length of a string in the buffer @@ -341,6 +343,7 @@ char * hb_macroTextSubst( char * szString, ULONG *pulStringLen ) * This will be called when macro variable or macro expression is * placed on the right side of the assignment or when it is used as * a parameter. + * PUSH operation */ void hb_macroGetValue( HB_ITEM_PTR pItem ) { @@ -354,7 +357,7 @@ void hb_macroGetValue( HB_ITEM_PTR pItem ) struMacro.bShortCuts = hb_comp_bShortCuts; struMacro.bName10 = hb_comp_bUseName10; - iStatus = hb_macroParse( &struMacro, szString, HB_P_MACROPUSH ); + iStatus = hb_macroParse( &struMacro, szString, HB_MACRO_GEN_PUSH ); hb_stackPop(); /* remove compiled string */ if( iStatus == HB_MACRO_OK && struMacro.status == HB_MACRO_OK ) @@ -370,6 +373,7 @@ void hb_macroGetValue( HB_ITEM_PTR pItem ) /* NOTE: * This will be called when macro variable or macro expression is * placed on the left side of the assignment + * POP operation */ void hb_macroSetValue( HB_ITEM_PTR pItem ) { @@ -383,7 +387,7 @@ void hb_macroSetValue( HB_ITEM_PTR pItem ) struMacro.bShortCuts = hb_comp_bShortCuts; struMacro.bName10 = hb_comp_bUseName10; - iStatus = hb_macroParse( &struMacro, szString, HB_P_MACROPOP ); + iStatus = hb_macroParse( &struMacro, szString, HB_MACRO_GEN_POP ); hb_stackPop(); /* remove compiled string */ if( iStatus == HB_MACRO_OK && struMacro.status == HB_MACRO_OK ) @@ -396,6 +400,102 @@ void hb_macroSetValue( HB_ITEM_PTR pItem ) } } +/* Compiles and run an aliased macro expression - generated pcode + * pops a value from the stack + * &alias->var := any + * alias->&var := any + */ +void hb_macroPopAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_macroPopAliasedValue(%p, %p)", pAlias, pVar)); + + hb_macroUseAliased( pAlias, pVar, HB_MACRO_GEN_POP ); +} + +/* Compiles and run an aliased macro expression - generated pcode + * pushes a value onto the stack + * any := &alias->var + * any := alias->&var + */ +void hb_macroPushAliasedValue( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_macroPushAliasedValue(%p, %p)", pAlias, pVar)); + + hb_macroUseAliased( pAlias, pVar, HB_MACRO_GEN_PUSH ); +} + +/* + * Compile and run: + * &alias->var or + * alias->&var + * NOTE: + * Clipper implements these two cases as: &( alias +'->' + variable ) + * This causes some non expected behaviours, for example: + * A :="M + M" + * ? &A->&A + * is the same as: + * &( "M + M->M + M" ) + * instead of + * &( "M + M" ) -> &( "M + M" ) + */ +static void hb_macroUseAliased( HB_ITEM_PTR pAlias, HB_ITEM_PTR pVar, int iFlag ) +{ + if( IS_STRING( pAlias ) && IS_STRING( pVar ) ) + { + /* grab memory for "alias->var" + */ + char * szString = ( char * ) hb_xgrab( pAlias->item.asString.length + pVar->item.asString.length + 3 ); + HB_MACRO struMacro; + int iStatus; + + memcpy( szString, pAlias->item.asString.value, pAlias->item.asString.length ); + szString[ pAlias->item.asString.length ] = '-'; + szString[ pAlias->item.asString.length + 1 ] = '>'; + memcpy( szString + pAlias->item.asString.length + 2, pVar->item.asString.value, pVar->item.asString.length ); + szString[ pAlias->item.asString.length + 2 + pVar->item.asString.length ] = '\0'; + + struMacro.bShortCuts = hb_comp_bShortCuts; + struMacro.bName10 = hb_comp_bUseName10; + iStatus = hb_macroParse( &struMacro, szString, iFlag ); + hb_xfree( szString ); + struMacro.string = NULL; + + hb_stackPop(); /* remove compiled variable name */ + hb_stackPop(); /* remove compiled alias */ + + if( iStatus == HB_MACRO_OK && struMacro.status == HB_MACRO_OK ) + { + hb_macroRun( &struMacro ); + hb_macroDelete( &struMacro ); + } + else + hb_macroSyntaxError( &struMacro ); + } + else if( hb_macroCheckParam( pVar ) ) + { + /* only right side of alias operator is a string - macro-compile + * this part only + */ + HB_MACRO struMacro; + int iStatus; + char * szString = pVar->item.asString.value; + + struMacro.bShortCuts = hb_comp_bShortCuts; + struMacro.bName10 = hb_comp_bUseName10; + iStatus = hb_macroParse( &struMacro, szString, iFlag | HB_MACRO_GEN_ALIASED ); + + hb_stackPop(); /* remove compiled string */ + + if( iStatus == HB_MACRO_OK && struMacro.status == HB_MACRO_OK ) + { + hb_macroRun( &struMacro ); + hb_macroDelete( &struMacro ); + } + else + hb_macroSyntaxError( &struMacro ); + } +} + /* compile a string and return a pcode to push a value of expression * NOTE: it can be called to implement an index key evaluation * use hb_macroRun() to evaluate a compiled pcode @@ -711,8 +811,11 @@ void hb_compGenPopAliasedVar( char * szVarName, } } else - /* Alias is already placed on stack */ - hb_compMemvarGenPCode( HB_P_MPOPALIASEDFIELD, szVarName, HB_MACRO_PARAM ); + /* Alias is already placed on stack + * NOTE: An alias will be determined at runtime then we cannot decide + * here if passed name is either a field or a memvar + */ + hb_compMemvarGenPCode( HB_P_MPOPALIASEDVAR, szVarName, HB_MACRO_PARAM ); } /* generates the pcode to push a nonaliased variable value to the virtual @@ -805,8 +908,11 @@ void hb_compGenPushAliasedVar( char * szVarName, } } else - /* Alias is already placed on stack */ - hb_compMemvarGenPCode( HB_P_MPUSHALIASEDFIELD, szVarName, HB_MACRO_PARAM ); + /* Alias is already placed on stack + * NOTE: An alias will be determined at runtime then we cannot decide + * here if passed name is either a field or a memvar + */ + hb_compMemvarGenPCode( HB_P_MPUSHALIASEDVAR, szVarName, HB_MACRO_PARAM ); } /* pushes a logical value on the virtual machine stack , */ diff --git a/harbour/source/macro/macro.y b/harbour/source/macro/macro.y index 493829c283..fc400bb3d8 100644 --- a/harbour/source/macro/macro.y +++ b/harbour/source/macro/macro.y @@ -185,13 +185,13 @@ int yylex( YYSTYPE *, HB_MACRO_PTR ); %% -Main : Expression '\n' { if( HB_MACRO_DATA->Flags & HB_P_MACROPUSH ) +Main : Expression '\n' { if( HB_MACRO_DATA->Flags & HB_MACRO_GEN_PUSH ) hb_compExprDelete( hb_compExprGenPush( $1, HB_MACRO_PARAM ), HB_MACRO_PARAM ); else hb_compExprDelete( hb_compExprGenPop( $1, HB_MACRO_PARAM ), HB_MACRO_PARAM ); hb_compGenPCode1( HB_P_ENDPROC, HB_MACRO_PARAM ); } - | Expression { if( HB_MACRO_DATA->Flags & HB_P_MACROPUSH ) + | Expression { if( HB_MACRO_DATA->Flags & HB_MACRO_GEN_PUSH ) hb_compExprDelete( hb_compExprGenPush( $1, HB_MACRO_PARAM ), HB_MACRO_PARAM ); else hb_compExprDelete( hb_compExprGenPop( $1, HB_MACRO_PARAM ), HB_MACRO_PARAM ); diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 656e793e86..bfa8933b66 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -129,6 +129,7 @@ static void hb_vmDebuggerEndProc( void ); /* notifies the debugger for an /* Push */ static void hb_vmPushAlias( void ); /* pushes the current workarea number */ static void hb_vmPushAliasedField( PHB_SYMB ); /* pushes an aliased field on the eval stack */ +static void hb_vmPushAliasedVar( PHB_SYMB ); /* pushes an aliased variable on the eval stack */ static void hb_vmPushBlock( BYTE * pCode, PHB_SYMB pSymbols ); /* creates a codeblock */ static void hb_vmPushMacroBlock( BYTE * pCode, PHB_SYMB pSymbols ); /* creates a macro-compiled codeblock */ static void hb_vmPushLocal( SHORT iLocal ); /* pushes the containts of a local onto the stack */ @@ -146,6 +147,7 @@ static double hb_vmPopNumber( void ); /* pops the stack latest value static double hb_vmPopDouble( int * ); /* pops the stack latest value and returns its double numeric format value */ static void hb_vmPopAlias( void ); /* pops the workarea number form the eval stack */ static void hb_vmPopAliasedField( PHB_SYMB ); /* pops an aliased field from the eval stack*/ +static void hb_vmPopAliasedVar( PHB_SYMB ); /* pops an aliased variable from the eval stack*/ static void hb_vmPopLocal( SHORT iLocal ); /* pops the stack latest value onto a local */ static void hb_vmPopStatic( USHORT uiStatic ); /* pops the stack latest value onto a static */ @@ -777,6 +779,12 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) w += 3; break; + case HB_P_PUSHALIASEDVAR: + uiParams = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); + hb_vmPushAliasedVar( pSymbols + uiParams ); + w += 3; + break; + case HB_P_PUSHFIELD: /* It pushes the current value of the given field onto the eval stack */ @@ -858,6 +866,12 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) w += 3; break; + case HB_P_POPALIASEDVAR: + uiParams = pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); + hb_vmPopAliasedVar( pSymbols + uiParams ); + w += 3; + break; + case HB_P_POPFIELD: /* Pops a value from the eval stack and uses it to set * a new value of the given field @@ -916,9 +930,11 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) break; case HB_P_MACROPOPALIASED: - /* compile and run - pop a field value from the stack */ + /* compile and run - pop an aliased variable from the stack */ + hb_macroPopAliasedValue( hb_stack.pPos - 2, hb_stack.pPos - 1 ); w++; break; + case HB_P_MACROPUSH: /* compile and run - leave the result on the stack */ /* the topmost element on the stack contains a macro @@ -929,7 +945,8 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) break; case HB_P_MACROPUSHALIASED: - /* compile and run - leave the field value on the stack */ + /* compile and run - leave an aliased variable on the stack */ + hb_macroPushAliasedValue( hb_stack.pPos - 2, hb_stack.pPos - 1 ); w++; break; @@ -940,7 +957,7 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) break; case HB_P_MACROTEXT: - /* macro text substitution + /* macro text substitution * "text ¯o.other text" */ hb_macroTextValue( hb_stack.pPos - 1 ); @@ -965,6 +982,14 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) } break; + case HB_P_MPOPALIASEDVAR: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_vmPopAliasedVar( ( *pDynSym )->pSymbol ); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + case HB_P_MPOPFIELD: { HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); @@ -998,6 +1023,14 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) } break; + case HB_P_MPUSHALIASEDVAR: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_vmPushAliasedVar( ( *pDynSym )->pSymbol ); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + case HB_P_MPUSHBLOCK: { /*NOTE: the pcode is stored in dynamically allocated memory @@ -2903,6 +2936,56 @@ static void hb_vmPushAliasedField( PHB_SYMB pSym ) hb_rddSelectWorkAreaNumber( iCurrArea ); } +/* It pops the last item from the stack to use it to select a workarea + * and next pushes the value of either a field or a memvar based on alias value + * (for performance reason it replaces alias value with field value) + * This is used in the following context: + * ( any_alias )->variable + */ +static void hb_vmPushAliasedVar( PHB_SYMB pSym ) +{ + PHB_ITEM pAlias = hb_stack.pPos - 1; + + HB_TRACE(HB_TR_DEBUG, ("hb_vmPushAliasedVar(%p)", pSym)); + + if( IS_STRING( pAlias ) ) + { + char * szAlias = hb_strUpper( pAlias->item.asString.value, pAlias->item.asString.length ); + + if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) + { /* M->variable */ + hb_memvarGetValue( pAlias, pSym ); + } + else + { + int iCmp = strncmp( szAlias, "MEMVAR", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "MEMVAR", pAlias->item.asString.length ); + if( iCmp == 0 ) + { /* MEMVAR-> or MEMVA-> or MEMV-> */ + hb_memvarGetValue( pAlias, pSym ); + } + else + { /* field variable */ + iCmp = strncmp( szAlias, "FIELD", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "FIELD", pAlias->item.asString.length ); + if( iCmp == 0 ) + { /* FIELD-> */ + hb_rddGetFieldValue( pAlias, pSym ); + } + else + { /* database alias */ + hb_vmPushAliasedField( pSym ); + } + } + } + + } + else + hb_vmPushAliasedField( pSym ); +} + static void hb_vmPushLocal( SHORT iLocal ) { HB_TRACE(HB_TR_DEBUG, ("hb_vmPushLocal(%hd)", iLocal)); @@ -3136,7 +3219,7 @@ static void hb_vmPopAlias( void ) } /* Pops the alias to use it to select a workarea and next pops a value - * into given field + * into a given field */ static void hb_vmPopAliasedField( PHB_SYMB pSym ) { @@ -3153,6 +3236,64 @@ static void hb_vmPopAliasedField( PHB_SYMB pSym ) hb_stackPop(); /* field value */ } +/* Pops the alias to use it to select a workarea and next pops a value + * into either a field or a memvar based on the alias value + * This is used in the following context: + * ( any_alias )->variable + */ +static void hb_vmPopAliasedVar( PHB_SYMB pSym ) +{ + HB_ITEM_PTR pAlias = hb_stack.pPos - 1; + + HB_TRACE(HB_TR_DEBUG, ("hb_vmPopAliasedVar(%p)", pSym)); + + /* "M", "MEMV" - "MEMVAR" and "FIEL" - "FIELD" are reserved aliases + */ + if( IS_STRING( pAlias ) ) + { + char * szAlias = pAlias->item.asString.value; + + if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) + { /* M->variable */ + hb_memvarSetValue( pSym, hb_stack.pPos - 2 ); + hb_stackPop(); /* alias */ + hb_stackPop(); /* value */ + } + else + { + int iCmp = strncmp( szAlias, "MEMVAR", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "MEMVAR", pAlias->item.asString.length ); + if( iCmp == 0 ) + { /* MEMVAR-> or MEMVA-> or MEMV-> */ + hb_memvarSetValue( pSym, hb_stack.pPos - 2 ); + hb_stackPop(); /* alias */ + hb_stackPop(); /* value */ + } + else + { /* field variable */ + iCmp = strncmp( szAlias, "FIELD", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "FIELD", pAlias->item.asString.length ); + if( iCmp == 0 ) + { /* FIELD-> */ + hb_rddPutFieldValue( hb_stack.pPos - 2, pSym ); + hb_stackPop(); /* alias */ + hb_stackPop(); /* value */ + } + else + { /* database alias */ + hb_vmPopAliasedField( pSym ); + } + } + } + } + else + { + hb_vmPopAliasedField( pSym ); + } +} + static void hb_vmPopLocal( SHORT iLocal ) { HB_TRACE(HB_TR_DEBUG, ("hb_vmPopLocal(%hd)", iLocal));