diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 5ecbfe19fa..c9530d3f23 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,43 @@ +19991212-13:55 GMT+1 Ryszard Glab + + *source/compiler/harbour.c + *source/macro/macro.c + * removed duplicated check if a reserved name was used + + *source/macro/macro.c + *include/hbexpr.c + *include/compiler.h + * removed 'IsFunction' parameter of hb_compGenPushSymbol + that is no longer needed. 'hb_compGenPushSymbol()' should push any + symbol without checking, the check for reserved function name is + done in hb_compGenPushFunCall() + + *source/compiler/harbour.l + *source/macro/macro.l + * removed duplicated check if a reserved name was used + * restored support for ¯o[ index ] syntax + + *include/extend.h + * added missing declaration of hb_macroRun() function + * moved here the definition of HB_MACRO structure + + *include/macro.h + * the definition of HB_MACRO structure moved to extend.h + + *include/expropt.h + * the definition of HB_CBVAR structure moved to extend.h + + *source/vm/hvm.c + *source/macro/macro.c + *include/extend.h + * added partial support for macro function call &var() or DO &var + (partial because a simple function name is allowed only - + there is no support for nested macros and complex macros) + + *source/macro.y + * added #undef __GNUC__ as a workaround of bison.simple bug in + yyparse() declaration + 19991211-15:55 GMT+1 Ryszard Glab *include/hbexpr.c diff --git a/harbour/include/compiler.h b/harbour/include/compiler.h index 91c595f0ab..1c9b4d1599 100644 --- a/harbour/include/compiler.h +++ b/harbour/include/compiler.h @@ -201,7 +201,7 @@ extern void hb_compGenPushLogical( int, HB_MACRO_DECL ); /* pushes a logical extern void hb_compGenPushLong( long, HB_MACRO_DECL ); /* Pushes a long number on the virtual machine stack */ extern void hb_compGenPushNil( HB_MACRO_DECL ); /* Pushes nil on the virtual machine stack */ extern void hb_compGenPushString( char *, ULONG, HB_MACRO_DECL ); /* Pushes a string on the virtual machine stack */ -extern void hb_compGenPushSymbol( char *, int, HB_MACRO_DECL ); /* Pushes a symbol on to the Virtual machine stack */ +extern void hb_compGenPushSymbol( char *, HB_MACRO_DECL ); /* Pushes a symbol on to the Virtual machine stack */ extern void hb_compGenPushAliasedVar( char *, BOOL, char *, long, HB_MACRO_DECL ); extern void hb_compGenPopAliasedVar( char *, BOOL, char *, long, HB_MACRO_DECL ); extern void hb_compGenPushFunRef( char *, HB_MACRO_DECL ); diff --git a/harbour/include/expropt.h b/harbour/include/expropt.h index b42f6be3c6..0845129374 100644 --- a/harbour/include/expropt.h +++ b/harbour/include/expropt.h @@ -36,15 +36,7 @@ #ifndef HB_EXPROPT_H_ #define HB_EXPROPT_H_ -/* This structure holds local variables declared in a codeblock - */ -typedef struct HB_CBVAR_ -{ - char * szName; - BYTE bType; - struct HB_CBVAR_ * pNext; -} HB_CBVAR, *HB_CBVAR_PTR; - +#include "extend.h" typedef struct HB_EXPR_ { diff --git a/harbour/include/extend.h b/harbour/include/extend.h index 4b6b895556..7c73bd4070 100644 --- a/harbour/include/extend.h +++ b/harbour/include/extend.h @@ -419,8 +419,41 @@ extern char * hb_setColor( char * ); extern char * hb_compReservedName( char * ); /* macro compiler */ + +typedef struct HB_CBVAR_ /* This structure holds local variables declared in a codeblock */ +{ + char * szName; + BYTE bType; + struct HB_CBVAR_ * pNext; +} HB_CBVAR, *HB_CBVAR_PTR; + +typedef struct HB_PCODE_INFO_ /* compiled pcode container */ +{ + BYTE * pCode; /* pointer to a memory block where pcode is stored */ + ULONG lPCodeSize; /* total memory size for pcode */ + ULONG lPCodePos; /* actual pcode offset */ + struct HB_PCODE_INFO_ *pPrev; + HB_CBVAR_PTR pLocals; +} HB_PCODE_INFO, * HB_PCODE_INFO_PTR; + +typedef struct HB_MACRO_ /* a macro compiled pcode container */ +{ + char * string; /* compiled string */ + ULONG length; /* length of the string */ + ULONG pos; /* current position inside of compiled string */ + int Flags; /* some flags we may need */ + int status; /* status of compilation */ + HB_PCODE_INFO_PTR pCodeInfo; /* pointer to pcode buffer and info */ + void * pParseInfo; /* data needed by the parser - it should be 'void *' to allow different implementation of macr compiler */ + BOOL bName10; /* are we limiting identifier names to 10 chars ? */ + BOOL bShortCuts; /* are we using logical shorcuts (in OR/AND) */ + PHB_SYMB pSymbols; /* local symbol table */ +} HB_MACRO, * HB_MACRO_PTR; + extern void hb_macroGetValue( HB_ITEM_PTR ); extern void hb_macroSetValue( HB_ITEM_PTR ); +extern void hb_macroPushSymbol( HB_ITEM_PTR ); +extern void hb_macroRun( HB_MACRO_PTR ); /* misc */ extern char * hb_version( USHORT uiMode ); diff --git a/harbour/include/hbexpr.c b/harbour/include/hbexpr.c index 65ef0077e3..c3bd514d64 100644 --- a/harbour/include/hbexpr.c +++ b/harbour/include/hbexpr.c @@ -79,7 +79,7 @@ #define hb_compGenPushLong( p1 ) hb_compGenPushLong( p1, HB_MACRO_PARAM ) #define hb_compGenPushNil( ) hb_compGenPushNil( p1, HB_MACRO_PARAM ) #define hb_compGenPushString( p1, p2 ) hb_compGenPushString( p1, p2, HB_MACRO_PARAM ) -#define hb_compGenPushSymbol( p1, p2 ) hb_compGenPushSymbol( p1, p2, HB_MACRO_PARAM ) +#define hb_compGenPushSymbol( p1 ) hb_compGenPushSymbol( p1, HB_MACRO_PARAM ) #define hb_compGenPushAliasedVar( p1, p2, p3, p4 ) hb_compGenPushAliasedVar( p1, p2, p3, p4, HB_MACRO_PARAM ) #define hb_compGenPopAliasedVar( p1, p2 , p3, p4 ) hb_compGenPopAliasedVar( p1, p2, p3, p4, HB_MACRO_PARAM ) #define hb_compGenPushFunRef( p1 ) hb_compGenPushFunRef( p1, HB_MACRO_PARAM ) @@ -2684,7 +2684,11 @@ static HB_EXPR_FUNC( hb_compExprUseAlias ) case HB_EA_LVALUE: break; case HB_EA_PUSH_PCODE: +#ifdef HB_MACRO_SUPPORT + hb_compGenPushSymbol( pSelf->value.asSymbol ); +#else hb_compGenPushSymbol( pSelf->value.asSymbol, FALSE ); +#endif break; case HB_EA_POP_PCODE: case HB_EA_PUSH_POP: diff --git a/harbour/include/macro.h b/harbour/include/macro.h index cb85fa0428..016e2fe4ed 100644 --- a/harbour/include/macro.h +++ b/harbour/include/macro.h @@ -56,29 +56,6 @@ #include "errorapi.h" #include "expropt.h" -typedef struct HB_PCODE_INFO_ -{ - BYTE * pCode; /* pointer to a memory block where pcode is stored */ - ULONG lPCodeSize; /* total memory size for pcode */ - ULONG lPCodePos; /* actual pcode offset */ - struct HB_PCODE_INFO_ *pPrev; - HB_CBVAR_PTR pLocals; -} HB_PCODE_INFO, * HB_PCODE_INFO_PTR; - -typedef struct HB_MACRO_ -{ - char * string; /* compiled string */ - ULONG length; /* length of the string */ - ULONG pos; /* current position inside of compiled string */ - int Flags; /* some flags we may need */ - int status; /* status of compilation */ - HB_PCODE_INFO_PTR pCodeInfo; /* pointer to pcode buffer and info */ - void * pParseInfo; /* data needed by the parser - it should be 'void *' to allow different implementation of macr compiler */ - BOOL bName10; /* are we limiting identifier names to 10 chars ? */ - BOOL bShortCuts; /* are we using logical shorcuts (in OR/AND) */ - PHB_SYMB pSymbols; /* local symbol table */ -} HB_MACRO, * HB_MACRO_PTR; - #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 */ diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index 98977b8493..3c9c37787e 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -1796,18 +1796,6 @@ void hb_compGenPushSymbol( char * szSymbolName, int iIsFunction ) USHORT wSym; PCOMSYMBOL pSym; - if( iIsFunction ) - { - char * pName = hb_compReservedName( szSymbolName ); - /* If it is reserved function name then we should truncate - * the requested name. - * We have to use passed szSymbolName so we can latter deallocate it - * (pName points to static data) - */ - if( pName ) - szSymbolName[ strlen( pName ) ] ='\0'; - } - pSym = hb_compSymbolFind( szSymbolName, &wSym ); if( ! pSym ) /* the symbol was not found on the symbol table */ { diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 2a251e9435..fff01478f5 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -100,6 +100,8 @@ TrueValue "."[t|y]"." FalseValue "."[f|n]"." Array {Identifier}[ \t]*"[" +MacroVarArray {MacroVar}[ \t]*"[" +MacroTxtArray ({MacroEnd}|{MacroId}|{MacroTxt})[ \t]*"[" AtArray "}"[ \t]*"[" ExpArray ")"[ \t]*"[" SubArray "]"[ \t]*"[" @@ -759,7 +761,7 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "#"{Separator}*"line" return LINE; -"loca"|"local" { +"loca"|"local" { yylval.string = hb_strupr( hb_strdup( yytext ) ); BEGIN LOCAL_; } @@ -1226,6 +1228,48 @@ Separator {SpaceTab} } } +{MacroVarArray} { + if( ! i_INDEX_STATE ) + { + BEGIN INDEX; + i_INDEX_STATE = 1; + } + + unput( '[' ); + yyleng--; + + /* Remove optional white space between Identifier and Index */ + while( yytext[ yyleng - 1 ] < 48 ) + yyleng--; + + yytext[yyleng] = 0; + if( yytext[ yyleng-1 ] == '.' ) + yytext[ yyleng-1 ] = '\0'; + yylval.string = hb_strupr( hb_strdup( yytext+1 ) ); + hb_comp_iState = MACROVAR; + return MACROVAR; + } + +{MacroTxtArray} { + if( ! i_INDEX_STATE ) + { + BEGIN INDEX; + i_INDEX_STATE = 1; + } + + unput( '[' ); + yyleng--; + + /* Remove optional white space between Identifier and Index */ + while( yytext[ yyleng - 1 ] < 48 ) + yyleng--; + + yytext[yyleng] = 0; + yylval.string = hb_strupr( hb_strdup( yytext ) ); + hb_comp_iState = MACROTEXT; + return MACROTEXT; + } + {ExpArray} { /* Must be recursive */ if( ! i_INDEX_STATE ) @@ -1269,7 +1313,7 @@ Separator {SpaceTab} return '}'; } -{MacroVar} { +{MacroVar} { if( yytext[ yyleng-1 ] == '.' ) yytext[ yyleng-1 ] = '\0'; yylval.string = hb_strupr( hb_strdup( yytext+1 ) ); @@ -1277,26 +1321,26 @@ Separator {SpaceTab} return MACROVAR; } -{MacroEnd} { +{MacroEnd} { yylval.string = hb_strupr( hb_strdup( yytext ) ); hb_comp_iState = MACROTEXT; return MACROTEXT; } -{MacroId} { +{MacroId} { yylval.string = hb_strupr( hb_strdup( yytext ) ); hb_comp_iState = MACROTEXT; return MACROTEXT; } -{MacroTxt} { +{MacroTxt} { yylval.string = hb_strupr( hb_strdup( yytext ) ); hb_comp_iState = MACROTEXT; return MACROTEXT; } -{Identifier} { +{Identifier} { if( hb_comp_bRestrictSymbolLength && strlen( yytext ) > 10 ) { yytext[ 10 ] = 0; diff --git a/harbour/source/macro/macro.c b/harbour/source/macro/macro.c index aafa5696ca..6c270a5917 100644 --- a/harbour/source/macro/macro.c +++ b/harbour/source/macro/macro.c @@ -105,7 +105,12 @@ static BOOL hb_macroCheckParam( HB_ITEM_PTR pItem ) return bValid; } -static void hb_macroRun( HB_MACRO_PTR pMacro ) +/* Executes pcode compiled by macro compiler + * + * pMacro is a pointer to HB_MACRO structure created by macro compiler + * + */ +void hb_macroRun( HB_MACRO_PTR pMacro ) { HB_TRACE(HB_TR_DEBUG, ("hb_macroRun(%p)", pMacro)); @@ -129,6 +134,44 @@ static void hb_macroSyntaxError( HB_MACRO_PTR pMacro ) } } +/* Check if passed string is a valid function name + */ +static BOOL hb_macroIsIdent( char * szString ) +{ + char * pTmp = szString; + + /* NOTE: This uses _a-zA-Z0-9 pattern to check for a valid name + */ + if( *pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') ) + { + ++pTmp; + while( *pTmp && (*pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') || (*pTmp >= '0' && *pTmp <= '9')) ) + ++pTmp; + } + + /* the name was valid if pTmp is at the end of a string + */ + return (*pTmp ? FALSE : TRUE ); +} + +/* Replace all nested macro operators + */ +static char * hb_macroTextSubst( char * szString ) +{ + char * szText; + ULONG ulLen; + + HB_TRACE(HB_TR_DEBUG, ("hb_macroTextSubst(%s)", szString)); + +/* TODO: Nested macro or complex macro ( e.g. ¯o¯o2.end ) + */ + ulLen = strlen( szString ) + 1; + szText = (char *) hb_xgrab( ulLen ); + memcpy( szText, szString, ulLen ); + + return szText; +} + /* NOTE: * This will be called when macro variable or macro expression is @@ -214,6 +257,33 @@ HB_MACRO_PTR hb_macroCompile( char * szString ) return pMacro; } +void hb_macroPushSymbol( HB_ITEM_PTR pItem ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_macroGetValue(%p)", pItem)); + + if( hb_macroCheckParam( pItem ) ) + { + HB_MACRO struMacro; + char * szString; + + szString = hb_macroTextSubst( pItem->item.asString.value ); + + hb_stackPop(); /* remove compiled string */ + if( hb_macroIsIdent( szString ) ) + { + HB_DYNS_PTR pDynSym; + + pDynSym = hb_dynsymGet( szString ); + /* NOTE: checking for valid function name is done in hb_vmDo() + */ + hb_vmPushSymbol( pDynSym->pSymbol ); + + hb_xfree( szString ); + } + else + hb_macroSyntaxError( &struMacro ); + } +} /* ************************************************************************* */ @@ -312,25 +382,11 @@ void hb_compMemvarGenPCode( BYTE bPCode, char * szVarName, HB_MACRO_DECL ) } /* generates the pcode to push a symbol on the virtual machine stack */ -void hb_compGenPushSymbol( char * szSymbolName, int iIsFunction, HB_MACRO_DECL ) +void hb_compGenPushSymbol( char * szSymbolName, HB_MACRO_DECL ) { HB_DYNS_PTR pSym; - if( iIsFunction ) - { - char * pName = hb_compReservedName( szSymbolName ); - /* If it is reserved function name then we should truncate - * the requested name. - * We have to use passed szSymbolName so we can latter deallocate it - * (pName points to static data) - */ - if( pName ) - pSym = hb_dynsymGet( pName ); - else - pSym = hb_dynsymGet( szSymbolName ); - } - else - pSym = hb_dynsymGet( szSymbolName ); + pSym = hb_dynsymGet( szSymbolName ); hb_compGenPCode1( HB_P_MPUSHSYM, HB_MACRO_PARAM ); hb_compGenPCodeN( ( BYTE * ) &pSym, sizeof( pSym ), HB_MACRO_PARAM ); } @@ -434,7 +490,7 @@ void hb_compGenPopAliasedVar( char * szVarName, } else { /* database alias */ - hb_compGenPushSymbol( hb_strdup( szAlias ), 0, HB_MACRO_PARAM ); + hb_compGenPushSymbol( hb_strdup( szAlias ), HB_MACRO_PARAM ); hb_compMemvarGenPCode( HB_P_MPOPALIASEDFIELD, szVarName, HB_MACRO_PARAM ); } } @@ -528,7 +584,7 @@ void hb_compGenPushAliasedVar( char * szVarName, } else { /* database alias */ - hb_compGenPushSymbol( hb_strdup( szAlias ), 0, HB_MACRO_PARAM ); + hb_compGenPushSymbol( hb_strdup( szAlias ), HB_MACRO_PARAM ); hb_compMemvarGenPCode( HB_P_MPUSHALIASEDFIELD, szVarName, HB_MACRO_PARAM ); } } @@ -571,10 +627,10 @@ void hb_compGenPushFunCall( char * szFunName, HB_MACRO_DECL ) { /* Abbreviated function name was used - change it for whole name */ - hb_compGenPushSymbol( szFunction, 1, HB_MACRO_PARAM ); + hb_compGenPushSymbol( szFunction, HB_MACRO_PARAM ); } else - hb_compGenPushSymbol( szFunName, 1, HB_MACRO_PARAM ); + hb_compGenPushSymbol( szFunName, HB_MACRO_PARAM ); } /* generates the pcode to push a string on the virtual machine stack */ diff --git a/harbour/source/macro/macro.l b/harbour/source/macro/macro.l index 618164367e..1356bd8b89 100644 --- a/harbour/source/macro/macro.l +++ b/harbour/source/macro/macro.l @@ -110,6 +110,8 @@ MacroId {Identifier}({MacroVar}|{MacroEnd}) MacroTxt ({MacroVar}|{MacroEnd}|{MacroId})+ Array {Identifier}[ \t]*"[" +MacroVarArray {MacroVar}[ \t]*"[" +MacroTxtArray ({MacroEnd}|{MacroId}|{MacroTxt})[ \t]*"[" AtArray "}"[ \t]*"[" ExpArray ")"[ \t]*"[" SubArray "]"[ \t]*"[" @@ -358,6 +360,48 @@ Separator {SpaceTab} } } +{MacroVarArray} { + if( ! i_INDEX_STATE ) + { + BEGIN INDEX; + i_INDEX_STATE = 1; + } + + unput( '[' ); + yyleng--; + + /* Remove optional white space between Identifier and Index */ + while( yytext[ yyleng - 1 ] < 48 ) + yyleng--; + + yytext[yyleng] = 0; + if( yytext[ yyleng-1 ] == '.' ) + yytext[ yyleng-1 ] = '\0'; + yylval_ptr->string = hb_strupr( hb_strdup( yytext+1 ) ); + hb_comp_iState = MACROVAR; + return MACROVAR; + } + +{MacroTxtArray} { + if( ! i_INDEX_STATE ) + { + BEGIN INDEX; + i_INDEX_STATE = 1; + } + + unput( '[' ); + yyleng--; + + /* Remove optional white space between Identifier and Index */ + while( yytext[ yyleng - 1 ] < 48 ) + yyleng--; + + yytext[yyleng] = 0; + yylval_ptr->string = hb_strupr( hb_strdup( yytext ) ); + hb_comp_iState = MACROTEXT; + return MACROTEXT; + } + {ExpArray} { /* Must be recursive */ if( ! i_INDEX_STATE ) diff --git a/harbour/source/macro/macro.y b/harbour/source/macro/macro.y index 218ae19adf..b77500f0c3 100644 --- a/harbour/source/macro/macro.y +++ b/harbour/source/macro/macro.y @@ -57,6 +57,11 @@ #define malloc hb_xgrab #undef free #define free hb_xfree +/* This is workaround of yyparse() declaration bug in bison.simple +*/ +#ifdef __GNUC__ +#undef __GNUC__ +#endif /* yacc/lex related definitions */ diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 1ae81a2a3e..4b8a24f8c4 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -935,6 +935,7 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) case HB_P_MACROSYMBOL: /* compile into a symbol name (used in function calls) */ + hb_macroPushSymbol( hb_stack.pPos - 1 ); w++; break; @@ -2514,7 +2515,12 @@ void hb_vmDo( USHORT uiParams ) if( pFunc ) pFunc(); else - hb_errInternal( 9999, "Invalid function pointer (%s) from hb_vmDo()", pSym->szName, NULL ); + { + /* Attempt to call an undefined function + * - generate unrecoverable runtime error + */ + hb_errRT_BASE( EG_NOFUNC, 1001, NULL, pSym->szName ); + } } while( hb_stack.pPos > hb_stack.pItems + wItemIndex ) @@ -3659,4 +3665,4 @@ HARBOUR HB___VMVARSGET( void ) { hb_itemReturn( s_aStatics.item.asArray.value->pItems + hb_stack.iStatics + hb_parni( 1 ) - 1 ); -} \ No newline at end of file +}