diff --git a/harbour/ChangeLog b/harbour/ChangeLog index ff7ed2f4af..1848c90cd8 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,19 @@ +19990518-01:45 Ryszard Glab + + * source/compiler/harbour.l, source/compiler/harbour.y + -added support for '-i' option (#include file search path) + however it doesn't use SET INCLUDE environment variable yet + -added error messages if unmatched ENDDO, ENDCASE, ENDIF, NEXT + is found + + * include/extend.h + -added forward declaration of CODEBLOCK structure and added + the proper type for pCodeblock member of ITEM structure + + * source/vm/hvm.c + -corrected pCodeblock type casting + -added C++ style declaration of HB_FIRSTSYMBOL and HB_LASTSYMBOL + 19990517-16:05 CET Eddie Runia * source/rtl/classes.c, source/rtl/tclass.prg, include/extend.h Initializers for DATA items added diff --git a/harbour/include/extend.h b/harbour/include/extend.h index b79a88a9a2..99d47386ec 100644 --- a/harbour/include/extend.h +++ b/harbour/include/extend.h @@ -46,6 +46,8 @@ void VirtualMachine( PBYTE pCode, PSYMBOL pSymbols ); /* invokes the virtual ma #define IT_NUMERIC ( IT_INTEGER | IT_LONG | IT_DOUBLE ) #define IT_ANY 0xFFFF +struct _CODEBLOCK; /* forward declaration */ + typedef struct /* items hold at the virtual machine stack */ { WORD wType; /* type of the item */ @@ -59,7 +61,7 @@ typedef struct /* items hold at the virtual machine stack */ int iLogical; /* logical values */ long lDate; /* date values */ PSYMBOL pSymbol; /* functions call symbol */ - BYTE * pCodeblock;/* pointer to a codeblock structure */ + struct _CODEBLOCK * pCodeblock;/* pointer to a codeblock structure */ WORD wItem; /* variable by reference, stack offset */ void * pBaseArray; /* array base */ } value; @@ -97,7 +99,7 @@ typedef struct } DYNSYM, * PDYNSYM; /* dynamic symbol structure */ /* internal structure for codeblocks */ -typedef struct +typedef struct _CODEBLOCK { BYTE * pCode; /* codeblock pcode */ PITEM pItems; /* table with referenced local variables */ diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 794ab6b9a6..50d3058c72 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -15,6 +15,7 @@ #include "y_tab.h" #include "hbsetup.h" /* main configuration file */ #include "hberrors.h" +#include "types.h" void yyerror( char * ); static void yyunput( int, char * ); @@ -43,8 +44,14 @@ void DefineKey( char * szKey ); /* add a new key to a #define expression */ void AddDefine( char * szDefine, char * szValue ); /* add a new define from the command line */ PDEFINE FindDef( char * szText ); /* finds a #define */ +/* variables defined in harbour.y */ extern int _iQuiet; extern int _iRestrictSymbolLength; +extern WORD _wSeqCounter; +extern WORD _wForCounter; +extern WORD _wIfCounter; +extern WORD _wWhileCounter; +extern WORD _wCaseCounter; PDEFINE pDefs = 0; /* support for #defines */ int iLine = 1; @@ -285,9 +292,23 @@ Separator {SpaceTab}|{Comment}|{LineCont} %{ /* ************************************************************************ */ %} -"else" _iState =ELSE; return ELSE; /* ELSE can be used in one contex only */ -"elseif" _iState =ELSEIF; return ELSEIF; /* ELSEIF can be used in one context only */ -"end"{Separator}+"sequ"("ence"|"enc"|"en"|"e")? return END; +"else" { /* ELSE can be used in one context only */ + if( _wIfCounter == 0 ) + GenError( ERR_UNMATCHED_ELSE, NULL, NULL ); + _iState =ELSE; + return ELSE; + } +"elseif" { /* ELSEIF can be used in one context only */ + if( _wIfCounter == 0 ) + GenError( ERR_UNMATCHED_ELSEIF, NULL, NULL ); + _iState =ELSEIF; + return ELSEIF; + } +"end"{Separator}+"sequ"("ence"|"enc"|"en"|"e")? { + if( _wSeqCounter == 0 ) + GenError( ERR_ENDIF, NULL, NULL ); + return END; + } "end" { BEGIN END_; } {Separator}*[\[\(] { /* array, function call */ yy_lex_count_lf(); @@ -342,9 +363,21 @@ Separator {SpaceTab}|{Comment}|{LineCont} %{ /* ************************************************************************ */ %} -"endif" return ENDIF; -"endcase" return ENDCASE; -"enddo" return ENDDO; +"endif"|"endi" { /* ENDIF can be used in one context only */ + if( _wIfCounter == 0 ) + GenError( ERR_ENDIF, NULL, NULL ); + return ENDIF; + } +"endc"("ase"|"as"|"a")? { /* ENDCASE can be used in one context only */ + if( _wWhileCounter == 0 ) + GenError( ERR_ENDCASE, NULL, NULL ); + return ENDCASE; + } +"enddo"|"endd" { /* ENDDO can be used in one context only */ + if( _wWhileCounter == 0 ) + GenError( ERR_ENDDO, NULL, NULL ); + return ENDDO; + } "exit"/[\n\;] return EXITLOOP; "exit" return EXIT; "extern"|"external" _iState =EXTERN; return EXTERN; @@ -368,6 +401,8 @@ Separator {SpaceTab}|{Comment}|{LineCont} if( _iState == LOOKUP ) { /* it is first item in the line */ ++iLine; + if( _wForCounter == 0 ) + GenError( ERR_NEXTFOR, NULL, NULL ); _iState =NEXT; return NEXT; } @@ -413,6 +448,8 @@ Separator {SpaceTab}|{Comment}|{LineCont} {Separator}*. { /* an identifier follows NEXT statement */ yy_lex_count_lf(); BEGIN 0; + if( _wForCounter == 0 ) + GenError( ERR_NEXTFOR, NULL, NULL ); unput( yytext[ yyleng-1 ] ); _iState =NEXT; return NEXT; @@ -560,8 +597,8 @@ Separator {SpaceTab}|{Comment}|{LineCont} "^=" _iState =EXPEQ; return EXPEQ; "%=" _iState =MODEQ; return MODEQ; "**"|"^" _iState =POWER; return POWER; -"."[t|y]"." return TRUE; -"."[f|n]"." return FALSE; +"."[t|y]"." return TRUEVALUE; +"."[f|n]"." return FALSEVALUE; ".and." return AND; ".or." return OR; "!"|".not." return NOT; diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 62859ff03d..7586b61a3c 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -55,7 +55,12 @@ typedef struct int iFiles; /* number of files currently opened */ } FILES; /* structure to control several opened PRGs and CHs */ -int Include( char * szFileName ); /* end #include support */ +typedef struct _PATHNAMES { /* the list of pathnames to search with #include */ + char *szPath; + struct _PATHNAMES *pNext; +} PATHNAMES; + +int Include( char * szFileName, PATHNAMES *pSearchPath ); /* end #include support */ /* * flags for bFlags member @@ -233,7 +238,10 @@ char * _szErrors[] = { "Statement not allowed outside of procedure or function", "ENDDO does not match WHILE", "ENDCASE does not match DO CASE", "NEXT does not match FOR", - "Syntax error: \'%s\'" + "ELSE does not match IF", + "ELSEIF does not match IF", + "Syntax error: \'%s\'", + "Unclosed control structures" }; /* Table with reserved functions names @@ -330,6 +338,7 @@ int EXTERNAL_LINKAGE sz_compare4( const void *pLookup, const void *pReserved ) #define RESERVED_FUNC(szName) \ bsearch( (szName), _szReservedFun, RESERVED_FUNCTIONS, sizeof(char*), sz_compare4 ) + FILES files; FUNCTIONS functions, funcalls; PFUNCTION _pInitFunc; @@ -341,12 +350,18 @@ int _iSyntaxCheckOnly = 0; /* syntax check only */ int _iLanguage = LANG_C; /* default Harbour generated output language */ int _iRestrictSymbolLength = 0; /* generate 10 chars max symbols length */ int _iShortCuts = 1; /* .and. & .or. expressions shortcuts */ +WORD _wSeqCounter = 0; +WORD _wForCounter = 0; +WORD _wIfCounter = 0; +WORD _wWhileCounter = 0; +WORD _wCaseCounter = 0; #ifdef OBJ_GENERATION int _iObj32 = 0; /* generate OBJ 32 bits */ #endif WORD _wStatics = 0; /* number of defined statics variables on the PRG */ PRETURN pReturns = 0; /* list of multiple returns from a function */ PEXTERN pExterns = 0; +PATHNAMES *_pIncludePath = NULL; %} @@ -360,7 +375,7 @@ PEXTERN pExterns = 0; }; %token FUNCTION PROCEDURE IDENTIFIER RETURN NIL DOUBLE INASSIGN INTEGER INTLONG -%token LOCAL STATIC IF ELSE ELSEIF END ENDIF LITERAL TRUE FALSE +%token LOCAL STATIC IF ELSE ELSEIF END ENDIF LITERAL TRUEVALUE FALSEVALUE %token INCLUDE EXTERN INIT EXIT AND OR NOT PUBLIC EQ NE1 NE2 %token INC DEC ALIAS DOCASE CASE OTHERWISE ENDCASE ENDDO MEMVAR %token WHILE EXIT LOOP END FOR NEXT TO STEP LE GE FIELD IN PARAMETERS @@ -424,7 +439,7 @@ Source : Crlf | Source MEMVAR IdentList ; -Include : NE1 INCLUDE LITERAL { if( ! Include( $3 ) ) +Include : NE1 INCLUDE LITERAL { if( ! Include( $3, _pIncludePath ) ) GenError( ERR_CANT_OPEN_INCLUDE, $3, NULL ); } Crlf ; @@ -689,8 +704,8 @@ Operators : Expression '=' Expression { GenPCode1( _EQUAL ); } /* compare | VarAssign ; -Logical : TRUE { $$ = 1; } - | FALSE { $$ = 0; } +Logical : TRUEVALUE { $$ = 1; } + | FALSEVALUE { $$ = 0; } ; Array : '{' ElemList '}' { GenArray( $2 ); } @@ -774,7 +789,7 @@ IfEndif : IfBegin EndIf { JumpHere( $1 ); } | IfBegin IfElseIf IfElse EndIf { JumpHere( $1 ); FixElseIfs( $2 ); } ; -IfBegin : IF Expression Crlf { $$ = JumpFalse( 0 ); } IfStats +IfBegin : IF Expression Crlf { $$ = JumpFalse( 0 ); ++_wIfCounter; } IfStats { $$ = Jump( 0 ); JumpHere( $4 ); } ; @@ -788,8 +803,8 @@ IfElseIf : ELSEIF Expression Crlf { $$ = JumpFalse( 0 ); } IfStats { $$ = GenElseIf( $1, Jump( 0 ) ); JumpHere( $5 ); } ; -EndIf : ENDIF - | END +EndIf : ENDIF { --_wIfCounter; } + | END { --_wIfCounter; } ; IfStats : /* no statements */ @@ -813,11 +828,11 @@ DoCase : DoCaseBegin EndCase { FixElseIfs( $2 ); } ; -EndCase : ENDCASE - | END +EndCase : ENDCASE { --_wCaseCounter; } + | END { --_wCaseCounter; } ; -DoCaseBegin : DOCASE Crlf +DoCaseBegin : DOCASE Crlf { ++_wCaseCounter; } ; Cases : CASE Expression Crlf { $$ = JumpFalse( 0 ); Line(); } CaseStmts { $$ = GenElseIf( 0, Jump( 0 ) ); JumpHere( $4 ); Line(); } @@ -833,14 +848,14 @@ CaseStmts : /* no statements */ DoWhile : WhileBegin Expression Crlf { $$ = JumpFalse( 0 ); } { Jump( $1 - functions.pLast->lPCodePos ); } - EndWhile { JumpHere( $4 ); } + EndWhile { JumpHere( $4 ); --_wWhileCounter; } | WhileBegin Expression Crlf { $$ = JumpFalse( 0 ); Line(); } WhileStatements { Jump( $1 - functions.pLast->lPCodePos ); } - EndWhile { JumpHere( $4 ); } + EndWhile { JumpHere( $4 ); --_wWhileCounter; } ; -WhileBegin : WHILE { $$ = functions.pLast->lPCodePos; } +WhileBegin : WHILE { $$ = functions.pLast->lPCodePos; ++_wWhileCounter; } ; WhileStatements : Statement @@ -851,7 +866,7 @@ EndWhile : END | ENDDO ; -ForNext : FOR IDENTIFIER ForAssign Expression { PopId( $2 ); $$ = functions.pLast->lPCodePos; } +ForNext : FOR IDENTIFIER ForAssign Expression { PopId( $2 ); $$ = functions.pLast->lPCodePos; ++_wForCounter;} TO Expression { PushId( $2 ); } StepExpr Crlf { GenPCode1( _FORTEST ); $$ = JumpTrue( 0 ); PushId( $2 ) } ForStatements { GenPCode1( _PLUS ); PopId( $2 ); Jump( $5 - functions.pLast->lPCodePos ); JumpHere( $11 ); } @@ -865,23 +880,23 @@ StepExpr : /* default step expression */ { PushInteger( 1 ); } | STEP Expression ; -ForStatements : ForStat NEXT - | ForStat NEXT IDENTIFIER - | NEXT - | NEXT IDENTIFIER +ForStatements : ForStat NEXT { --_wForCounter; } + | ForStat NEXT IDENTIFIER { --_wForCounter; } + | NEXT { --_wForCounter; } + | NEXT IDENTIFIER { --_wForCounter; } ; ForStat : Statements { Line(); } ; -BeginSeq : BEGINSEQ Crlf +BeginSeq : BEGINSEQ Crlf { ++_wSeqCounter; } RecoverSeq - END + END { --_wSeqCounter; } - | BEGINSEQ Crlf + | BEGINSEQ Crlf { ++_wSeqCounter; } Statements RecoverSeq - END + END { --_wSeqCounter; } ; RecoverSeq : /* no recover */ @@ -955,7 +970,7 @@ int harbour_main( int argc, char * argv[] ) { int iStatus = 0, iArg = 1; char szFileName[ _POSIX_PATH_MAX ]; /* filename to parse */ - char *szPath =""; + char *szOutPath =""; FILENAME *pFileName =NULL; if( argc > 1 ) @@ -1030,6 +1045,27 @@ int harbour_main( int argc, char * argv[] ) } break; + case 'i': + case 'I': + { + PATHNAMES *pPath = _pIncludePath; + + if( pPath ) + { + while( pPath->pNext ) + pPath =pPath->pNext; + pPath->pNext =(PATHNAMES *)OurMalloc( sizeof(PATHNAMES) ); + pPath =pPath->pNext; + } + else + { + _pIncludePath = pPath =(PATHNAMES *)OurMalloc( sizeof(PATHNAMES) ); + } + pPath->pNext = NULL; + pPath->szPath = argv[ iArg ]+2; + } + break; + case 'l': case 'L': _iLineNumbers = 0; @@ -1042,7 +1078,7 @@ int harbour_main( int argc, char * argv[] ) case 'o': case 'O': - szPath = argv[ iArg ]+2; + szOutPath = argv[ iArg ]+2; break; case 'q': @@ -1107,7 +1143,7 @@ int harbour_main( int argc, char * argv[] ) atexit( close_on_exit ); - if( Include( szFileName ) ) + if( Include( szFileName, NULL ) ) { FunDef( strupr( strdup( pFileName->name ) ), FS_PUBLIC, FUN_PROCEDURE ); yyparse(); @@ -1120,7 +1156,7 @@ int harbour_main( int argc, char * argv[] ) if( ! _iSyntaxCheckOnly && ! _iObj32 ) #else if( ! _iSyntaxCheckOnly ) -#endif +#endif { if( _pInitFunc ) { @@ -1138,7 +1174,7 @@ int harbour_main( int argc, char * argv[] ) } /* we create a the output file */ - pFileName->path = szPath; + pFileName->path = szOutPath; switch( _iLanguage ) { case LANG_C: @@ -1205,6 +1241,7 @@ void PrintUsage( char * szSelf ) "\t\t\t /gj (Java) --> \n" "\t\t\t /gp (Pascal) --> \n" "\t\t\t /gr (Resources) --> \n" + "\t/i\tadd #include file search path\n" "\t/l\t\tsuppress line number information\n" "\t/n\t\tno implicit starting procedure\n" "\t/o\tobject file drive and/or path\n" @@ -1495,12 +1532,35 @@ PCOMSYMBOL AddSymbol( char * szSymbolName ) return pSym; } -int Include( char * szFileName ) +int Include( char * szFileName, PATHNAMES *pSearch ) { PFILE pFile; - if( ! ( yyin = fopen( szFileName, "r" ) ) ) + if( ! ( yyin = fopen( szFileName, "r" ) ) ) + { + if( pSearch ) + { + FILENAME *pFileName =SplitFilename( szFileName ); + char szFName[ _POSIX_PATH_MAX ]; /* filename to parse */ + + pFileName->name =szFileName; + pFileName->extension =NULL; + while( pSearch && !yyin ) + { + pFileName->path =pSearch->szPath; + MakeFilename( szFName, pFileName ); + if( ! ( yyin = fopen( szFName, "r" ) ) ) + { + pSearch = pSearch->pNext; + if( ! pSearch ) + return 0; + } + } + OurFree( pFileName ); + } + else return 0; + } if( ! _iQuiet ) printf( "\nparsing file %s\n", szFileName ); @@ -2934,6 +2994,9 @@ void FixReturns( void ) /* fixes all last defined function returns jumps offsets } pReturns = 0; } + + if( (_wSeqCounter + _wWhileCounter + _wIfCounter + _wCaseCounter + _wForCounter) > 0 ) + GenError( ERR_UNCLOSED_STRU, NULL, NULL ); } void Function( BYTE bParams ) diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 2272b2a24f..8c881dcbdc 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -138,8 +138,12 @@ typedef struct PSYMBOL pSymbols; /* module local symbol table address */ } OBJSYMBOLS, * POBJSYMBOLS; /* structure used from Harbour generated OBJs */ +#ifdef __cplusplus +extern "C" POBJSYMBOLS HB_FIRSTSYMBOL, HB_LASTSYMBOL; +#else extern POBJSYMBOLS HB_FIRSTSYMBOL, HB_LASTSYMBOL; #endif +#endif STACK stack; int iHBDEBUG = 0; /* if 1 traces the virtual machine activity */ @@ -1610,7 +1614,7 @@ void PushBlock( BYTE * pCode, WORD wSize, WORD wParam, PSYMBOL pSymbols ) { ItemRelease( stack.pPos ); stack.pPos->wType = IT_BLOCK; - stack.pPos->value.pCodeblock = (BYTE *)CodeblockNew( pCode, wSize, pSymbols, + stack.pPos->value.pCodeblock = CodeblockNew( pCode, wSize, pSymbols, stack.iStatics, stack.pBase - stack.pItems ); /* store the stack base of function where the codeblock was defined */ stack.pPos->wBase = stack.pBase - stack.pItems;