diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 6fbb8f1ba7..24506b56eb 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,20 @@ +19990803-05:30 GMT+2 Ryszard Glab + + *tests/working/Makefile + + added possibility to build a single file. Usage: + make PM=file + make PM=file.prg + PM can be replaced with pm + + *source/compiler/harbour.y + * DO .. WITH .. statement passes variables by reference now + + *source/vm/hvm.c + * added reporting of line numbers in some internal errors + + *source/compiler/harbour.l + * corrected missed line continuation with BREAK; EXIT; and LOOP; + 19990802-20:00 EDT David G. Holm * config/os2/icc.cf * Added '/NOE' to 'AR_FLAGS' to get rid of linker errors for diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index f9da7bb5c8..130822440f 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -226,7 +226,7 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "break" BEGIN BREAK_; -{Separator}*\n { /* at the end of line */ +{Separator}*[\n;] { /* at the end of line */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); if( _iState == LOOKUP ) @@ -444,7 +444,7 @@ Separator {SpaceTab} %} "exit" { BEGIN EXIT_; } -{Separator}*[\n] { /* EXIT last item in the line */ +{Separator}*[\n;] { /* EXIT last item in the line */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( _iState == LOOKUP ) @@ -740,7 +740,7 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "loop" BEGIN LOOP_; -{Separator}*\n { /* at the end of the line */ +{Separator}*[\n;] { /* at the end of the line */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; if( _iState == LOOKUP ) diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index c1367666b9..e84d9934b4 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -501,7 +501,7 @@ extern int _iState; /* current parser state (defined in harbour.l */ %type DOUBLE %type ArgList ElemList ExpList FunCall FunScope IncDec Logical Params ParamList %type INTEGER BlockExpList Argument IfBegin VarId VarList MethParams ObjFunCall -%type MethCall BlockList FieldList DoArgList +%type MethCall BlockList FieldList DoArgList VarAt %type INTLONG WhileBegin BlockBegin %type IfElseIf Cases @@ -581,7 +581,7 @@ Statement : ExecFlow Crlf {} | IDENTIFIER '=' Expression Crlf { PopId( $1 ); } | AliasVar '=' Expression Crlf { /* TODO */ GenPCode1( HB_P_POP ); } | AliasFunc '=' Expression Crlf { --iLine; GenError( _szCErrors, 'E', ERR_INVALID_LVALUE, NULL, NULL ); } - | VarId ArrayIndex '=' Expression Crlf { GenPCode1( HB_P_ARRAYPUT ); GenPCode1( HB_P_POP ); } + | VarAt '=' Expression Crlf { GenPCode1( HB_P_ARRAYPUT ); GenPCode1( HB_P_POP ); } | FunArrayCall '=' Expression Crlf { GenPCode1( HB_P_ARRAYPUT ); GenPCode1( HB_P_POP ); } | ObjectData '=' { MessageFix( SetData( $1 ) ); } Expression Crlf { Function( 1 ); GenPCode1( HB_P_POP ); } | ObjectData ArrayIndex '=' Expression Crlf { GenPCode1( HB_P_ARRAYPUT ); GenPCode1( HB_P_POP ); } @@ -635,7 +635,7 @@ MethParams : /* empty */ { $$ = 0; } ; ObjectData : IdSend IDENTIFIER { $$ = $2; _lMessageFix = functions.pLast->lPCodePos; Message( $2 ); Function( 0 ); } - | VarId ArrayIndex ':' IDENTIFIER { GenPCode1( HB_P_ARRAYAT ); $$ = $4; _lMessageFix = functions.pLast->lPCodePos; Message( $4 ); Function( 0 ); } + | VarAt ':' IDENTIFIER { GenPCode1( HB_P_ARRAYAT ); $$ = $3; _lMessageFix = functions.pLast->lPCodePos; Message( $3 ); Function( 0 ); } | ObjFunCall IDENTIFIER { $$ = $2; _lMessageFix = functions.pLast->lPCodePos; Message( $2 ); Function( 0 ); } | ObjFunArray ':' IDENTIFIER { $$ = $3; _lMessageFix = functions.pLast->lPCodePos; Message( $3 ); Function( 0 ); } | ObjectMethod ':' IDENTIFIER { $$ = $3; _lMessageFix = functions.pLast->lPCodePos; Message( $3 ); Function( 0 ); } @@ -644,7 +644,7 @@ ObjectData : IdSend IDENTIFIER { $$ = $2; _lMessageFix = fun ; ObjectMethod : IdSend IDENTIFIER { Message( $2 ); } '(' MethParams ')' { Function( $5 ); } - | VarId ArrayIndex ':' MethCall { Function( $4 ); GenPCode1( HB_P_ARRAYAT ); } + | VarAt ':' MethCall { Function( $3 ); GenPCode1( HB_P_ARRAYAT ); } | ObjFunCall MethCall { Function( $2 ); } | ObjFunArray ':' MethCall { Function( $3 ); } | ObjectData ':' MethCall { Function( $3 ); } @@ -749,8 +749,8 @@ AliasFunc : IDENTIFIER ALIAS '(' ExpList ')' {} VarUnary : IDENTIFIER IncDec %prec POST { PushId( $1 ); Duplicate(); $2 ? Inc(): Dec(); PopId( $1 ); } | IncDec IDENTIFIER %prec PRE { PushId( $2 ); $1 ? Inc(): Dec(); Duplicate(); PopId( $2 ); } - | VarId ArrayIndex IncDec %prec POST { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); $3 ? Inc(): Dec(); GenPCode1( HB_P_ARRAYPUT ); $3 ? Dec(): Inc(); } - | IncDec VarId ArrayIndex %prec PRE { DupPCode( $2 ); GenPCode1( HB_P_ARRAYAT ); $1 ? Inc(): Dec(); GenPCode1( HB_P_ARRAYPUT ); } + | VarAt IncDec %prec POST { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); $2 ? Inc(): Dec(); GenPCode1( HB_P_ARRAYPUT ); $2 ? Dec(): Inc(); } + | IncDec VarAt %prec PRE { DupPCode( $2 ); GenPCode1( HB_P_ARRAYAT ); $1 ? Inc(): Dec(); GenPCode1( HB_P_ARRAYPUT ); } | FunArrayCall IncDec %prec POST { GenPCode1( HB_P_DUPLTWO ); GenPCode1( HB_P_ARRAYAT ); $2 ? Inc(): Dec(); GenPCode1( HB_P_ARRAYPUT ); $2 ? Dec(): Inc(); } | IncDec FunArrayCall %prec PRE { GenPCode1( HB_P_DUPLTWO ); GenPCode1( HB_P_ARRAYAT ); $1 ? Inc(): Dec(); GenPCode1( HB_P_ARRAYPUT ); } | ObjectData IncDec %prec POST { MessageDupl( SetData( $1 ) ); Function( 0 ); $2 ? Inc(): Dec(); Function( 1 ); $2 ? Dec(): Inc(); } @@ -766,14 +766,25 @@ IncDec : INC { $$ = 1; } ; Variable : VarId {} - | VarId ArrayIndex { GenPCode1( HB_P_ARRAYAT ); } + | VarAt { GenPCode1( HB_P_ARRAYAT ); } | FunArrayCall { GenPCode1( HB_P_ARRAYAT ); } | ObjectData {} | ObjectData ArrayIndex { GenPCode1( HB_P_ARRAYAT ); } | ObjectMethod ArrayIndex { GenPCode1( HB_P_ARRAYAT ); } ; -VarId : IDENTIFIER { $$ = functions.pLast->lPCodePos; PushId( $1 ); } +VarId : IDENTIFIER { $$ = functions.pLast->lPCodePos; + if( _bForceByRefer && functions.pLast->szName ) + /* DO .. WITH uses reference to a variable + * if not inside a codeblock + */ + PushIdByRef( $1 ); + else + PushId( $1 ); + } + ; + +VarAt : IDENTIFIER { $$ = functions.pLast->lPCodePos; PushId( $1 ); } ArrayIndex { $$ =$2; } ; ArrayIndex : '[' IndexList ']' @@ -791,13 +802,13 @@ VarAssign : IDENTIFIER INASSIGN Expression { PopId( $1 ); PushId( $1 ); } | IDENTIFIER DIVEQ { PushId( $1 ); } Expression { GenPCode1( HB_P_DIVIDE ); PopId( $1 ); PushId( $1 ); } | IDENTIFIER EXPEQ { PushId( $1 ); } Expression { GenPCode1( HB_P_POWER ); PopId( $1 ); PushId( $1 ); } | IDENTIFIER MODEQ { PushId( $1 ); } Expression { GenPCode1( HB_P_MODULUS ); PopId( $1 ); PushId( $1 ); } - | VarId ArrayIndex INASSIGN Expression { GenPCode1( HB_P_ARRAYPUT ); } - | VarId ArrayIndex PLUSEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_PLUS ); GenPCode1( HB_P_ARRAYPUT ); } - | VarId ArrayIndex MINUSEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_MINUS ); GenPCode1( HB_P_ARRAYPUT ); } - | VarId ArrayIndex MULTEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_MULT ); GenPCode1( HB_P_ARRAYPUT ); } - | VarId ArrayIndex DIVEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_DIVIDE ); GenPCode1( HB_P_ARRAYPUT ); } - | VarId ArrayIndex EXPEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_POWER ); GenPCode1( HB_P_ARRAYPUT ); } - | VarId ArrayIndex MODEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_MODULUS ); GenPCode1( HB_P_ARRAYPUT ); } + | VarAt INASSIGN Expression { GenPCode1( HB_P_ARRAYPUT ); } + | VarAt PLUSEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_PLUS ); GenPCode1( HB_P_ARRAYPUT ); } + | VarAt MINUSEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_MINUS ); GenPCode1( HB_P_ARRAYPUT ); } + | VarAt MULTEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_MULT ); GenPCode1( HB_P_ARRAYPUT ); } + | VarAt DIVEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_DIVIDE ); GenPCode1( HB_P_ARRAYPUT ); } + | VarAt EXPEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_POWER ); GenPCode1( HB_P_ARRAYPUT ); } + | VarAt MODEQ { DupPCode( $1 ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_MODULUS ); GenPCode1( HB_P_ARRAYPUT ); } | FunArrayCall INASSIGN Expression { GenPCode1( HB_P_ARRAYPUT ); } | FunArrayCall PLUSEQ { GenPCode1( HB_P_DUPLTWO ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_PLUS ); GenPCode1( HB_P_ARRAYPUT ); } | FunArrayCall MINUSEQ { GenPCode1( HB_P_DUPLTWO ); GenPCode1( HB_P_ARRAYAT ); } Expression { GenPCode1( HB_P_MINUS ); GenPCode1( HB_P_ARRAYPUT ); } @@ -1109,6 +1120,12 @@ RecoverEmpty : RECOVER RecoverUsing : RECOVER USING IDENTIFIER ; +/* NOTE: In Clipper all variables used in DO .. WITH are passed by reference + * however if they are part of an expression then they are passed by value + * for example: + * DO .. WITH ++variable + * will pass the value of variable not a reference + */ DoProc : DO IDENTIFIER { PushSymbol( $2, 1 ); PushNil(); Do( 0 ); } | DO IDENTIFIER { PushSymbol( $2, 1 ); PushNil(); _bForceByRefer=TRUE; } WITH DoArgList { Do( $5 ); _bForceByRefer=FALSE; } | WHILE { PushSymbol( yy_strdup("WHILE"), 1 ); PushNil(); _bForceByRefer=TRUE; } WITH DoArgList { Do( $4 ); _bForceByRefer=FALSE; } diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 5d256455f2..4d58dbc841 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -725,7 +725,7 @@ void Do( WORD wParams ) if( ! IS_SYMBOL( pItem ) ) { StackShow(); - printf( "symbol item expected as a base from Do()\n" ); + printf( "symbol item expected as a base from Do() in line %i\n", stack.pBase->item.asSymbol.lineno ); exit( 1 ); } @@ -763,7 +763,7 @@ void Do( WORD wParams ) pFunc = pSym->pFunPtr; if( ! pFunc ) { - printf( "error: invalid function pointer (%s) from Do()\n", pSym->szName ); + printf( "error: invalid function pointer (%s) from Do() in line %i\n", pSym->szName, stack.pBase->item.asSymbol.lineno ); exit( 1 ); } pFunc(); @@ -784,7 +784,7 @@ HARBOUR DoBlock( void ) if( ! IS_BLOCK( pBlock ) ) { - printf( "error: codeblock expected from DoBlock()\n" ); + printf( "error: codeblock expected from DoBlock() in line %i\n", stack.pBase->item.asSymbol.lineno ); exit( 1 ); } @@ -839,7 +839,7 @@ HARBOUR HB_EVAL( void ) } else { - printf( "Not a valid codeblock on eval\n" ); + printf( "Not a valid codeblock on eval in line %i\n", stack.pBase->item.asSymbol.lineno ); exit( 1 ); } } @@ -1459,7 +1459,7 @@ long PopDate( void ) } else { - printf( "incorrect item value trying to Pop a date value\n" ); + printf( "incorrect item value trying to Pop a date value in line %i\n", stack.pBase->item.asSymbol.lineno ); exit( 1 ); return 0; } @@ -1489,7 +1489,7 @@ double PopDouble( WORD *pwDec ) break; default: - printf( "Incorrect item type trying to Pop a double\n" ); + printf( "Incorrect item type trying to Pop a double in line %i\n", stack.pBase->item.asSymbol.lineno ); exit( 1 ); d = 0; } @@ -1569,7 +1569,8 @@ double PopNumber( void ) break; default: - printf( "Incorrect item on the stack trying to pop a number\n" ); + printf( "Incorrect item on the stack trying to pop a number in line %i\n", stack.pBase->item.asSymbol.lineno ); + StackShow(); exit( 1 ); break; } diff --git a/harbour/tests/working/Makefile b/harbour/tests/working/Makefile index aa30d6dcdf..a67516b08b 100644 --- a/harbour/tests/working/Makefile +++ b/harbour/tests/working/Makefile @@ -4,6 +4,17 @@ ROOT = ../../ +LIBS=\ + tools \ + vm \ + rtl \ + rdd \ + hbpp \ + +ifeq ($(PM),) + PM := $(pm) +endif +ifeq ($(PM),) # PM not defined = build all files PRG_SOURCES=\ ainstest.prg \ and_or.prg \ @@ -147,11 +158,19 @@ C_HEADERS=\ BAD_C_SOURCES=\ extend2.c \ -LIBS=\ - tools \ - vm \ - rtl \ - rdd \ - hbpp \ - include $(TOP)$(ROOT)config/test.cf + +else #PM defined = build specified file + +ifneq ($(findstring .prg,$(PM)),) + PRG_MAIN :=$(PM) +else + ifneq ($(findstring .PRG,$(PM)),) + PRG_MAIN := $(PM) + else + PRG_MAIN := $(PM).prg + endif +endif +include $(TOP)$(ROOT)config/bin.cf + +endif