diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 9acb99f2f4..5ad5e6afef 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,10 +1,28 @@ +2000-11-07 22:50 UTC+0800 Ron Pinkas + * include/hberrors.h + + Added: #define HB_COMP_ERR_BLOCK 47 + * source/compiler/hbgenerr.c + + Added Error: "Code block contains both macro and declared symbol references" + + * source/compiler/harbour.c + * Made public: hb_compLocalGetPos() and hb_compStaticGetPos() + + * source/compiler/harbour.slx + + Added: char * hb_comp_SLX_LastBlock( BOOL bReset ) + + * source/compiler/harbour.sly + + Added logic to support Early Expansions of Macro within CodeBlock unless parenthesized. + + + tests/tstblock.prg + + New test of Early/Late expansion of Macros within CodeBlocks. + 2000-11-07 16:25 UTC+0100 Ryszard Glab *include/hbexpra.c *source/compiler/expropta.c *source/macro/macroa.c *fixed internal _GET_ optimization for macro variables - + *source/rtl/tgetint.prg *__GET uses macro operator if no initial value is passed and there is no set/get block diff --git a/harbour/include/hberrors.h b/harbour/include/hberrors.h index 9fa20bc08e..aa585091b6 100644 --- a/harbour/include/hberrors.h +++ b/harbour/include/hberrors.h @@ -91,6 +91,7 @@ extern "C" { #define HB_COMP_ERR_FUNC_ANNOUNCE 44 #define HB_COMP_ERR_JUMP_NOT_FOUND 45 #define HB_COMP_ERR_CASE 46 +#define HB_COMP_ERR_BLOCK 47 #define HB_COMP_WARN_AMBIGUOUS_VAR 1 #define HB_COMP_WARN_MEMVAR_ASSUMED 2 diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index 7a6ec97149..952e224079 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -53,10 +53,10 @@ static void hb_compInitVars( void ); static void hb_compGenOutput( int ); static void hb_compOutputFile( void ); +int hb_compLocalGetPos( char * szVarName ); /* returns the order + 1 of a local variable */ +int hb_compStaticGetPos( char *, PFUNCTION ); /* return if passed name is a static variable */ static int hb_compFieldGetPos( char *, PFUNCTION ); /* return if passed name is a field variable */ -static int hb_compLocalGetPos( char * szVarName ); /* returns the order + 1 of a local variable */ static int hb_compMemvarGetPos( char *, PFUNCTION ); /* return if passed name is a memvar variable */ -static int hb_compStaticGetPos( char *, PFUNCTION ); /* return if passed name is a static variable */ static void hb_compGenFieldPCode( BYTE , int, char *, PFUNCTION ); /* generates the pcode for database field */ static void hb_compGenVariablePCode( BYTE , char * ); /* generates the pcode for undeclared variable */ @@ -1288,7 +1288,7 @@ USHORT hb_compVariableGetPos( PVAR pVars, char * szVarName ) /* returns the orde return 0; } -static int hb_compLocalGetPos( char * szVarName ) /* returns the order + 1 of a variable if defined or zero */ +int hb_compLocalGetPos( char * szVarName ) /* returns the order + 1 of a variable if defined or zero */ { int iVar; PFUNCTION pFunc = hb_comp_functions.pLast; @@ -1423,7 +1423,7 @@ static int hb_compLocalGetPos( char * szVarName ) /* returns the order + 1 of a * All static variables are hold in a single array at runtime then positions * are numbered for whole PRG module. */ -static int hb_compStaticGetPos( char * szVarName, PFUNCTION pFunc ) +int hb_compStaticGetPos( char * szVarName, PFUNCTION pFunc ) { int iVar; diff --git a/harbour/source/compiler/harbour.slx b/harbour/source/compiler/harbour.slx index 3b2e4be589..95312627a5 100644 --- a/harbour/source/compiler/harbour.slx +++ b/harbour/source/compiler/harbour.slx @@ -42,20 +42,23 @@ #define YY_BUF_SIZE HB_PP_STR_SIZE static int iTexts = 0, iCloseSquare = 0, iWantsEOL, iWantsEXP, iWantsID, iWantsVAR; -static char * aTexts[ NUMERALS_PER_LINE ]; +static char *aTexts[ NUMERALS_PER_LINE ]; static unsigned char iIdentifier = 0; -static char* sIdOnHold; +static char *sIdOnHold, *s_sLastBlock = NULL; +char * hb_comp_SLX_LastBlock( BOOL bReset ); long hb_comp_SLX_Hex2L( char* sHex ); static int hb_comp_SLX_ElementToken( char* szToken, unsigned int iTokenLen ); static int hb_comp_SLX_InterceptAction( int iRet, char *sToken ); -static int hb_comp_SLX_CustomAction( int x, int aiHold[], int *ptr_iHold, BOOL *ptr_bIgnoreWords, int iLastToken, char *sToken ); +static int hb_comp_SLX_CustomAction( int x, int aiHold[], int *ptr_iHold, BOOL *ptr_bIgnoreWords, int iLastToken, char *sToken, char *s_szBuffer ); /* ----------------------------------------------------- Language Definitions. ---------------------------------------------------- */ /* Delimiters. */ ACCEPT_TOKEN_AND_DROP_DELIMITER_IF_ONE_OF_THESE( " \t" ); +#define HB_CHK_BLOCK LEX_CUSTOM_ACTION - 1 + ACCEPT_TOKEN_AND_RETURN_DELIMITERS { LEX_DELIMITER( ',' ) AS_TOKEN( ',' ), LEX_DELIMITER( '(' ) AS_TOKEN( '(' ), @@ -70,7 +73,7 @@ ACCEPT_TOKEN_AND_RETURN_DELIMITERS { LEX_DELIMITER( '<' ) AS_TOKEN( '<' + DONT_REDUCE ), LEX_DELIMITER( '>' ) AS_TOKEN( '>' + DONT_REDUCE ), LEX_DELIMITER( '!' ) AS_TOKEN( NOT + DONT_REDUCE ), - LEX_DELIMITER( '{' ) AS_TOKEN( '{' + DONT_REDUCE ), + LEX_DELIMITER( '{' ) AS_TOKEN( HB_CHK_BLOCK ), LEX_DELIMITER( '|' ) AS_TOKEN( '|' + DONT_REDUCE ), LEX_DELIMITER( '^' ) AS_TOKEN( POWER + DONT_REDUCE ), LEX_DELIMITER( '%' ) AS_TOKEN( '%' + DONT_REDUCE ), @@ -82,10 +85,10 @@ ACCEPT_TOKEN_AND_RETURN_DELIMITERS { }; /* Custom Intermediate Token needed to be expanded. */ -#define HB_LIT_ACT LEX_CUSTOM_ACTION - 1 -#define HB_NESTED_LIT LEX_CUSTOM_ACTION - 2 -#define HB_QOUT_ACT LEX_CUSTOM_ACTION - 3 -#define HB_RET_QOUT_LIT LEX_CUSTOM_ACTION - 4 +#define HB_LIT_ACT LEX_CUSTOM_ACTION - 2 +#define HB_NESTED_LIT LEX_CUSTOM_ACTION - 3 +#define HB_QOUT_ACT LEX_CUSTOM_ACTION - 4 +#define HB_RET_QOUT_LIT LEX_CUSTOM_ACTION - 5 /* Stream Pairs. */ DEFINE_STREAM_AS_ONE_OF_THESE { @@ -100,7 +103,7 @@ DEFINE_STREAM_AS_ONE_OF_THESE { START_NEW_LINE_IF_ONE_OF_THESE( "\n;" ); -#define HB_SELF LEX_CUSTOM_ACTION - 5 +#define HB_SELF LEX_CUSTOM_ACTION - 6 SELF_CONTAINED_WORDS_ARE { LEX_WORD( ".AND." ) AS_TOKEN( AND + DONT_REDUCE ), @@ -142,32 +145,32 @@ SELF_CONTAINED_WORDS_ARE { #define HB_WANTS_EXP LEX_CUSTOM_ACTION - 2048 /* When 2 identifiers are correct syntax like in class declaration, we have to temporarily store the 2nd identifier. */ -#define HB_ID_ON_HOLD LEX_CUSTOM_ACTION - 6 +#define HB_ID_ON_HOLD LEX_CUSTOM_ACTION - 7 -#define HB_MACRO_ERR LEX_CUSTOM_ACTION - 7 +#define HB_MACRO_ERR LEX_CUSTOM_ACTION - 8 -#define HB_INIT_PROC LEX_CUSTOM_ACTION - 8 -#define HB_INIT_FUNC LEX_CUSTOM_ACTION - 9 -#define HB_EXIT_PROC LEX_CUSTOM_ACTION - 10 -#define HB_EXIT_FUNC LEX_CUSTOM_ACTION - 11 -#define HB_STATIC_PROC LEX_CUSTOM_ACTION - 12 -#define HB_STATIC_FUNC LEX_CUSTOM_ACTION - 13 +#define HB_INIT_PROC LEX_CUSTOM_ACTION - 9 +#define HB_INIT_FUNC LEX_CUSTOM_ACTION - 10 +#define HB_EXIT_PROC LEX_CUSTOM_ACTION - 11 +#define HB_EXIT_FUNC LEX_CUSTOM_ACTION - 12 +#define HB_STATIC_PROC LEX_CUSTOM_ACTION - 13 +#define HB_STATIC_FUNC LEX_CUSTOM_ACTION - 14 -#define HB_DO_CASE_ID LEX_CUSTOM_ACTION - 14 +#define HB_DO_CASE_ID LEX_CUSTOM_ACTION - 15 -#define HB_DO_WHILE_ID LEX_CUSTOM_ACTION - 15 -#define HB_DO_WHILE_WITH LEX_CUSTOM_ACTION - 16 +#define HB_DO_WHILE_ID LEX_CUSTOM_ACTION - 16 +#define HB_DO_WHILE_WITH LEX_CUSTOM_ACTION - 17 -#define _WITH_ID_CR LEX_CUSTOM_ACTION - 17 -#define _WITH_ID_SEMI LEX_CUSTOM_ACTION - 18 +#define _WITH_ID_CR LEX_CUSTOM_ACTION - 18 +#define _WITH_ID_SEMI LEX_CUSTOM_ACTION - 19 -#define HB_IN LEX_CUSTOM_ACTION - 19 -#define HB_STEP LEX_CUSTOM_ACTION - 20 -#define HB_TO LEX_CUSTOM_ACTION - 21 -#define HB_WITH LEX_CUSTOM_ACTION - 22 +#define HB_IN LEX_CUSTOM_ACTION - 20 +#define HB_STEP LEX_CUSTOM_ACTION - 21 +#define HB_TO LEX_CUSTOM_ACTION - 22 +#define HB_WITH LEX_CUSTOM_ACTION - 23 /* When reservered words are used as Identifier. */ -#define HB_IDENTIFIER LEX_CUSTOM_ACTION - 23 +#define HB_IDENTIFIER LEX_CUSTOM_ACTION - 24 #define USE_KEYWORDS @@ -431,7 +434,7 @@ LANGUAGE_RULES_ARE { #define YY_INPUT( buf, result, max_size ) result = yy_lex_input( buf, max_size ); #undef CUSTOM_ACTION - #define CUSTOM_ACTION(x) x = hb_comp_SLX_CustomAction( x, aiHold, &iHold, &bIgnoreWords, iLastToken, (char*) sToken ) + #define CUSTOM_ACTION(x) x = hb_comp_SLX_CustomAction( x, aiHold, &iHold, &bIgnoreWords, iLastToken, (char*) sToken, s_szBuffer ) #undef STREAM_EXCEPTION #define STREAM_EXCEPTION( sPair, cChar ) \ @@ -743,7 +746,7 @@ long hb_comp_SLX_Hex2L( char* sHex ) return lSum; } -int hb_comp_SLX_CustomAction( int x, int aiHold[], int *ptr_iHold, BOOL *ptr_bIgnoreWords, int iLastToken, char *sToken ) +int hb_comp_SLX_CustomAction( int x, int aiHold[], int *ptr_iHold, BOOL *ptr_bIgnoreWords, int iLastToken, char *sToken, char *s_szBuffer ) { DEBUG_INFO( printf( "Custom Action for %i\n", x ) ); @@ -784,6 +787,51 @@ int hb_comp_SLX_CustomAction( int x, int aiHold[], int *ptr_iHold, BOOL *ptr_bIg DEBUG_INFO( printf( "HB_SELF, Primary Identifier %s Increased to: %i\n", "SELF", iIdentifier ) ); return IDENTIFIER; + case HB_CHK_BLOCK : + if( s_sLastBlock == NULL ) + { + char *pTmp = (char *) s_szBuffer; + + /* Skip White Space. */ + while( *pTmp && ( *pTmp == ' ' || *pTmp == '\t' ) ) + { + pTmp++; + } + + if( *pTmp == '|' ) + { + unsigned int iBrackets = 1; + char cTmp; + + pTmp++; + while( *pTmp ) + { + if( *pTmp == '}' ) + { + iBrackets--; + if( iBrackets == 0 ) + { + break; + } + } + else if( *pTmp == '{' ) + { + iBrackets++; + } + pTmp++; + } + + pTmp++; + cTmp = *pTmp; + *pTmp = '\0'; + + s_sLastBlock = hb_compIdentifierNew( s_szBuffer - 1, TRUE ); + + *pTmp = cTmp; + } + } + return '{' + DONT_REDUCE; + case HB_LIT_ACT : yylval.string = hb_compIdentifierNew( sPair, TRUE ); return LITERAL + DONT_REDUCE ; @@ -944,3 +992,14 @@ int yy_lex_input( char *buffer, int iBufferSize ) return hb_pp_Internal( hb_comp_bPPO ? hb_comp_yyppo : NULL, buffer ); } + +char * hb_comp_SLX_LastBlock( BOOL bReset ) +{ + if( bReset && s_sLastBlock ) + { + //hb_xfree( s_sLastBlock ); + s_sLastBlock = NULL; + } + + return s_sLastBlock; +} diff --git a/harbour/source/compiler/harbour.sly b/harbour/source/compiler/harbour.sly index 059e1d81d4..34bb4bf669 100644 --- a/harbour/source/compiler/harbour.sly +++ b/harbour/source/compiler/harbour.sly @@ -118,7 +118,11 @@ static PTR_LOOPEXIT hb_comp_pLoops = NULL; static HB_RTVAR_PTR hb_comp_rtvars = NULL; static HB_EXPR_PTR pArrayIndexAsList = NULL, pGetArgList = NULL, pBaseArrayName = NULL; -static BOOL bTrancuateBaseArray = FALSE; +static BOOL bTrancuateBaseArray = FALSE, bBlock = FALSE, bBlockMacro = FALSE, bBlockDeclared = FALSE; + +extern int hb_compLocalGetPos( char * szVarName ); /* returns the order + 1 of a local variable */ +extern int hb_compStaticGetPos( char *, PFUNCTION ); /* return if passed name is a static variable */ +extern char * hb_comp_SLX_LastBlock( BOOL bReset ); char * hb_comp_szAnnounce = NULL; /* ANNOUNCEd procedure */ @@ -497,7 +501,13 @@ ArrayAtAlias : ArrayAt ALIASOP { $$ = $1; } /* Variables */ -Variable : IdentName { $$ = hb_compExprNewVar( $1 ); } +Variable : IdentName { + $$ = hb_compExprNewVar( $1 ); + if( bBlock && ( hb_compLocalGetPos( $1 ) || hb_compStaticGetPos( $1, hb_comp_functions.pLast ) ) ) + { + bBlockDeclared = TRUE; + } + } ; VarAlias : IdentName ALIASOP { $$ = hb_compExprNewAlias( $1 ); } @@ -505,8 +515,8 @@ VarAlias : IdentName ALIASOP { $$ = hb_compExprNewAlias( $1 ); } /* Macro variables */ -MacroVar : MACROVAR { $$ = hb_compExprNewMacro( NULL, '&', $1 ); } - | MACROTEXT { $$ = hb_compExprNewMacro( NULL, 0, $1 ); } +MacroVar : MACROVAR { $$ = hb_compExprNewMacro( NULL, '&', $1 ); if( bBlock ) bBlockMacro = TRUE } + | MACROTEXT { $$ = hb_compExprNewMacro( NULL, 0, $1 ); if( bBlock ) bBlockMacro = TRUE; } ; MacroVarAlias : MacroVar ALIASOP { $$ = $1; } @@ -980,12 +990,6 @@ ElemList : Argument { $$ = hb_compExprNewList( $1 ); } | ElemList ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } ; -CodeBlock : '{' '|' { $$ = hb_compExprNewCodeBlock(); } BlockNoVar - '|' BlockExpList '}' { $$ = $3; } - | '{' '|' { $$ = hb_compExprNewCodeBlock(); } BlockVarList - '|' BlockExpList '}' { $$ = $3; } - ; - Get : GET Variable { pGetArgList = hb_compExprNewArgList( $2 ); } ',' GetArgList ')' { $$ = hb_compExprNewFunCall( hb_compExprNewFunName( "__GET"), pGetArgList ); pGetArgList = NULL; } | GET AliasVar { pGetArgList = hb_compExprNewArgList( $2 ); } ',' GetArgList ')' @@ -1038,11 +1042,56 @@ GetAExt : { /* Nothing*/ } | ',' GetArgList ; +CodeBlock : '{' '|' { bBlock = TRUE; $$ = hb_compExprNewCodeBlock() } BlockNoVar '|' BlockExpList '}' + { + if( bBlockMacro ) + { + if( bBlockDeclared ) + { + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_BLOCK, NULL, NULL ); + $$ = $3; + } + else + { + $$ = hb_compExprNewMacro( hb_compExprNewString( hb_comp_SLX_LastBlock( FALSE ) ), 0, NULL ); + } + } + else + { + $$ = $3; + } + hb_comp_SLX_LastBlock( TRUE ); + bBlock = FALSE; bBlockMacro = FALSE; bBlockDeclared = FALSE; + } + + | '{' '|' { bBlock = TRUE; $$ = hb_compExprNewCodeBlock(); } BlockVarList '|' BlockExpList '}' + { + if( bBlockMacro ) + { + if( bBlockDeclared ) + { + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_BLOCK, NULL, NULL ); + $$ = $3; + } + else + { + $$ = hb_compExprNewMacro( hb_compExprNewString( hb_comp_SLX_LastBlock( FALSE ) ), 0, NULL ); + } + } + else + { + $$ = $3; + } + hb_comp_SLX_LastBlock( TRUE ); + bBlock = FALSE; bBlockMacro = FALSE; bBlockDeclared = FALSE; + } + ; + /* NOTE: This uses $-2 then don't use BlockExpList in other context */ -BlockExpList : Expression { $$ = hb_compExprAddListExpr( $-2, $1 ); } - | BlockExpList ',' Expression { $$ = hb_compExprAddListExpr( $-2, $3 ); } - ; +BlockExpList : Expression { $$ = hb_compExprAddListExpr( $-2, $1 ); } + | BlockExpList ',' Expression { $$ = hb_compExprAddListExpr( $-2, $3 ); } + ; /* NOTE: This is really not needed however it allows the use of $-2 item * in BlockExpList to refer the same rule defined in Codeblock diff --git a/harbour/source/compiler/hbgenerr.c b/harbour/source/compiler/hbgenerr.c index 83dca140ba..823a62a069 100644 --- a/harbour/source/compiler/hbgenerr.c +++ b/harbour/source/compiler/hbgenerr.c @@ -86,6 +86,7 @@ char * hb_comp_szErrors[] = "ANNOUNCEd procedure \'%s\' must be a public symbol", "Jump PCode not found", "CASE or OTHERWISE does not match DO CASE", + "Code block contains both macro and declared symbol references" }; /* Table with parse warnings */