From b1bb363c6b0152b4b7919409715d98fdd265286f Mon Sep 17 00:00:00 2001 From: Ryszard Glab Date: Sat, 8 May 1999 02:01:38 +0000 Subject: [PATCH] see ChangeLog 1999.05.08-03:02 --- harbour/ChangeLog | 34 ++++++++- harbour/include/extend.h | 2 +- harbour/source/compiler/harbour.l | 73 +++++++++++++++---- harbour/source/compiler/harbour.y | 65 ++++++++++++++--- harbour/source/rtl/codebloc.c | 39 +++++++---- harbour/source/rtl/extend.c | 6 +- harbour/source/vm/hvm.c | 11 +-- harbour/tests/working/keywords.prg | 109 +++++++++++++++++++++++++---- harbour/tests/working/statics.prg | 29 ++++++-- 9 files changed, 300 insertions(+), 68 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 3d91de61c3..726a14f24f 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,30 @@ +Sat May 8 03:02:04 1999 Ryszard Glab + + * source/compiler/harbour.y, source/compiler/harbour.l + -static variables can be accessed in a codeblock even if this + codeblock is a return value (detached static variables) + -Harbour finds now illegal initializations of static variables + (static variables can be initialized using literals only) + -there is no 'redefinition of predefined function' error when the name + of compiled source code is the same as reserved function + -corrected support for /*******/ comments + -Harbour distinguish now 'CASE' variable, 'CASE()' function and + CASE statement (see tests/working/keywords.prg) + + * tests/working/keywords.prg + -added many more wild statements to test Harbour compiler + + * test/working/statics.prg + -added code to test access of static variables from a codeblock + + * source/rtl/extend.c + -added brackets to avoid ambiguous if/else + + * source/include/extend.h + * source/rtl/codebloc.c + - added support for static variables in a codeblock + + 19990507-20:15 EDT David G. Holm * source/compiler/harbour.l * source/compiler/harbour.y @@ -37,9 +64,10 @@ Thu May 07 17:00:00 1999 Victor Szel 19990507-07:25 Ryszard Glab * source/compiler/harbour.y, source/compiler/harbour.l - -improoved support for BEGIN SEGEUENCE - -added distinction between BEGIN comannd and begin variable - -added distinction between BREAK command and break variable + -improoved support for BEGIN SEGEUENCE + -added distinction between BEGIN command and begin variable + -added distinction between BREAK command and break variable + * tests/working/keywords.prg -new file to test if we are 100% compatible with Clipper diff --git a/harbour/include/extend.h b/harbour/include/extend.h index d1c4c601db..e9e2b60591 100644 --- a/harbour/include/extend.h +++ b/harbour/include/extend.h @@ -64,7 +64,6 @@ typedef struct /* items hold at the virtual machine stack */ void * pBaseArray; /* array base */ } value; WORD wBase; /* stack frame number of items position for a function call */ - PSYMBOL pSymbols; /* codeblocks symbols */ WORD wLine; /* currently processed PRG line number */ WORD wParams; /* number of received parameters for a function call */ } ITEM, * PITEM; @@ -106,6 +105,7 @@ typedef struct WORD wDetached; /* holds if pItems table variables values */ PSYMBOL pSymbols; /* codeblocks symbols */ WORD wRefBase; /* stack frame position for referenced local variables */ + int iStatBase; /* static base for function where CB was created */ long lCounter; /* numer of references to this codeblock */ } CODEBLOCK, * PCODEBLOCK; diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index d36fcabc88..3f627500f3 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -55,7 +55,15 @@ long lNumber = 0; #define LOOKUP 0 int _iState = LOOKUP; -//Comment1 "/*"((.*)|(\n))"*/" +void yy_lex_count_lf( void ) +{ + char * pTmp = yytext; + while( (pTmp = strchr(pTmp, '\n')) ) + { + ++iLine; + ++pTmp; + } +} %} @@ -67,7 +75,7 @@ Identifier (([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+)) String (\"(([^\"]*)|([\!]*))\")|(\'(([^\']*)|([\!]*))\') PseudoFunc {Identifier}"("+.*")"+ -Comment1 "/*"([^\*]|("*"[^\/]))*"*/" +Comment1 "/*"(.*|[\n])"*/" Comment2 [\/][\/].* Comment ({Comment1}|{Comment2}) LineCont (;.*\n) @@ -75,7 +83,7 @@ Separator {SpaceTab}|{Comment}|{LineCont} %x COMMENT3 DEFINE DEFINE_PARAMS DEFINE_EXPR %x IFDEF IFNDEF STRING1 STRING2 -%x NEXT_ BREAK_ +%x NEXT_ BREAK_ CASE_ %% @@ -96,8 +104,9 @@ Separator {SpaceTab}|{Comment}|{LineCont} yylval.string[ yyleng - 2 ] = 0; return LITERAL; } "/*" BEGIN COMMENT3; -"*/" BEGIN 0; +"*"["*"]*"/" BEGIN 0; [^"*/"\n]* ; +"*" ; [\/\"]+ ; \n ++iLine; if( ! _iQuiet ) printf( "\rline: %i", iLine ); @@ -154,28 +163,64 @@ Separator {SpaceTab}|{Comment}|{LineCont} } else { /* there is another item in line already */ - yylval.string = "BrEaK"; + yylval.string = strdup("BrEaK"); return IDENTIFIER; } } {Separator}*[^_a-zA-Z] { /* there is no identifier after "break" */ + yy_lex_count_lf(); BEGIN 0; - yylval.string = ((yytext[ yyleng-1 ] =='(')?"BREAK":"BrEaK"); + yylval.string = strdup( ((yytext[ yyleng-1 ] =='(')?"BREAK":"BrEaK") ); _iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } {Separator}*. { /* an identifier follows BREAK statement */ + yy_lex_count_lf(); BEGIN 0; unput( yytext[ yyleng-1 ] ); _iState =BREAK; return BREAK; } . { BEGIN 0; unput( yytext[ yyleng-1 ] ); } -"case" return CASE; +"case" { BEGIN CASE_; } +{Separator}*[\:\=\|\$\%\*\,\/\[\]\)\}] { /* there is an operator after "case" */ + yy_lex_count_lf(); + BEGIN 0; + yylval.string = strdup( "CASE" ); + _iState =IDENTIFIER; + unput( yytext[ yyleng-1 ] ); + return IDENTIFIER; + } +{Separator}*("+="|"-=") { /* operators */ + yy_lex_count_lf(); + BEGIN 0; + yylval.string = strdup( "CASE" ); + _iState =IDENTIFIER; + unput( yytext[ yyleng-2 ] ); + unput( yytext[ yyleng-1 ] ); + return IDENTIFIER; + } +{Separator}*(\n|.) { /* not operator */ + yy_lex_count_lf(); + BEGIN 0; + if( yytext[ yyleng-1 ] == '\n' ) + --iLine; + unput( yytext[ yyleng-1 ] ); + if( _iState == LOOKUP ) + { /* it is first item in the line */ + _iState =CASE; + return CASE; + } + else + { /* there is another item in line already */ + yylval.string = strdup( "CASE" ); + return IDENTIFIER; + } + } "do" return DO; -"do"{SpaceTab}+"case" return DOCASE; -("do"{SpaceTab}+"while")|"while" return WHILE; +"do"{Separator}+"case" { _iState =DOCASE; return DOCASE; } +("do"{SpaceTab}+"while")|"while" { _iState =WHILE; return WHILE; } "else" return ELSE; "elseif" _iState =ELSEIF; return ELSEIF; "end"/[^(] return END; @@ -208,18 +253,20 @@ Separator {SpaceTab}|{Comment}|{LineCont} else { /* there is another item in line already */ unput( yytext[ yyleng-1 ] ); - yylval.string = "nExT"; + yylval.string = strdup( "nExT" ); return IDENTIFIER; } } -{Separator}*[^_a-zA-Z\n\;] { /* there is no identifier after "next" */ +{Separator}*[^_a-zA-Z] { /* there is no identifier after "next" */ + yy_lex_count_lf(); BEGIN 0; - yylval.string = ((yytext[ yyleng-1 ] =='(')?"NEXT":"nExT"); + yylval.string = strdup( ((yytext[ yyleng-1 ] =='(')?"NEXT":"nExT") ); unput( yytext[ yyleng-1 ] ); _iState =IDENTIFIER; return IDENTIFIER; } {Separator}*. { /* an identifier follows NEXT statement */ + yy_lex_count_lf(); BEGIN 0; unput( yytext[ yyleng-1 ] ); _iState =NEXT; @@ -311,7 +358,7 @@ Separator {SpaceTab}|{Comment}|{LineCont} {String} yylval.string = strdup( yytext + 1 ); yylval.string[ yyleng - 2 ] = 0; return LITERAL; -{LineCont} { ++iLine; } +{LineCont} ++iLine; {Identifier} { PDEFINE pDef = FindDef( yytext ); diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 27af0ca371..272401a7a2 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -80,6 +80,8 @@ typedef struct __FUNC /* functions definition support */ */ #define FUN_STATEMENTS 1 /* Function have at least one executable statement */ #define FUN_USES_STATICS 2 /* Function uses static variables */ +#define FUN_PROCEDURE 4 /* This is a procedure that shouldn't return value */ +#define FUN_ILLEGAL_INIT 8 /* Attempt to initialize static variable with a function call */ typedef struct { @@ -172,7 +174,7 @@ void FixElseIfs( void * pIfElseIfs ); /* implements the ElseIfs pcode fixups */ void FixReturns( void ); /* fixes all last defined function returns jumps offsets */ void Function( BYTE bParams ); /* generates the pcode to execute a Clipper function pushing its result */ PFUNCTION FunctionNew( char *, char ); /* creates and initialises the _FUNC structure */ -void FunDef( char * szFunName, char cScope ); /* starts a new Clipper language function definition */ +void FunDef( char * szFunName, char cScope, int iType ); /* starts a new Clipper language function definition */ void GenArray( WORD wElements ); /* instructs the virtual machine to build an array and load elemnst from the stack */ void * GenElseIf( void * pFirstElseIf, WORD wOffset ); /* generates a support structure for elseifs pcode fixups */ void GenError( int, char*, char * ); /* generic parsing error management function */ @@ -222,6 +224,7 @@ void CodeBlockEnd( void ); /* end of codeblock creation */ /* Static variables */ void StaticDefStart( void ); void StaticDefEnd( WORD ); +void StaticAssign( void ); /* checks if static variable is initialized with function call */ void * OurMalloc( LONG lSize ); /* our malloc with error control */ void * OurRealloc( void * p, LONG lSize ); /* our malloc with error control */ @@ -262,6 +265,7 @@ int iVarScope = 0; /* holds the scope for next variables to be defined #define ERR_NUMERIC_FORMAT 6 #define ERR_STRING_TERMINATOR 7 #define ERR_FUNC_RESERVED 8 +#define ERR_ILLEGAL_INIT 9 /* Table with parse errors */ char * _szErrors[] = { "Statement not allowed outside of procedure or function", @@ -271,7 +275,8 @@ char * _szErrors[] = { "Statement not allowed outside of procedure or function", "Outer codeblock variable is out of reach: \'%s\'", "Invalid numeric format '.'", "Unterminated string: \'%s\'", - "Redefinition of predefined function %s: \'%s\'" + "Redefinition of predefined function %s: \'%s\'", + "Illegal initializer: \'%s\'" }; /* Table with reserved functions names @@ -468,8 +473,8 @@ ExtList : IDENTIFIER { AddExtern( $1 ); } | ExtList ',' IDENTIFIER { AddExtern( $3 ); } ; -Function : FunScope FUNCTION IDENTIFIER { FunDef( $3, $1 ); } Params Crlf { SetFrame(); } - | FunScope PROCEDURE IDENTIFIER { FunDef( $3, $1 ); } Params Crlf { SetFrame(); } +Function : FunScope FUNCTION IDENTIFIER { FunDef( $3, $1, 0 ); } Params Crlf { SetFrame(); } + | FunScope PROCEDURE IDENTIFIER { FunDef( $3, $1, FUN_PROCEDURE ); } Params Crlf { SetFrame(); } ; FunScope : { $$ = FS_PUBLIC; } @@ -523,14 +528,14 @@ FunCall : FunStart ')' { $$ = 0; } | FunStart ArgList ')' { $$ = $2; } ; -FunStart : IDENTIFIER '(' { PushSymbol( $1, 1 ); PushNil(); $$ = $1; } +FunStart : IDENTIFIER '(' { StaticAssign(); PushSymbol( $1, 1 ); PushNil(); $$ = $1; } ; MethCall : MethStart ')' { $$ = 0; } | MethStart ArgList ')' { $$ = $2; } ; -MethStart : IDENTIFIER '(' { Message( $1 ); $$ = $1; } +MethStart : IDENTIFIER '(' { StaticAssign(); Message( $1 ); $$ = $1; } ; ArgList : ',' { PushNil(); PushNil(); $$ = 2; } @@ -1127,7 +1132,7 @@ int harbour_main( int argc, char * argv[] ) if( Include( szFileName ) ) { - FunDef( strupr( strdup( pFileName->name ) ), FS_PUBLIC ); + FunDef( strupr( strdup( pFileName->name ) ), FS_PUBLIC, FUN_PROCEDURE ); yyparse(); FixReturns(); /* fix all previous function returns offsets */ fclose( yyin ); @@ -1397,7 +1402,14 @@ void AddVar( char * szVarName ) * defined is stored in pOwner member. */ if( iVarScope == VS_STATIC ) + { pFunc =pFunc->pOwner; + /* Check if an illegal action was invoked during a static variable + * value initialization + */ + if( _pInitFunc->bFlags & FUN_ILLEGAL_INIT ) + GenError( ERR_ILLEGAL_INIT, szVarName, pFunc->szName ); + } /* Check if a declaration of duplicated variable name is requested */ if( pFunc->szName ) @@ -1583,7 +1595,13 @@ PFUNCTION FunctionNew( char *szName, char cScope ) return pFunc; } -void FunDef( char * szFunName, char cScope ) /* stores a Clipper defined function */ +/* + * Stores a Clipper defined function/procedure + * szFunName - name of a function + * cScope - scope of a function + * iType - FUN_PROCEDURE if a procedure or 0 + */ +void FunDef( char * szFunName, char cScope, int iType ) { PCOMSYMBOL pSym; PFUNCTION pFunc; @@ -1620,6 +1638,7 @@ void FunDef( char * szFunName, char cScope ) /* stores a Clipper defined functi pSym->cScope |= cScope; /* we may have a non public function and a object message */ pFunc =FunctionNew( szFunName, cScope ); + pFunc->bFlags |= iType; if( functions.iCount == 0 ) { @@ -2677,6 +2696,14 @@ void PushId( char * szVarName ) /* generates the pcode to push a variable value { WORD wVar; + if( iVarScope == VS_STATIC ) + { + /* Reffering to any variable is not allowed during initialization + * of static variable + */ + _pInitFunc->bFlags |= FUN_ILLEGAL_INIT; + } + if( ( wVar = GetLocalVarPos( szVarName ) ) ) GenPCode3( _PUSHLOCAL, LOBYTE( wVar ), HIBYTE( wVar ) ); @@ -2698,6 +2725,14 @@ void PushIdByRef( char * szVarName ) /* generates the pcode to push a variable b { WORD wVar; + if( iVarScope == VS_STATIC ) + { + /* Reffering to any variable is not allowed during initialization + * of static variable + */ + _pInitFunc->bFlags |= FUN_ILLEGAL_INIT; + } + if( ( wVar = GetLocalVarPos( szVarName ) ) ) GenPCode3( _PUSHLOCALREF, LOBYTE( wVar ), HIBYTE( wVar ) ); @@ -3110,7 +3145,7 @@ void StaticDefStart( void ) { _pInitFunc =FunctionNew( "_INITSTATICS", FS_INIT ); _pInitFunc->pOwner =functions.pLast; - _pInitFunc->bFlags =FUN_USES_STATICS; + _pInitFunc->bFlags =FUN_USES_STATICS | FUN_PROCEDURE; functions.pLast =_pInitFunc; PushInteger( 1 ); /* the number of static variables is unknown now */ GenPCode3( _STATICS, 0, 0 ); @@ -3133,6 +3168,18 @@ void StaticDefEnd( WORD wCount ) functions.pLast =_pInitFunc->pOwner; _pInitFunc->pOwner =NULL; _wStatics += wCount; + iVarScope =0; +} + +/* + * This function checks if we are initializing a static variable. + * It should be called only in case when the parser have recognized any + * function or method invocation. + */ +void StaticAssign( void ) +{ + if( iVarScope == VS_STATIC ) + _pInitFunc->bFlags |= FUN_ILLEGAL_INIT; } void * OurMalloc( LONG lSize ) diff --git a/harbour/source/rtl/codebloc.c b/harbour/source/rtl/codebloc.c index 979500ee3c..6da7272467 100644 --- a/harbour/source/rtl/codebloc.c +++ b/harbour/source/rtl/codebloc.c @@ -23,7 +23,8 @@ extern STACK stack; * +2 bytes -> table of referenced local variables * +2 + 2 *(number of referenced variables) -> codeblock pcode */ -PCODEBLOCK CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols ) +PCODEBLOCK CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols, + int iStaticsBase, WORD wStackBase ) { PCODEBLOCK pCBlock; WORD wVars; @@ -61,18 +62,26 @@ PCODEBLOCK CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols ) /* the codeblock initally contains references to local variables */ pCBlock->wDetached =FALSE; - /* since the only allowed operation on a codeblock is evaluating it then - * there is no need to duplicate its pcode -just store the poiter to it + /* + * pcode is stored in static segment now. + * The only allowed operation on a codeblock is evaluating it then + * there is no need to duplicate its pcode -just store the pointer to it */ - pCBlock->pCode = (BYTE *) _xgrab( wSize ); - memcpy( pCBlock->pCode, pBuffer, wSize ); + pCBlock->pCode = pBuffer; pCBlock->pSymbols =pSymbols; pCBlock->wDetached =FALSE; pCBlock->lCounter =1; + pCBlock->iStatBase =iStaticsBase; + /* + * wStackBase is stack base of function where the codeblock was defined + * We need it because stack.pBase points to a stack base of EVAL function + * at the time of codeblock evaluation. + */ + pCBlock->wRefBase =wStackBase; #ifdef CODEBLOCKDEBUG - printf( "codeblock created (%li)\n", pCBlock->lCounter ); + printf( "codeblock created (%li) %lx\n", pCBlock->lCounter, pCBlock ); #endif return pCBlock; } @@ -82,7 +91,7 @@ PCODEBLOCK CodeblockNew( BYTE * pBuffer, WORD wSize, PSYMBOL pSymbols ) void CodeblockDelete( PCODEBLOCK pCBlock ) { #ifdef CODEBLOCKDEBUG - printf( "delete a codeblock (%li)\n", pCBlock->lCounter ); + printf( "delete a codeblock (%li) %lx\n", pCBlock->lCounter, pCBlock ); #endif if( --pCBlock->lCounter == 0 ) { @@ -92,14 +101,11 @@ void CodeblockDelete( PCODEBLOCK pCBlock ) */ while( w < pCBlock->wLocals ) ItemRelease( &pCBlock->pItems[ w++ ] ); - /* free space allocated for a codeblock pcodes - */ - _xfree( pCBlock->pCode ); /* free space allocated for a CODEBLOCK structure */ _xfree( pCBlock ); #ifdef CODEBLOCKDEBUG - printf( "codeblock deleted (%li)\n", pCBlock->lCounter ); + printf( "codeblock deleted (%li) %lx\n", pCBlock->lCounter, pCBlock ); #endif } } @@ -132,7 +138,7 @@ void CodeblockDetach( PCODEBLOCK pCBlock ) pCBlock->wDetached =TRUE; } #ifdef CODEBLOCKDEBUG - printf( "codeblock detached(%li)\n", pCBlock->lCounter ); + printf( "codeblock detached(%li) %lx\n", pCBlock->lCounter, pCBlock ); #endif } @@ -140,10 +146,13 @@ void CodeblockDetach( PCODEBLOCK pCBlock ) * wStackBase is stack base of function where the codeblock was defined * We need it because stack.pBase points to a stack base of EVAL function */ -void CodeblockEvaluate( PCODEBLOCK pCBlock, WORD wStackBase ) +void CodeblockEvaluate( PCODEBLOCK pCBlock ) { - pCBlock->wRefBase =wStackBase; + int iStatics = stack.iStatics; + + stack.iStatics = pCBlock->iStatBase; VirtualMachine( pCBlock->pCode, pCBlock->pSymbols ); + stack.iStatics = iStatics; } /* Get local variable referenced in a codeblock @@ -175,6 +184,6 @@ void CodeblockCopy( PITEM pDest, PITEM pSource ) pDest->value.pCodeblock =pSource->value.pCodeblock; ((PCODEBLOCK) pDest->value.pCodeblock)->lCounter++; #ifdef CODEBLOCKDEBUG - printf( "copy a codeblock (%li)\n", ((PCODEBLOCK) pDest->value.pCodeblock)->lCounter); + printf( "copy a codeblock (%li) %lx\n", ((PCODEBLOCK) pDest->value.pCodeblock)->lCounter, pDest->value.pCodeblock); #endif } diff --git a/harbour/source/rtl/extend.c b/harbour/source/rtl/extend.c index 18db454f31..6eb9d8a080 100644 --- a/harbour/source/rtl/extend.c +++ b/harbour/source/rtl/extend.c @@ -44,11 +44,12 @@ char * _parc( WORD wParam, ... ) pItem = stack.pBase + 1 + wParam; if( IS_ARRAY( pItem ) ) + { if( wArrayIndex ) return ArrayGetString( pItem, wArrayIndex ); else return ""; - + } else if( IS_STRING( pItem ) ) return pItem->value.szText; @@ -73,11 +74,12 @@ ULONG _parclen( WORD wParam, ... ) pItem = stack.pBase + 1 + wParam; if( IS_ARRAY( pItem ) ) + { if( wArrayIndex ) return ArrayGetStringLen( pItem, wArrayIndex ); else return 0; - + } else if( IS_STRING( pItem ) ) return pItem->wLength; diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 06f2d2d937..479ac6249b 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -112,10 +112,10 @@ void StackPush( void ); /* pushes an item on to the stack */ void StackInit( void ); /* initializes the stack */ void StackShow( void ); /* show the types of the items on the stack for HBDEBUGging purposes */ -PCODEBLOCK CodeblockNew( BYTE *, WORD, PSYMBOL ); +PCODEBLOCK CodeblockNew( BYTE *, WORD, PSYMBOL, int, WORD ); void CodeblockDelete( PCODEBLOCK ); PITEM CodeblockGetVar( PITEM, SHORT ); -void CodeblockEvaluate( PCODEBLOCK, WORD ); +void CodeblockEvaluate( PCODEBLOCK ); void CodeblockCopy( PITEM, PITEM ); void CodeblockDetach( PCODEBLOCK ); @@ -608,7 +608,7 @@ void Do( WORD wParams ) WORD wItemIndex = pItem - stack.pItems; PITEM pSelf = stack.pPos - wParams - 1; HARBOURFUNC pFunc; - WORD iStatics = stack.iStatics; /* Return iStatics position */ + int iStatics = stack.iStatics; /* Return iStatics position */ if( ! IS_SYMBOL( pItem ) ) { @@ -683,7 +683,7 @@ HARBOUR DoBlock( void ) */ stack.pBase->wLine =pBlock->wLine; - CodeblockEvaluate( (PCODEBLOCK)pBlock->value.pCodeblock, pBlock->wBase ); + CodeblockEvaluate( (PCODEBLOCK)pBlock->value.pCodeblock ); /* restore stack pointers */ stack.pBase = stack.pItems + wStackBase; @@ -1526,7 +1526,8 @@ 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 = (BYTE *)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; /* store the number of expected parameters */ diff --git a/harbour/tests/working/keywords.prg b/harbour/tests/working/keywords.prg index dd819a4155..a70be3315a 100644 --- a/harbour/tests/working/keywords.prg +++ b/harbour/tests/working/keywords.prg @@ -1,19 +1,29 @@ +/* + * $Id$ +*/ //DO NOT RUN THIS PROGRAM - ITS PURPOSE IS THE SYNTAX CHECK ONLY! -STATIC nExt, bEgin, bReak +STATIC nExt, bEgin, bReak, cAse Function Main() - NEXT(nExt) - BEGIN( bEgin +';' + ; ////// - ";" ; /* ;;;;;just trying to be smart;;;;;;; */ +//just to prevent any disaster if someone will want to run it + IF( .T. ) + RETURN nil + ENDIF + + NEXT(nExt) //in Clipper: NEXT does not match FOR + BEGIN( bEgin +';' + ;; //////Clipper doesn't like more then one ';' + ";" ; /* ;;;;;Clipper doesn't like this comment after ';' ;;;;;;; */ ) BREAK_(bReak) +// CASE(case) //it is not possible to call case() in this context + case :=CASE( CASE ) //this is valid RETURN nil /*================================================================ -************************************************ Checking for NEXT +* * * * * ** Checking for NEXT */ FUNCTION NeXT( next_next/*next next*/ ) Local nExt, nExt7, nExtNEXT @@ -23,15 +33,24 @@ Local nExt, nExt7, nExtNEXT OutStd( nExT ) // Actually this needs to use str() Next /*next*/ nExt //next -//NEXT + + FOR nExt = 1 TO nExt + QOut( nExt ) + NEXT + + FOR nExt :=1 TO 10 + QOut( nExt ) + NEXT ; ////////// ; + NEXT nExt := 10 //next - nExt++ /*n_ext*/ //--- + nExt++ /*in Clipper: NEXT does not match FOR*/ --nExt /*next*/ nExt7 :=7 nExtNEXT := nExt //next + nExt[ 1 ] :=nExt //in Clipper: NEXT does not match FOR nExt[ nExt ] := NEXT( nExt[nExt+nExt] * nExt *(nExt+nExt*5) ) IF( nExt > nExt+4 ) @@ -48,11 +67,10 @@ RETURN( nExt * /*next*/ nExt ) * Checking for BEGIN */ FUNCTION BEGIN( BEGIN_BEGIN ) -//LOCAL bEgin, xbEgin , bEginBEGIN , bEgin0, xbEginBEGIN:=100 LOCAL bEgin LOCAL xbEgin LOCAL bEginBEGIN -LOCAL bEgin0, /* BEGIN OF BEGIN */ ; /* begin */ +LOCAL bEgin0, /* BEGIN OF BEGIN */ ; /* in Clipper: Incomplete statement */ bEgin1 LOCAL xbEginBEGIN := 100 @@ -91,12 +109,28 @@ LOCAL bReak:=0 IF( bReak = 0 ) Break /*break*/ ( nil ) BREAK /* break to beggining */ - Break() //this line is not valid in Clipper: syntax error: ')' + Break() //in Clipper: syntax error: ')' ENDIF - Break /* break in break */ ;;; -; ///////////// - () + Break /**** BREAK AGAIN ****/; ;;;;; +; ////////////////////////////////////////////////// +; //What +; //the +; //comment +; //like +; //it +; //is +; //doing +; //in +; //this +; //place? +; //Do +; //you +; //use +; //it +; //often? +;/////////////////////////////////////////////////// + () //in Clipper: incomplete statement or unbalanced delimiters begin sequence FOR bReak:=1 To 10 @@ -109,4 +143,51 @@ recover USING bReak end BREAK -RETURN bReak[ bReak ] +RETURN bReak[ bReak ] //in Clipper: syntax error ' BREAK ' + +/*==================================================================== +* Test for CASE/DO CASE +*/ +FUNCTION CASE( case_ ) +LOCAL case + + FOR case:=1 TO 15 + QUOT( case ) + QOUT( case * ; //// +case ) + NEXT case + + case[ case ] :=case //in Clipper: Case is not immediatelly within DO CASE + case[ 2 ] :=2 //in Clipper: the same as above - Harbour compiles both + case =case + case - case + case :={|case| case( case )} + case :={|| case } + + DO /* case */ CASE + CASE 1 + case =case ** case + CASE 2+case + case =case +1 + CASE case++ +// case-- //sorry -Clipper also doesn't compile this line +// case++ //sorry -Clipper also doesn't compile this line + CASE ++case + ++case + CASE ; + case( case ) + CASE CASE + CASE !CASE + CASE -CASE + CASE +CASE +/* +* +* +*/ + CASE( CASE ) + case =case != case + CASE( CASE ) //new CASE or function call? :) + OTHERWISE + case *=case + ENDCASE + +RETURN case diff --git a/harbour/tests/working/statics.prg b/harbour/tests/working/statics.prg index 2d0227c072..317535bc9a 100644 --- a/harbour/tests/working/statics.prg +++ b/harbour/tests/working/statics.prg @@ -3,9 +3,9 @@ static z := "First" function Main() -LOCAL i +LOCAL i, cb - static a := "Hello", b := { 1, 3 } + static a := "Hello", b := { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } QOut( a ) QOut( b[ 2 ] ) @@ -17,6 +17,11 @@ LOCAL i FOR i:=1 TO 10 NumStat() NEXT + + cb :=DetachVar( 10 ) + FOR i:=1 To 10 + QOut( EVAL( cb, b[ i ] ) ) + NEXT return nil @@ -32,8 +37,20 @@ FUNCTION THREE( p ) QOut( p ) RETURN p -PROCEDURE NumStat() -STATIC n:=0 +PROCEDURE NumStat(a) +STATIC n:=1 +LOCAL cb +//STATIC m:=n //uncomment it to see an error +//STATIC m:=Time() //uncomment it to see an error + + cb :={|x| z +STR(x)} QOut( ++n ) - QOut( z ) -RETURN \ No newline at end of file + QOut( EVAL( cb,n ) ) + +RETURN + + +FUNCTION DetachVar( xLocal ) +STATIC xStatic:=100 + +RETURN( {|x| ++xStatic, x+xStatic+xLocal} ) \ No newline at end of file