diff --git a/harbour/ChangeLog b/harbour/ChangeLog index f32ed87db8..671d752804 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,35 @@ +19990520-01:40 Ryszard Glab + + * source/compiler/harbour.y + -corrected support for INCLUDE environment variable (the last path + was ignored) + -definition of path delimiter and path list separator was moved to + hbsetup.h file. OS_PATH_DELIMITER and OS_PATH_LIST_SEPARATOR are + now defined. + -changed #define from OBJ_GENERATION to HARBOUR_OBJ_GENERATION + + * source/compiler/harbour.l + -EXIT keyword is now properly supported + + * source/vm/hvm.c + -changed #define from OBJ_GENERATION to HARBOUR_OBJ_GENERATION + -changed #define from HARBOUR_MAIN to HARBOUR_START_PROCEDURE + + * include/hbsetup.h + -changed #define from OBJ_GENERATION to HARBOUR_OBJ_GENERATION + -changed #define from HARBOUR_MAIN to HARBOUR_START_PROCEDURE + -added #define OS_PATH_DELIMITER + -added #define OS_PATH_LIST_SEPARATOR + + * include/hberrors.h + -added #define ERR_UNMATCHED_EXIT + + * source/rtl/environ.c + -corrected support for Watcom C/C++ compiler + + * tests/working/keywords.prg + -added test code for EXIT keyword + 19990519-21:22 CET Eddie Runia * makefile.b16 Patrick patch (command-line too long entered) diff --git a/harbour/include/hberrors.h b/harbour/include/hberrors.h index 032ed01b55..030e2c49bb 100644 --- a/harbour/include/hberrors.h +++ b/harbour/include/hberrors.h @@ -21,5 +21,6 @@ #define ERR_UNMATCHED_ELSEIF 16 #define ERR_SYNTAX 17 #define ERR_UNCLOSED_STRU 18 +#define ERR_UNMATCHED_EXIT 19 void GenError( int, char*, char * ); /* generic parsing error management function */ diff --git a/harbour/include/hbsetup.h b/harbour/include/hbsetup.h index efb4d2ea3e..eab3c461e2 100644 --- a/harbour/include/hbsetup.h +++ b/harbour/include/hbsetup.h @@ -16,15 +16,19 @@ * * By default we are using automatic lookup (symbol not defined) */ -/*#define HARBOUR_MAIN "MAIN"*/ +#define HARBOUR_START_PROCEDURE "MAIN" -/* This symbol defines if we want an ability to create and link OBJ files +/* This symbol defines if we want an ability to create and link OBJ files * generated by Harbour compiler * * By default it is disabled (symbol is not defined) */ -/*#define OBJ_GENERATION*/ +/*#define HARBOUR_OBJ_GENERATION*/ +/* Operating system specific definitions + */ +#define OS_PATH_DELIMITER '\\' +#define OS_PATH_LIST_SEPARATOR ';' -#endif \ No newline at end of file +#endif diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 189ddad6c4..173a2b3b81 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -97,7 +97,7 @@ Separator {SpaceTab}|{Comment}|{LineCont} %x COMMENT3 DEFINE DEFINE_PARAMS DEFINE_EXPR %x IFDEF IFNDEF STRING1 STRING2 STRING3 -%x NEXT_ BREAK_ CASE_ DO_ WHILE_ WITH_ END_ +%x NEXT_ BREAK_ CASE_ DO_ WHILE_ WITH_ END_ EXIT_ %s INDEX %% @@ -305,7 +305,7 @@ Separator {SpaceTab}|{Comment}|{LineCont} else { /* there is another item in line already */ yylval.string = strdup( "DO" ); - _iState =IDENTIFIER; + _iState =IDENTIFIER; return IDENTIFIER; } } @@ -339,6 +339,9 @@ Separator {SpaceTab}|{Comment}|{LineCont} GenError( ERR_ENDIF, NULL, NULL ); return END; } +%{ +/* ************************************************************************ */ +%} "end" { BEGIN END_; } {Separator}*[\[\(] { /* array, function call */ yy_lex_count_lf(); @@ -395,7 +398,7 @@ Separator {SpaceTab}|{Comment}|{LineCont} %} "endif"|"endi" { /* ENDIF can be used in one context only */ if( _wIfCounter == 0 ) - GenError( ERR_ENDIF, NULL, NULL ); + GenError( ERR_ENDIF, NULL, NULL ); return ENDIF; } "endc"("ase"|"as"|"a")? { /* ENDCASE can be used in one context only */ @@ -408,8 +411,56 @@ Separator {SpaceTab}|{Comment}|{LineCont} GenError( ERR_ENDDO, NULL, NULL ); return ENDDO; } -"exit"/[\n\;] return EXITLOOP; -"exit" return EXIT; +%{ +/* ************************************************************************ */ +%} +"exit" { BEGIN EXIT_; } +{Separator}*[\n] { /* EXIT last item in the line */ + yy_lex_count_lf(); + --iLine; + unput( yytext[ yyleng-1 ] ); + BEGIN 0; + if( _iState == LOOKUP ) + { /* it is first item in the line */ + if( _wForCounter == 0 && _wWhileCounter == 0 ) + GenError( ERR_UNMATCHED_EXIT, NULL, NULL ); + _iState =EXITLOOP; + return EXITLOOP; + } + else + { /* there is another item in line already */ + yylval.string = strdup( "EXIT" ); + _iState =IDENTIFIER; + return IDENTIFIER; + } + } +{Separator}+[_a-zA-Z] { /* an identifier after the EXIT */ + yy_lex_count_lf(); + unput( yytext[ yyleng-1 ] ); + BEGIN 0; + if( _iState == LOOKUP ) + { /* it is first item in the line */ + _iState =EXIT; + return EXIT; + } + else + { /* there is another item in line already */ + yylval.string = strdup( "EXIT" ); + _iState =IDENTIFIER; + return IDENTIFIER; + } + } +{Separator}*. { /* any character (not identifier) after EXIT */ + yy_lex_count_lf(); + unput( yytext[ yyleng-1 ] ); + yylval.string = strdup( "EXIT" ); + BEGIN 0; + _iState =IDENTIFIER; + return IDENTIFIER; + } +%{ +/* ************************************************************************ */ +%} "extern"|"external" _iState =EXTERN; return EXTERN; "field"/[^(] _iState =FIELD; return FIELD; "for" _iState = FOR; return FOR; @@ -633,7 +684,7 @@ Separator {SpaceTab}|{Comment}|{LineCont} ".or." return OR; "!"|".not." return NOT; "::" unput( ':' ); unput( 'f' ); unput( 'l' ); unput( 'e' ); unput( 'S' ); -[,\;\{\}\|\#\&\:\<\>\[\]\(\)\@] return yytext[ 0 ]; +[,\;\{\}\|\#\&\:\<\>\[\]\(\)\@] _iState =OPERATOR; return yytext[ 0 ]; {InvalidNumber} GenError( ERR_NUMERIC_FORMAT, NULL, NULL ); diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index cfae332755..13802a78da 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -30,8 +30,7 @@ #endif /* TODO: #define this for various platforms */ -#define PATH_DELIMITER "/\\" -#define IS_PATH_SEP( c ) (strchr(PATH_DELIMITER, (c))!=NULL) +#define IS_PATH_SEP( c ) ( (c) == OS_PATH_DELIMITER ) #define OPT_DELIMITER "/-" #define IS_OPT_SEP( c ) (strchr(OPT_DELIMITER, (c))!=NULL) @@ -200,7 +199,7 @@ void GenJava( char *, char * ); /* generates the Java language output */ void GenPascal( char *, char * ); /* generates the Pascal language output */ void GenRC( char *, char * ); /* generates the RC language output */ void GenPortObj( char *, char * ); /* generates the portable objects */ -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION void GenObj32( char *, char * ); /* generates OBJ 32 bits */ #endif @@ -244,7 +243,8 @@ char * _szErrors[] = { "Statement not allowed outside of procedure or function", "ELSE does not match IF", "ELSEIF does not match IF", "Syntax error: \'%s\'", - "Unclosed control structures" + "Unclosed control structures", + "EXIT statement with no loop in sight" }; /* Table with reserved functions names @@ -359,7 +359,7 @@ WORD _wForCounter = 0; WORD _wIfCounter = 0; WORD _wWhileCounter = 0; WORD _wCaseCounter = 0; -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION int _iObj32 = 0; /* generate OBJ 32 bits */ #endif WORD _wStatics = 0; /* number of defined statics variables on the PRG */ @@ -837,7 +837,7 @@ EndCase : ENDCASE { --_wCaseCounter; } | END { --_wCaseCounter; } ; -DoCaseBegin : DOCASE Crlf { ++_wCaseCounter; } +DoCaseBegin : DOCASE { ++_wCaseCounter; } Crlf ; Cases : CASE Expression Crlf { $$ = JumpFalse( 0 ); Line(); } CaseStmts { $$ = GenElseIf( 0, Jump( 0 ) ); JumpHere( $4 ); Line(); } @@ -871,9 +871,9 @@ EndWhile : END | ENDDO ; -ForNext : FOR IDENTIFIER ForAssign Expression { PopId( $2 ); $$ = functions.pLast->lPCodePos; ++_wForCounter;} +ForNext : FOR IDENTIFIER ForAssign Expression { PopId( $2 ); $$ = functions.pLast->lPCodePos; ++_wForCounter; } TO Expression { PushId( $2 ); } - StepExpr Crlf { GenPCode1( _FORTEST ); $$ = JumpTrue( 0 ); PushId( $2 ) } + StepExpr Crlf { GenPCode1( _FORTEST ); $$ = JumpTrue( 0 ); PushId( $2 ); } ForStatements { GenPCode1( _PLUS ); PopId( $2 ); Jump( $5 - functions.pLast->lPCodePos ); JumpHere( $11 ); } ; @@ -1009,7 +1009,7 @@ int harbour_main( int argc, char * argv[] ) free( szDefText ); } break; -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION case 'f': case 'F': { @@ -1152,12 +1152,13 @@ int harbour_main( int argc, char * argv[] ) char * pDelim; pPath = szInclude = strdup( szInclude ); - while( (pDelim = strchr( pPath, ';' )) != NULL ) + while( (pDelim = strchr( pPath, OS_PATH_LIST_SEPARATOR )) != NULL ) { *pDelim ='\0'; AddSearchPath( pPath, &_pIncludePath ); pPath =pDelim + 1; } + AddSearchPath( pPath, &_pIncludePath ); } FunDef( strupr( strdup( pFileName->name ) ), FS_PUBLIC, FUN_PROCEDURE ); @@ -1167,7 +1168,7 @@ int harbour_main( int argc, char * argv[] ) fclose( yyin ); files.pLast =NULL; -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION if( ! _iSyntaxCheckOnly && ! _iObj32 ) #else if( ! _iSyntaxCheckOnly ) @@ -1223,7 +1224,7 @@ int harbour_main( int argc, char * argv[] ) break; } } -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION if( _iObj32 ) { pFileName->extension = ".obj"; @@ -1253,7 +1254,7 @@ void PrintUsage( char * szSelf ) printf( "Syntax: %s [options]\n" "\nOptions: \n" "\t/d[=]\t#define \n" -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION "\t/f\t\tgenerated object file\n" "\t\t\t /fobj32 --> Windows/Dos 32 bits OBJ\n" #endif @@ -1294,7 +1295,7 @@ FILENAME *SplitFilename( char *szFilename ) if( iSlashPos == 0 ) { /* root path -> \filename */ - pName->_buffer[ 0 ] =PATH_DELIMITER[ 0 ]; + pName->_buffer[ 0 ] =OS_PATH_DELIMITER; pName->_buffer[ 1 ] ='\x0'; pName->path =pName->_buffer; iPos =2; /* first free position after the slash */ @@ -1368,7 +1369,7 @@ char *MakeFilename( char *szFileName, FILENAME *pFileName ) */ if( !( IS_PATH_SEP(pFileName->name[ 0 ]) || IS_PATH_SEP(pFileName->path[ iLen-1 ]) ) ) { - szFileName[ iLen++ ] =PATH_DELIMITER[ 0 ]; + szFileName[ iLen++ ] =OS_PATH_DELIMITER; szFileName[ iLen ] ='\x0'; } } @@ -3365,11 +3366,10 @@ void GenPortObj( char *szFileName, char *szName ) { PFUNCTION pFunc = functions.pFirst; PCOMSYMBOL pSym = symbols.pFirst; - WORD w, wLen, wSym, wVar; + WORD w, wLen, wVar; LONG lPCodePos; LONG lPad; LONG lSymbols; - char chr; FILE * yyc; /* file handle for C output */ szName = szName; @@ -3379,6 +3379,8 @@ void GenPortObj( char *szFileName, char *szName ) return; } + szName = szName; + if( ! _iQuiet ) printf( "\ngenerating portable object file...\n" ); diff --git a/harbour/source/rtl/environ.c b/harbour/source/rtl/environ.c index 6d2250b038..f1cb0f1937 100644 --- a/harbour/source/rtl/environ.c +++ b/harbour/source/rtl/environ.c @@ -14,6 +14,17 @@ #ifdef __WATCOMC__ #include + #if defined(__386__) && !defined(__WINDOWS_386__) + #define INT_86 int386 + #else + #define INT_86 int86 + #endif +#else + #if defined(__EMX__) + #define INT_86 _int86 + #else + #define INT_86 int86 + #endif #endif HARBOUR OS() @@ -101,22 +112,7 @@ HARBOUR OS() /* detect OS/2 */ regs.h.ah = 0x30; -#if defined(__WATCOMC__) && defined(__386__) - - int386(0x21, ®s, ®s); - -#else - -#if defined(__EMX__) - - _int86(0x21, ®s, ®s); - -#else - - int86(0x21, ®s, ®s); - -#endif /* __EMX__ */ -#endif /* WATCOMC */ + INT_86( 0x21, ®s, ®s ); if(regs.h.al >= 10) { @@ -139,28 +135,13 @@ HARBOUR OS() hb_osminor = _osminor; regs.w.ax = 0x160A; -#if defined(__WATCOMC__) && defined(__386__) + INT_86( 0x2F, ®s, ®s ); - int386(0x2F, ®s, ®s); - -#else - -#if defined(__EMX__) - - _int86(0x2F, ®s, ®s); - -#else - - int86(0x2F, ®s, ®s); - -#endif /* EMX */ -#endif /* WATCOMC */ - - if(regs.x.ax == 0) + if( regs.w.ax == 0) { hb_os = "Windows"; - hb_osmajor = regs.x.bx / 256; - hb_osminor = regs.x.bx % 256; + hb_osmajor = regs.w.bx / 256; + hb_osminor = regs.w.bx % 256; hb_osletter = 0; } else diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index c381e65ed8..e0863d4e7d 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -1,6 +1,6 @@ /* $Id$ * - * The Harbour virtual machine + * The Harbour virtual machine */ /* Please note the following comments we may use everywhere @@ -134,7 +134,7 @@ extern ULONG ulMemoryMaxBlocks; /* maximum number of used memory blocks */ extern ULONG ulMemoryConsumed; /* memory size consumed */ extern ULONG ulMemoryMaxConsumed; /* memory max size consumed */ -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION void ProcessObjSymbols ( void ); /* process Harbour generated OBJ symbols */ typedef struct @@ -187,7 +187,7 @@ BYTE bErrorLevel = 0; /* application exit errorlevel */ StackInit(); NewDynSym( &symEval ); /* initialize dynamic symbol for evaluating codeblocks */ InitializeSets(); /* initialize Sets */ -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION ProcessObjSymbols(); /* initialize Harbour generated OBJs symbols */ #endif @@ -196,14 +196,14 @@ BYTE bErrorLevel = 0; /* application exit errorlevel */ DoInitFunctions( argc, argv ); /* process defined INIT functions */ -#ifdef HARBOUR_MAIN +#ifdef HARBOUR_START_PROCEDURE { - PDYNSYM pDynSym =FindDynSym( HARBOUR_MAIN ); + PDYNSYM pDynSym =FindDynSym( HARBOUR_START_PROCEDURE ); if( pDynSym ) pSymStart =pDynSym->pSymbol; else { - printf( "Can\'t locate the starting procedure: \'%s\'", HARBOUR_MAIN ); + printf( "Can\'t locate the starting procedure: \'%s\'", HARBOUR_START_PROCEDURE ); exit(1); } } @@ -1826,7 +1826,7 @@ void ProcessSymbols( PSYMBOL pModuleSymbols, WORD wModuleSymbols ) /* module sym { PSYMBOLS pNewSymbols, pLastSymbols; WORD w; -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION static int iObjChecked = 0; if( ! iObjChecked ) @@ -1862,7 +1862,7 @@ void ProcessSymbols( PSYMBOL pModuleSymbols, WORD wModuleSymbols ) /* module sym } } -#ifdef OBJ_GENERATION +#ifdef HARBOUR_OBJ_GENERATION void ProcessObjSymbols( void ) { POBJSYMBOLS pObjSymbols = ( POBJSYMBOLS ) &HB_FIRSTSYMBOL; diff --git a/harbour/tests/working/keywords.prg b/harbour/tests/working/keywords.prg index d3fa68cf7e..9ea642661f 100644 --- a/harbour/tests/working/keywords.prg +++ b/harbour/tests/working/keywords.prg @@ -4,7 +4,7 @@ //DO NOT RUN THIS PROGRAM - ITS PURPOSE IS THE SYNTAX CHECK ONLY! EXTERNAL __case, __begin -STATIC nExt, bEgin, bReak, cAse, do, wHile, wIth +STATIC nExt, bEgin, bReak, cAse, do, wHile, wIth, eXit Function Main() @@ -39,6 +39,8 @@ Function Main() END_() //END? surprise :) it works in some cases! + EXIT( eXit ) + RETURN nil /*================================================================ @@ -279,16 +281,16 @@ LOCAL with do->do :=do->do +1 ( do )->( do() ) do[ 1 ] :=do - do[ do ] :=do[ do ][ do ] +//////// do[ do ] :=do[ do ][ do ] DO do WITH do DO do WITH do() - DO do + DO do DO while; while while :=while() - ENDDO + ENDDO while while // while++ //incomplete statement or unbalanced delimiter @@ -298,8 +300,8 @@ LOCAL with while->while :=while() +while->while enddo - while[ 1 ] :=while - while[ 2 ] +=2 +// while[ 1 ] :=while +// while[ 2 ] +=2 // while( while ) // while( while[1] ) // while[ while ] :=while[ 1 ] //in Clipper: syntax error ' 1 ' @@ -413,3 +415,44 @@ RETURN end FUNCTION end( end ) RETURN end * end + +/*==================================================================== +* Test for EXIT +*/ +EXIT FUNCTION EXIT( exit ) +//LOCAL exit + + exit++ + ++exit + + exit[ 1 ] :=1 + exit :=exit[ 1 ] + exit->exit :=exit->exit +1 + ( exit )->exit :=exit + DO exit WITH exit + + exit() + exit( exit ) + +// EXIT //EXIT statement with no loop in sight + + FOR exit:=1 TO 10 + exit++ + DO exit + EXIT + NEXT + + WHILE !exit + exit +=1 + EXIT + ENDDO + + DO CASE + CASE exit +// EXIT //EXIT statement with no loop in sight + CASE !exit + exit() + ENDCASE + +RETURN exit +