From 912b301c8557d9a2badbf7bd0f2fa01d8f8a4ecb Mon Sep 17 00:00:00 2001 From: Ryszard Glab Date: Fri, 14 Jul 2006 13:47:17 +0000 Subject: [PATCH] 2006-07-14 16:00 UTC+0100 Ryszard Glab * include/hbcomp.h * include/hberrors.h * include/hbexpra.c * include/hbexprb.c * include/hbexprc.c * include/hbmacro.h * include/hbpcode.h * include/hbpp.h * include/hbxvm.h * source/common/expropt1.c * source/compiler/cmdcheck.c * source/compiler/expropta.c * source/compiler/exproptb.c * source/compiler/exproptc.c * source/compiler/genc.c * source/compiler/gencc.c * source/compiler/gencli.c * source/compiler/genhrb.c * source/compiler/genjava.c * source/compiler/genobj32.c * source/compiler/harbour.c * source/compiler/harbour.l * source/compiler/harbour.y * source/compiler/hbdead.c * source/compiler/hbfix.c * source/compiler/hbfunchk.c * source/compiler/hbgenerr.c * source/compiler/hblbl.c * source/compiler/hbpcode.c * source/compiler/hbstripl.c * source/macro/macroa.c * source/macro/macrob.c * source/macro/macroc.c * source/vm/hvm.c * source/vm/macro.c * fixed compilation of code that uses '@' pass by reference. The following syntax is no longer supported: var := IIF( .T., @var, var ) however you can still use the following: funcall( IIF( bPassbyRef, @someVar, someVar ) ) +added support for the following statement: WITH OBJECT ... END inside this statement you can use simplified form of sending messages to the object specified by :message( ) instead objexpression:message() :property instead objexpression:property The runtime error will be generated at the time of message sending (or property access/assign) if is not a value of type object. You can use the reserved property: :__withobject to access/assign the controlling object. *fixed support for command line response file (@file.clp) to be compatible with Clipper (Clipper genertes a single obj file) *fixed memory leaks when there is a fatal error in autoopened module (using DO ... statement) *implicit startup functions are removed from the list of functions before generation of output code * source/pp/ppcomp.c * source/pp/pplib.c * source/pp/ppcore.c * redefinition of #define no longer causes a memory leak * fixed repeatable optional clauses #xcommand SET [, ] WITH => :=[; :=] * fixed compilation of optional clauses (when used in different order then declared) -this fixes the following long waiting bug: #command MYCOMMAND [] [MYCLAUSE ] => ; MyFunction( {} [, ] ) MYCOMMAND MYCLAUSE 321 "HELLO" * fixed restricted macro match marker * tests/Makefile - tests/pretest.prg + utils/hbpptest + utils/hbpptest/Makefile + utils/hbpptest/pretest.prg * moved file 'pretest.prg' from tests to separate directory to make easier validation of the preprocessor * TODO * added note to fix hb_objGetMethod() so it will not generate error if there is no method * doc/en/clipper.txt * added documentation for WITH OBJECT usage --- harbour/ChangeLog | 93 +++ harbour/TODO | 7 + harbour/doc/en/clipper.txt | 105 +++ harbour/include/hbcomp.h | 9 +- harbour/include/hberrors.h | 1 + harbour/include/hbexpra.c | 26 +- harbour/include/hbexprb.c | 37 +- harbour/include/hbexprc.c | 63 +- harbour/include/hbmacro.h | 4 +- harbour/include/hbpcode.h | 5 +- harbour/include/hbpp.h | 2 +- harbour/include/hbxvm.h | 4 + harbour/source/common/expropt1.c | 5 + harbour/source/compiler/cmdcheck.c | 3 +- harbour/source/compiler/expropta.c | 2 +- harbour/source/compiler/exproptb.c | 2 +- harbour/source/compiler/exproptc.c | 2 +- harbour/source/compiler/genc.c | 38 +- harbour/source/compiler/gencc.c | 37 +- harbour/source/compiler/gencli.c | 3 - harbour/source/compiler/genhrb.c | 4 - harbour/source/compiler/genjava.c | 4 - harbour/source/compiler/genobj32.c | 13 +- harbour/source/compiler/harbour.c | 186 +++-- harbour/source/compiler/harbour.l | 17 +- harbour/source/compiler/harbour.y | 101 ++- harbour/source/compiler/hbdead.c | 3 + harbour/source/compiler/hbfix.c | 5 +- harbour/source/compiler/hbfunchk.c | 5 +- harbour/source/compiler/hbgenerr.c | 3 +- harbour/source/compiler/hblbl.c | 12 + harbour/source/compiler/hbpcode.c | 10 +- harbour/source/compiler/hbstripl.c | 5 +- harbour/source/macro/macroa.c | 2 +- harbour/source/macro/macrob.c | 2 +- harbour/source/macro/macroc.c | 2 +- harbour/source/pp/ppcomp.c | 4 +- harbour/source/pp/ppcore.c | 252 +++++-- harbour/source/pp/pplib.c | 2 +- harbour/source/vm/hvm.c | 191 ++++-- harbour/source/vm/macro.c | 7 +- harbour/tests/Makefile | 1 - harbour/tests/pretest.prg | 421 ------------ harbour/utils/hbpptest/Makefile | 28 + harbour/utils/hbpptest/pretest.prg | 1008 ++++++++++++++++++++++++++++ 45 files changed, 2007 insertions(+), 729 deletions(-) delete mode 100644 harbour/tests/pretest.prg create mode 100644 harbour/utils/hbpptest/Makefile create mode 100644 harbour/utils/hbpptest/pretest.prg diff --git a/harbour/ChangeLog b/harbour/ChangeLog index d399b2895b..fe3080a415 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,99 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ + It fixes compilation of empty .prg files in C++ mode + + * harbour/source/rtl/dbjoin.prg + - removed unused variable + +2006-07-14 16:00 UTC+0100 Ryszard Glab + * include/hbcomp.h + * include/hberrors.h + * include/hbexpra.c + * include/hbexprb.c + * include/hbexprc.c + * include/hbmacro.h + * include/hbpcode.h + * include/hbpp.h + * include/hbxvm.h + * source/common/expropt1.c + * source/compiler/cmdcheck.c + * source/compiler/expropta.c + * source/compiler/exproptb.c + * source/compiler/exproptc.c + * source/compiler/genc.c + * source/compiler/gencc.c + * source/compiler/gencli.c + * source/compiler/genhrb.c + * source/compiler/genjava.c + * source/compiler/genobj32.c + * source/compiler/harbour.c + * source/compiler/harbour.l + * source/compiler/harbour.y + * source/compiler/hbdead.c + * source/compiler/hbfix.c + * source/compiler/hbfunchk.c + * source/compiler/hbgenerr.c + * source/compiler/hblbl.c + * source/compiler/hbpcode.c + * source/compiler/hbstripl.c + * fixed compilation of code that uses '@' pass by + * source/macro/macrob.c + * source/macro/macroc.c + * source/vm/hvm.c + * source/vm/macro.c + * fixed compilation of code that uses '@' pass by + reference. The following syntax is no longer supported: + var := IIF( .T., @var, var ) + however you can still use the following: + funcall( IIF( bPassbyRef, @someVar, someVar ) ) + +added support for the following statement: + WITH OBJECT + ... + END + inside this statement you can use simplified form of sending + messages to the object specified by + :message( ) instead objexpression:message() + :property instead objexpression:property + The runtime error will be generated at the time of message + sending (or property access/assign) if + is not a value of type object. + You can use the reserved property: + :__withobject + to access/assign the controlling object. + *implicit startup functions are removed from the list of + to be compatible with Clipper (Clipper genertes a single + obj file) + *fixed memory leaks when there is a fatal error in autoopened + module (using DO ... statement) + *implicit startup functions are removed from the list of + functions before generation of output code + + #xcommand SET [, ] WITH => + * source/pp/pplib.c + * source/pp/ppcore.c + order then declared) -this fixes the following long + * fixed repeatable optional clauses + #xcommand SET [, ] WITH => + :=[; :=] + * fixed compilation of optional clauses (when used in different + order then declared) -this fixes the following long + waiting bug: + #command MYCOMMAND [] [MYCLAUSE ] => ; + MyFunction( {} [, ] ) + MYCOMMAND MYCLAUSE 321 "HELLO" + * fixed restricted macro match marker + + * tests/Makefile + - tests/pretest.prg + + utils/hbpptest + + utils/hbpptest/Makefile + + utils/hbpptest/pretest.prg + * moved file 'pretest.prg' from tests to separate directory + to make easier validation of the preprocessor + + * TODO + * added note to fix hb_objGetMethod() so it will not generate error if there is no method * doc/en/clipper.txt diff --git a/harbour/TODO b/harbour/TODO index 47fc62f074..e8a034c12a 100644 --- a/harbour/TODO +++ b/harbour/TODO @@ -221,6 +221,13 @@ Assign to: Ryszard Detail...: Real strong typing in the compiler. Status...: Open. +*** + +Assign to: ??? +Detail...: Remove generation of runtime error inside 'hb_objGetMethod' + for built-in classes (GET, TBROWSE,...) +Status...: Open. + ======================================================================= diff --git a/harbour/doc/en/clipper.txt b/harbour/doc/en/clipper.txt index 8efea8f13d..f2b9c98dc1 100644 --- a/harbour/doc/en/clipper.txt +++ b/harbour/doc/en/clipper.txt @@ -58,3 +58,108 @@ such case the program will never execute the "main" symbol. In Harbour the first *non* INIT/EXIT symbol, will be executed as the main symbol after all INIT procedures have been executed. +FOR EACH statement +------------------ +Harbour has support enumeration loop with the following syntax: + + FOR EACH var1 [,var255] IN expr1 [,expr255] [DESCEND] + [EXIT] + [LOOP] + ... + NEXT + +Note: + -expr can be a string or an array + -enumerator variable 'var' stores a reference to the element of + an array or a string specified by 'expr' thus assigments to the + enumerator changes the value of given array element + -after the loop the controlling variable(s) store the value which + they had before entering the loop + -the enumeraqtor variable supports the following properties + :__enumindex - the loop counter for variable + :__enumbase - the value that is being traversed + :__enumvalue - the value of variable + + +for example: + a = 'A' + b = 'B' + FOR EACH a,b IN { 1, 2, 3, 4 }, "abcd" + ? a, b //prints: 1 a + // 2 b + // 3 c + // 4 d + NEXT + ? a, b //prints: A B + + // you can use EXIT statement inside the loop + FOR EACH a IN { 1, 2, 3, 4 } + IF( a:__enumindex == 3 ) + ? a + EXIT + ENDIF + NEXT + + arr := { 1, 2, 3 } + str := "abc" + FOR EACH a, b IN arr, str + a *= 2 + str := UPPER( str ) + NEXT + //now 'arr' stores { 2, 4, 6 } + //howerer 'str' still stores "abc" + +Notice the difference: + FOR EACH a IN someValue + ? a:__enumindex //prints current value of the index + ? (a):__enumindex //sends '__enumindex' message to the current value + NEXT + + +WITH OBJECT +----------- +Harbour supports the following statement: + + WITH OBJECT expression + ... + END + + Inside this WITH OBJECT/END enclosure you can use the simplified + form of sending messages to the object. You can use the syntax + :message( [params] ) + :property + to send messages to the object specified by 'expression' + +for example: + WITH OBJECT myobj:a[1]:myitem + :message( 1 ) + :value := 9 + END + + The above code is equivalent to: + myobj:a[1]:myitem:message( 1 ) + myobj:a[1]:myitem:value := 9 + + Inside WITH OBJECT/END you can access (or even assign a new object) + using a special reserved property :__withobject + + The runtime error will be generated at the time of message + sending (or property access/assign) if + is not a value of type object. + +for example: + CLASS foo + DATA name INIT 'FOO' + ENDCLASS + + CLASS bar + DATA name INIT 'BAR' + ENDCLASS + + WITH OBJECT foo():new() + ? :name //prints 'FOO' + ? :__withobject:name //also prints 'FOO' + ? :__withobject := bar():new() + ? :name //prints 'BAR' + END + \ No newline at end of file diff --git a/harbour/include/hbcomp.h b/harbour/include/hbcomp.h index ce76f9a552..35a8cc82a1 100644 --- a/harbour/include/hbcomp.h +++ b/harbour/include/hbcomp.h @@ -260,6 +260,7 @@ typedef struct _HB_LABEL_INFO BOOL fSetSeqBegin; BOOL fCondJump; BOOL fForEach; + BOOL fWithObject; ULONG * pulLabels; } HB_LABEL_INFO, * PHB_LABEL_INFO; @@ -328,7 +329,7 @@ extern PINLINE hb_compInlineAdd( char * szFunName ); extern PFUNCTION hb_compFunCallAdd( char * szFuntionName ); extern PFUNCTION hb_compFunCallFind( char * szFunName ); /* locates a previously defined called function */ -extern void hb_compFunCallCheck( char *, int ); +extern BOOL hb_compFunCallCheck( char *, int ); extern void hb_compVariableAdd( char * szVarName, BYTE cType ); /* add a new param, local, static variable to a function definition or a public or private */ extern PVAR hb_compVariableFind( PVAR pVars, USHORT wOrder ); /* returns a variable if defined or zero */ @@ -394,8 +395,8 @@ extern void hb_compLinePush( void ); /* generates the pcode with the currently c extern void hb_compLinePushIfDebugger( void ); /* generates the pcode with the currently compiled source code line */ extern void hb_compLinePushIfInside( void ); /* generates the pcode with the currently compiled source code line */ -extern void hb_compGenMessage( char * szMsgName ); /* sends a message to an object */ -extern void hb_compGenMessageData( char * szMsg ); /* generates an underscore-symbol name for a data assignment */ +extern void hb_compGenMessage( char * szMsgName, BOOL bIsObject ); /* sends a message to an object */ +extern void hb_compGenMessageData( char * szMsg, BOOL bIsObject ); /* generates an underscore-symbol name for a data assignment */ extern void hb_compGenPopVar( char * szVarName ); /* generates the pcode to pop a value from the virtual machine stack onto a variable */ extern void hb_compGenPushDouble( double dNumber, BYTE bWidth, BYTE bDec ); /* Pushes a number on the virtual machine stack */ extern void hb_compGenPushFunCall( char * ); /* generates the pcode to push function's call */ @@ -470,7 +471,7 @@ extern void hb_compFileInfo( void ); extern void hb_compPrintLogo( void ); extern void hb_compPrintModes( void ); -extern int hb_compCompile( char * szPrg, int argc, char * argv[] ); +extern int hb_compCompile( char * szPrg, int argc, char * argv[], BOOL bSingleFile ); #endif /* HB_MACRO_SUPPORT */ diff --git a/harbour/include/hberrors.h b/harbour/include/hberrors.h index cc7c840ed0..23ac50cd18 100644 --- a/harbour/include/hberrors.h +++ b/harbour/include/hberrors.h @@ -119,6 +119,7 @@ HB_EXTERN_BEGIN #define HB_COMP_ERR_INVALID_DATE 57 #define HB_COMP_ERR_MEMOVERFLOW 58 #define HB_COMP_ERR_MEMCORRUPT 59 +#define HB_COMP_ERR_WITHOBJECT 60 #define HB_COMP_WARN_AMBIGUOUS_VAR 1 #define HB_COMP_WARN_MEMVAR_ASSUMED 2 diff --git a/harbour/include/hbexpra.c b/harbour/include/hbexpra.c index 7e3e228ee8..b2b9138b47 100644 --- a/harbour/include/hbexpra.c +++ b/harbour/include/hbexpra.c @@ -170,8 +170,8 @@ void hb_compExprClear( HB_EXPR_PTR pExpr ) #if defined( HB_MACRO_SUPPORT ) void hb_compExprDelete( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) { - HB_TRACE(HB_TR_DEBUG, ("hb_compExprDelete()")); - if( pExpr->ExprType != HB_ET_NONE ) + HB_TRACE(HB_TR_DEBUG, ("hb_compExprDelete(%p)",pExpr)); + if( pExpr && pExpr->ExprType != HB_ET_NONE ) { HB_EXPR_USE( pExpr, HB_EA_DELETE ); pExpr->ExprType = HB_ET_NONE; @@ -180,8 +180,8 @@ void hb_compExprDelete( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) #else void hb_compExprDelete( HB_EXPR_PTR pExpr ) { - HB_TRACE(HB_TR_DEBUG, ("hb_compExprDelete()")); - if( --pExpr->Counter == 0 ) + HB_TRACE(HB_TR_DEBUG, ("hb_compExprDelete(%p)", pExpr)); + if( pExpr && --pExpr->Counter == 0 ) { HB_EXPR_USE( pExpr, HB_EA_DELETE ); HB_XFREE( pExpr ); @@ -374,7 +374,13 @@ HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) iCount = 0; #ifndef HB_MACRO_SUPPORT - hb_compFunCallCheck( pName->value.asSymbol, iCount ); + if( ! hb_compFunCallCheck( pName->value.asSymbol, iCount ) ) + { + hb_compExprDelete( pName ); + if( pParms ) + hb_compExprDelete( pParms ); + return NULL; + } #endif /* TODO: EMPTY() (not done by Clipper) */ @@ -1030,10 +1036,12 @@ HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr ) #endif { - HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenStatement(%i)", pExpr->ExprType)); - - pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); - HB_EXPR_USE( pExpr, HB_EA_STATEMENT ); + HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenStatement(%p)", pExpr)); + if( pExpr ) + { + pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); + HB_EXPR_USE( pExpr, HB_EA_STATEMENT ); + } return pExpr; } diff --git a/harbour/include/hbexprb.c b/harbour/include/hbexprb.c index 18a706e319..591e9d78c8 100644 --- a/harbour/include/hbexprb.c +++ b/harbour/include/hbexprb.c @@ -2085,7 +2085,8 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) { case HB_EA_REDUCE: { - pSelf->value.asMessage.pObject = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_REDUCE ), HB_MACRO_PARAM ); + if( pSelf->value.asMessage.pObject ) + pSelf->value.asMessage.pObject = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_REDUCE ), HB_MACRO_PARAM ); if( pSelf->value.asMessage.pParms ) /* Is it a method call ? */ pSelf->value.asMessage.pParms = HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_REDUCE ); } @@ -2098,11 +2099,17 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) case HB_EA_PUSH_PCODE: { + BOOL bIsObject = (pSelf->value.asMessage.pObject != NULL); + /* pSelf->value.asMessage.pObject is NULL if WITH OBJECT is used */ + if( pSelf->value.asMessage.pParms ) /* Is it a method call ? */ { int iParms = hb_compExprListLen( pSelf->value.asMessage.pParms ); - HB_EXPR_PCODE1( hb_compGenMessage, pSelf->value.asMessage.szMessage ); - HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE2( hb_compGenMessage, pSelf->value.asMessage.szMessage, bIsObject ); + if( bIsObject ) + { + HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + } /* NOTE: if method with no parameters is called then the list * of parameters contain only one expression of type HB_ET_NONE * There is no need to push this parameter @@ -2120,8 +2127,11 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) else { /* acces to instance variable */ - HB_EXPR_PCODE1( hb_compGenMessage, pSelf->value.asMessage.szMessage ); - HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE2( hb_compGenMessage, pSelf->value.asMessage.szMessage, bIsObject ); + if( bIsObject ) + { + HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + } HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); } } @@ -2129,11 +2139,17 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) case HB_EA_POP_PCODE: { + BOOL bIsObject = (pSelf->value.asMessage.pObject != NULL); + /* pSelf->value.asMessage.pObject if WITH OBJECT is used */ + /* NOTE: This is an exception from the rule - this leaves * the return value on the stack */ - HB_EXPR_PCODE1( hb_compGenMessageData, pSelf->value.asMessage.szMessage ); - HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE2( hb_compGenMessageData, pSelf->value.asMessage.szMessage, bIsObject ); + if( bIsObject ) + { + HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + } HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE ); HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 1, ( BOOL ) 1 ); } @@ -2155,9 +2171,14 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) case HB_EA_DELETE: { - HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMessage.pObject ); + if( pSelf->value.asMessage.pObject ) + { + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMessage.pObject ); + } if( pSelf->value.asMessage.pParms ) + { HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMessage.pParms ); + } #if defined( HB_MACRO_SUPPORT ) HB_XFREE( pSelf->value.asMessage.szMessage ); #endif diff --git a/harbour/include/hbexprc.c b/harbour/include/hbexprc.c index e51e245bb8..a5c80f0d91 100644 --- a/harbour/include/hbexprc.c +++ b/harbour/include/hbexprc.c @@ -71,6 +71,33 @@ /* ************************************************************************* */ +#if defined( HB_MACRO_SUPPORT ) +static void hb_compExprSendPopPush( HB_EXPR_PTR pObj, HB_MACRO_DECL ) +#else +static void hb_compExprSendPopPush( HB_EXPR_PTR pObj ) +#endif +{ + if( pObj->value.asMessage.pObject ) + { + /* Push _message for later use */ + HB_EXPR_PCODE2( hb_compGenMessageData, pObj->value.asMessage.szMessage, TRUE ); + /* Push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + + /* Now push current value of variable */ + HB_EXPR_PCODE2( hb_compGenMessage, pObj->value.asMessage.szMessage, TRUE ); + /* Push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + } + else + { + /* Push _message for later use */ + HB_EXPR_PCODE2( hb_compGenMessageData, pObj->value.asMessage.szMessage, FALSE ); + /* Now push current value of variable */ + HB_EXPR_PCODE2( hb_compGenMessage, pObj->value.asMessage.szMessage, FALSE ); + } +} + #if defined( HB_MACRO_SUPPORT ) void hb_compExprDelOperator( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) #else @@ -98,17 +125,7 @@ void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) */ if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) { - HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; - - /* Push _message for the later assignment. */ - HB_EXPR_PCODE1( hb_compGenMessageData, pObj->value.asMessage.szMessage ); - /* Push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - - /* Now push current value of variable */ - HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage ); - /* push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compExprSendPopPush, pSelf->value.asOperator.pLeft ); /* Do it. */ HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); @@ -263,17 +280,7 @@ void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) */ if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) { - HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; - - /* Push _message for the later assignment. */ - HB_EXPR_PCODE1( hb_compGenMessageData, pObj->value.asMessage.szMessage ); - /* Push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - - /* Now push current value of variable */ - HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage ); - /* Push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compExprSendPopPush, pSelf->value.asOperator.pLeft ); /* Do it.*/ HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); @@ -402,17 +409,7 @@ void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper ) */ if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) { - HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; - - /* Push _message for later use */ - HB_EXPR_PCODE1( hb_compGenMessageData, pObj->value.asMessage.szMessage ); - /* Push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); - - /* Now push current value of variable */ - HB_EXPR_PCODE1( hb_compGenMessage, pObj->value.asMessage.szMessage ); - /* Push object */ - HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compExprSendPopPush, pSelf->value.asOperator.pLeft ); /* Do it. */ HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 0, ( BOOL ) 1 ); diff --git a/harbour/include/hbmacro.h b/harbour/include/hbmacro.h index c813f396dd..23629e122d 100644 --- a/harbour/include/hbmacro.h +++ b/harbour/include/hbmacro.h @@ -134,8 +134,8 @@ extern void hb_compMemvarGenPCode( BYTE bPCode, char * szVarName, HB_BISON_PTR p extern void hb_compGenPushSymbol( char * szSymbolName, BOOL bFunction, BOOL bAlias, HB_BISON_PTR pMacro ); extern void hb_compGenPushLong( HB_LONG lNumber, HB_BISON_PTR pMacro ); extern void hb_compGenPushDate( HB_LONG lNumber, HB_BISON_PTR pMacro ); -extern void hb_compGenMessage( char * szMsgName, HB_BISON_PTR pMacro ); -extern void hb_compGenMessageData( char * szMsg, HB_BISON_PTR pMacro ); +extern void hb_compGenMessage( char * szMsgName, BOOL bIsObject, HB_BISON_PTR pMacro ); +extern void hb_compGenMessageData( char * szMsg, BOOL bIsObject, HB_BISON_PTR pMacro ); extern void hb_compGenPopVar( char * szVarName, HB_BISON_PTR pMacro ); extern void hb_compGenPopAliasedVar( char * szVarName, BOOL bPushAliasValue, diff --git a/harbour/include/hbpcode.h b/harbour/include/hbpcode.h index 268f2cd6c1..c7abd54fae 100644 --- a/harbour/include/hbpcode.h +++ b/harbour/include/hbpcode.h @@ -214,8 +214,11 @@ typedef enum HB_P_MINUSEQ, /* 140 subs a value from the variable reference, leave result on the stack */ HB_P_MULTEQ, /* 141 multiplies a variable reference by a value, leave result on the stack */ HB_P_DIVEQ, /* 142 divides the var reference by a value, leave result on the stack */ + HB_P_WITHOBJECTSTART, /* 143 start WITH OBJECT code */ + HB_P_WITHOBJECTMESSAGE, /* 144 push message for WITH OBJECT */ + HB_P_WITHOBJECTEND, /* 145 end WITH OBJECT code */ /* NOTE: This have to be the last definition */ - HB_P_LAST_PCODE /* 143 this defines the number of defined pcodes */ + HB_P_LAST_PCODE /* 146 this defines the number of defined pcodes */ } HB_PCODE; #endif /* HB_PCODE_H_ */ diff --git a/harbour/include/hbpp.h b/harbour/include/hbpp.h index 1a7b3d0209..f915dd87d2 100644 --- a/harbour/include/hbpp.h +++ b/harbour/include/hbpp.h @@ -99,7 +99,7 @@ extern void hb_pp_Init( void ); extern void hb_pp_Free( void ); extern void hb_pp_CloseInclude( void ); extern int hb_pp_ParseDirective( char * ); /* Parsing preprocessor directives ( #... ) */ -extern int hb_pp_ParseExpression( char *, char * ); /* Parsing a line ( without preprocessor directive ) */ +extern int hb_pp_ParseExpression( char *, char *, BOOL ); /* Parsing a line ( without preprocessor directive ) */ extern int hb_pp_WrStr( FILE *, char * ); extern int hb_pp_RdStr( FILE *, char *, int, BOOL, char *, int *, int * ); extern void hb_pp_Stuff( char *, char *, int, int, int ); diff --git a/harbour/include/hbxvm.h b/harbour/include/hbxvm.h index b15d8f0dd8..948b5886da 100644 --- a/harbour/include/hbxvm.h +++ b/harbour/include/hbxvm.h @@ -83,6 +83,10 @@ extern HB_EXPORT BOOL hb_xvmEnumNext( void ); /* increment F extern HB_EXPORT BOOL hb_xvmEnumPrev( void ); /* decrement FOR EACH loop counter */ extern HB_EXPORT void hb_xvmEnumEnd( LONG * ); /* rewind the stack after FOR EACH loop counter */ +extern HB_EXPORT void hb_xvmWithObjectStart( void ); /* prepare WITH OBJECT staement */ +extern HB_EXPORT void hb_xvmWithObjectEnd( void ); /* rewind the stack after normal WITH OBJECT */ +extern HB_EXPORT LONG hb_xvmWithObjectBase( LONG * ); /* get/restore previous WITH OBJECT stack frame */ + extern HB_EXPORT void hb_xvmSetLine( USHORT uiLine ); /* set .prg line number information */ extern HB_EXPORT void hb_xvmFrame( int iLocals, int iParams ); /* increases the stack pointer for the amount of locals and params suplied */ diff --git a/harbour/source/common/expropt1.c b/harbour/source/common/expropt1.c index c077eef1e6..142067708a 100644 --- a/harbour/source/common/expropt1.c +++ b/harbour/source/common/expropt1.c @@ -259,7 +259,12 @@ char *hb_compExprAsSymbol( HB_EXPR_PTR pExpr ) { case HB_ET_VARIABLE: case HB_ET_VARREF: + case HB_ET_FUNNAME: return pExpr->value.asSymbol ; + break; + + case HB_ET_FUNCALL: + return pExpr->value.asFunCall.pFunName->value.asSymbol; } return NULL; } diff --git a/harbour/source/compiler/cmdcheck.c b/harbour/source/compiler/cmdcheck.c index 9d3337a7e9..0ecb89f342 100644 --- a/harbour/source/compiler/cmdcheck.c +++ b/harbour/source/compiler/cmdcheck.c @@ -765,8 +765,9 @@ void hb_compChkEnvironVar( char *szSwitch ) case 'P': if( *( s + 1 ) == '-' ) hb_comp_bPPO = 0; - else + else if( ! hb_comp_bPPO ) { + /* do not set a path if option specified more then once */ char *szPath = hb_strdup( s + 1 ); hb_comp_pPpoPath = hb_fsFNameSplit( szPath ); diff --git a/harbour/source/compiler/expropta.c b/harbour/source/compiler/expropta.c index f9e080aae3..3dfb87c7da 100644 --- a/harbour/source/compiler/expropta.c +++ b/harbour/source/compiler/expropta.c @@ -5,6 +5,6 @@ /* hbexpra.c is also included from ../macro/macro.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.21 - ignore this magic number - this is used to force compilation + * 1.22 - ignore this magic number - this is used to force compilation */ #include "hbexpra.c" diff --git a/harbour/source/compiler/exproptb.c b/harbour/source/compiler/exproptb.c index a90876e746..0ffb734ad0 100644 --- a/harbour/source/compiler/exproptb.c +++ b/harbour/source/compiler/exproptb.c @@ -5,6 +5,6 @@ /* hbexprb.c is also included from ../macro/macro.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.17 - ignore this magic number - this is used to force compilation + * 1.18 - ignore this magic number - this is used to force compilation */ #include "hbexprb.c" diff --git a/harbour/source/compiler/exproptc.c b/harbour/source/compiler/exproptc.c index 82bfb3eaa7..8127e1992d 100644 --- a/harbour/source/compiler/exproptc.c +++ b/harbour/source/compiler/exproptc.c @@ -5,6 +5,6 @@ /* hbexprc.c is also included from ../macro/macro.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.9 - ignore this magic number - this is used to force compilation + * 1.10 - ignore this magic number - this is used to force compilation */ #include "hbexprc.c" diff --git a/harbour/source/compiler/genc.c b/harbour/source/compiler/genc.c index 844d6687a4..4d1e52c48d 100644 --- a/harbour/source/compiler/genc.c +++ b/harbour/source/compiler/genc.c @@ -98,9 +98,6 @@ void hb_compGenCCode( PHB_FNAME pFileName ) /* generates the C language ou fprintf( yyc, "\n\n" ); - if( ! hb_comp_bStartProc ) - pFunc = pFunc->pNext; /* No implicit starting procedure */ - /* write functions prototypes for PRG defined functions */ while( pFunc ) { @@ -235,9 +232,6 @@ void hb_compGenCCode( PHB_FNAME pFileName ) /* generates the C language ou */ pFunc = hb_comp_functions.pFirst; - if( ! hb_comp_bStartProc ) - pFunc = pFunc->pNext; /* No implicit starting procedure */ - while( pFunc ) { bIsInitStatics = ( pFunc == hb_comp_pInitFunc ); @@ -1952,6 +1946,33 @@ static HB_GENC_FUNC( hb_p_diveq ) return 1; } +static HB_GENC_FUNC( hb_p_withobjectstart ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_WITHOBJECTSTART,\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_withobjectmessage ) +{ + fprintf( cargo->yyc, "\tHB_P_WITHOBJECTMESSAGE, %i, %i,", + pFunc->pCode[ lPCodePos + 1 ], + pFunc->pCode[ lPCodePos + 2 ] ); + if( cargo->bVerbose ) fprintf( cargo->yyc, "\t/* %s */", hb_compSymbolGetPos( HB_PCODE_MKUSHORT( &( pFunc->pCode[ lPCodePos + 1 ] ) ) )->szName ); + fprintf( cargo->yyc, "\n" ); + return 3; +} + +static HB_GENC_FUNC( hb_p_withobjectend ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_WITHOBJECTEND,\n" ); + return 1; +} /* NOTE: The order of functions have to match the order of opcodes * mnemonics @@ -2104,7 +2125,10 @@ static HB_GENC_FUNC_PTR s_verbose_table[] = { hb_p_pluseq, hb_p_minuseq, hb_p_multeq, - hb_p_diveq + hb_p_diveq, + hb_p_withobjectstart, + hb_p_withobjectmessage, + hb_p_withobjectend }; static void hb_compGenCReadable( PFUNCTION pFunc, FILE * yyc ) diff --git a/harbour/source/compiler/gencc.c b/harbour/source/compiler/gencc.c index b6aaa7fa57..ab2762d3bc 100644 --- a/harbour/source/compiler/gencc.c +++ b/harbour/source/compiler/gencc.c @@ -1551,6 +1551,32 @@ static HB_GENC_FUNC( hb_p_diveq ) return 1; } +static HB_GENC_FUNC( hb_p_withobjectstart ) +{ + HB_GENC_LABEL(); + + fprintf( cargo->yyc, "\thb_xvmWithObjectStart();\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_withobjectend ) +{ + HB_GENC_LABEL(); + + fprintf( cargo->yyc, "\thb_xvmWithObjectEnd();\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_withobjectmessage ) +{ + HB_GENC_LABEL(); + + fprintf( cargo->yyc, "\thb_xvmPushSymbol( symbols + %hu );\n", + HB_PCODE_MKUSHORT( &pFunc->pCode[ lPCodePos + 1 ] ) ); + fprintf( cargo->yyc, "\thb_vmPush( hb_stackItem( s_lWithObjectBase ) );\n" ); + + return 3; +} /* NOTE: The order of functions have to match the order of opcodes * mnemonics @@ -1703,7 +1729,10 @@ static HB_GENC_FUNC_PTR s_verbose_table[] = { hb_p_pluseq, hb_p_minuseq, hb_p_multeq, - hb_p_diveq + hb_p_diveq, + hb_p_withobjectstart, + hb_p_withobjectmessage, + hb_p_withobjectend }; void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) @@ -1716,7 +1745,7 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) label_info.yyc = yyc; label_info.fVerbose = ( hb_comp_iGenCOutput == HB_COMPGENC_VERBOSE ); label_info.fSetSeqBegin = FALSE; - label_info.fCondJump = label_info.fForEach = FALSE; + label_info.fCondJump = label_info.fForEach = label_info.fWithObject = FALSE; if( pFunc->lPCodePos == 0 ) label_info.pulLabels = NULL; else @@ -1730,6 +1759,8 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) fprintf( yyc, " ULONG ulPrivateBase = hb_memvarGetPrivatesBase();\n" ); if( label_info.fForEach ) fprintf( yyc, " LONG lForEachBase = 0;\n" ); + if( label_info.fWithObject ) + fprintf( yyc, " LONG lWithObjectBase = hb_xvmWithObjectBase(NULL);\n" ); if( label_info.fCondJump ) fprintf( yyc, " BOOL fValue;\n" ); fprintf( yyc, " do {\n" ); @@ -1739,6 +1770,8 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) fprintf( yyc, " } while ( 0 );\n" ); if( label_info.fForEach ) fprintf( yyc, " while( lForEachBase )\n {\n\thb_stackRemove( lForEachBase );\n\thb_xvmEnumEnd( &lForEachBase );\n }\n" ); + if( label_info.fWithObject ) + fprintf( yyc, " hb_xvmWithObjectBase( &lWithObjectBase );\n" ); fprintf( yyc, " hb_xvmExitProc( ulPrivateBase );\n" ); fprintf( yyc, "}\n" ); diff --git a/harbour/source/compiler/gencli.c b/harbour/source/compiler/gencli.c index 130076d7c5..47fc13deb9 100644 --- a/harbour/source/compiler/gencli.c +++ b/harbour/source/compiler/gencli.c @@ -107,9 +107,6 @@ void hb_compGenILCode( PHB_FNAME pFileName ) /* generates the IL output */ */ pFunc = hb_comp_functions.pFirst; - if( ! hb_comp_bStartProc ) - pFunc = pFunc->pNext; /* No implicit starting procedure */ - while( pFunc ) { bIsInitFunction = ( pFunc->cScope & HB_FS_INIT ) ; diff --git a/harbour/source/compiler/genhrb.c b/harbour/source/compiler/genhrb.c index cb164df4c9..ac004d3956 100644 --- a/harbour/source/compiler/genhrb.c +++ b/harbour/source/compiler/genhrb.c @@ -96,8 +96,6 @@ void hb_compGenPortObj( PHB_FNAME pFileName ) } pFunc = hb_comp_functions.pFirst; - if( ! hb_comp_bStartProc ) - pFunc = pFunc->pNext; lSymbols = 0; /* Count number of symbols */ while( pFunc ) @@ -113,8 +111,6 @@ void hb_compGenPortObj( PHB_FNAME pFileName ) /* Generate functions data */ pFunc = hb_comp_functions.pFirst; - if( ! hb_comp_bStartProc ) - pFunc = pFunc->pNext; /* No implicit starting procedure */ while( pFunc ) { diff --git a/harbour/source/compiler/genjava.c b/harbour/source/compiler/genjava.c index 35047e0c2d..5c480e7b3c 100644 --- a/harbour/source/compiler/genjava.c +++ b/harbour/source/compiler/genjava.c @@ -112,8 +112,6 @@ void hb_compGenJava( PHB_FNAME pFileName ) } pFunc = hb_comp_functions.pFirst; - if( ! hb_comp_bStartProc ) - pFunc = pFunc->pNext; lSymbols = 0; /* Count number of symbols */ while( pFunc ) @@ -129,8 +127,6 @@ void hb_compGenJava( PHB_FNAME pFileName ) /* Generate functions data */ pFunc = hb_comp_functions.pFirst; - if( ! hb_comp_bStartProc ) - pFunc = pFunc->pNext; /* No implicit starting procedure */ while( pFunc ) { diff --git a/harbour/source/compiler/genobj32.c b/harbour/source/compiler/genobj32.c index 1b8da1d976..7f0b053b31 100644 --- a/harbour/source/compiler/genobj32.c +++ b/harbour/source/compiler/genobj32.c @@ -129,9 +129,6 @@ static ULONG GetPCodesSize( void ) ULONG ulTotal = 0; PFUNCTION pFunction = hb_comp_functions.pFirst; - if( ! hb_comp_bStartProc ) - pFunction = pFunction->pNext; - while( pFunction ) { ulTotal += pFunction->lPCodePos; @@ -281,9 +278,9 @@ static void GenerateDataSegment( FILE * hObjFile ) static void GenerateCodeSegment( FILE * hObjFile ) { - USHORT wFunctions = hb_comp_functions.iCount - ( hb_comp_bStartProc ? 0: 1 ); + USHORT wFunctions = hb_comp_functions.iCount; ULONG ulSize = wFunctions * sizeof( prgFunction ); - PFUNCTION pFunc = ( hb_comp_bStartProc ? hb_comp_functions.pFirst: hb_comp_functions.pFirst->pNext ); + PFUNCTION pFunc = hb_comp_functions.pFirst; USHORT w = 0; DefineSegment( hObjFile, 2, /* "_TEXT" position + 1 into localNames */ @@ -469,9 +466,6 @@ static void CodeSegment( FILE * hObjFile, BYTE * prgCode, ULONG ulPrgLen, USHORT PFUNCTION pFunction = hb_comp_functions.pFirst; ULONG ulPCodeOffset = hb_comp_symbols.iCount * sizeof( HB_SYMB ); - if( ! hb_comp_bStartProc ) - pFunction = pFunction->pNext; - putbyte( 0xA0, hObjFile, &bChk ); putword( wTotalLen, hObjFile, &bChk ); putbyte( 1, hObjFile, &bChk ); /* 1 = _TEXT segment */ @@ -500,9 +494,6 @@ static void DataSegment( FILE * hObjFile, BYTE * symbol, ULONG wSymLen, ULONG wS ULONG ulSymbolNameOffset = GetSymbolsSize() + GetPCodesSize(); ULONG ulFunctionOffset; - if( ! hb_comp_bStartProc ) - pFunction = pFunction->pNext; - putbyte( 0xA0, hObjFile, &bChk ); putword( wTotalLen, hObjFile, &bChk ); putbyte( 4, hObjFile, &bChk ); /* 2 = _DATA segment defined order */ diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index 69674bf30c..f069c8dff7 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -112,6 +112,7 @@ PCOMDECLARED hb_comp_pLastMethod; int hb_comp_iLine; /* currently processed line number (globaly) */ char * hb_comp_szFile; /* Source file name of compiled module */ PFUNCTION hb_comp_pInitFunc; +PHB_FNAME hb_comp_pMainFileName = NULL; PHB_FNAME hb_comp_pFileName = NULL; PHB_FNAME hb_comp_pFilePpo = NULL; @@ -172,7 +173,7 @@ static BOOL hb_comp_bExternal = FALSE; */ static PEXTERN hb_comp_pExterns = NULL; static PAUTOOPEN hb_comp_pAutoOpen = NULL; -static int hb_compAutoOpen( char * szPrg, BOOL * bSkipGen ); +static int hb_compAutoOpen( char * szPrg, BOOL * bSkipGen, BOOL bSingleFile ); /* -m Support */ static BOOL hb_compAutoOpenFind( char * szName ); @@ -278,7 +279,7 @@ int main( int argc, char * argv[] ) if( argv[ i ][ 0 ] == '@' ) iStatus = hb_compProcessRSPFile( argv[ i ] + 1, argc, argv ); else - iStatus = hb_compCompile( argv[ i ], argc, argv ); + iStatus = hb_compCompile( argv[ i ], argc, argv, TRUE ); if( iStatus != EXIT_SUCCESS ) break; @@ -338,7 +339,7 @@ void hb_compMainExit( void ) hb_xfree( pAutoOpen->szName ); hb_xfree( pAutoOpen ); } - + hb_xexit(); } @@ -357,7 +358,6 @@ static int hb_compProcessRSPFile( char * szRspName, int argc, char * argv[] ) hb_fsFNameMerge( szFile, pFileName ); szRspName = szFile; } - hb_xfree( pFileName ); inFile = fopen( szRspName, "r" ); if( !inFile ) @@ -367,7 +367,10 @@ static int hb_compProcessRSPFile( char * szRspName, int argc, char * argv[] ) } else { - int iProcess = 1, i = 0, ch; + int i = 0, ch; + BOOL bAutoOpen = hb_comp_bAutoOpen; + + hb_comp_bAutoOpen = TRUE; do { @@ -388,23 +391,16 @@ static int hb_compProcessRSPFile( char * szRspName, int argc, char * argv[] ) continue; } + while( i == 0 && HB_ISSPACE( ch ) ) + ch = fgetc( inFile ); + if( ch == EOF || HB_ISSPACE( ch ) || ch == '#' ) { szFile[ i ] = '\0'; if( i > 0 ) - { - if( iProcess > 1 ) - hb_pp_Init(); - - iStatus = hb_compCompile( szFile, argc, argv ); - - if( iStatus != EXIT_SUCCESS ) - break; - - iProcess ++; - i = 0; - } + hb_compAutoOpenAdd( szFile ); + i = 0; while( ch != EOF && ch != '\n' ) ch = fgetc( inFile ); } @@ -414,6 +410,12 @@ static int hb_compProcessRSPFile( char * szRspName, int argc, char * argv[] ) while( ch != EOF ); fclose ( inFile ); + + hb_comp_bAutoOpen = bAutoOpen; + + hb_fsFNameMerge( szFile, pFileName ); + hb_xfree( pFileName ); + hb_compCompile( szFile, argc, argv, FALSE ); } return iStatus; @@ -3059,7 +3061,12 @@ void hb_compGenVarPCode( BYTE bPCode, char * szVarName ) hb_compGenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ), ( BOOL ) 1 ); } -void hb_compGenMessage( char * szMsgName ) /* sends a message to an object */ +/* sends a message to an object */ +/* bIsObject = TRUE if we are sending a message to real object + bIsObject is FALSE if we are sending a message to an object specified + with WITH OBJECT statement. +*/ +void hb_compGenMessage( char * szMsgName, BOOL bIsObject ) { USHORT wSym; PCOMSYMBOL pSym = hb_compSymbolFind( szMsgName, &wSym, HB_SYM_MSGNAME ); @@ -3067,17 +3074,20 @@ void hb_compGenMessage( char * szMsgName ) /* sends a message to an object if( ! pSym ) /* the symbol was not found on the symbol table */ pSym = hb_compSymbolAdd( szMsgName, &wSym, HB_SYM_MSGNAME ); pSym->cScope |= HB_FS_MESSAGE; - hb_compGenPCode3( HB_P_MESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), ( BOOL ) 1 ); + if( bIsObject ) + hb_compGenPCode3( HB_P_MESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), ( BOOL ) 1 ); + else + hb_compGenPCode3( HB_P_WITHOBJECTMESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ), ( BOOL ) 1 ); } -void hb_compGenMessageData( char * szMsg ) /* generates an underscore-symbol name for a data assignment */ +void hb_compGenMessageData( char * szMsg, BOOL bIsObject ) /* generates an underscore-symbol name for a data assignment */ { char * szResult = ( char * ) hb_xgrab( strlen( szMsg ) + 2 ); strcpy( szResult, "_" ); strcat( szResult, szMsg ); - hb_compGenMessage( hb_compIdentifierNew( szResult, TRUE ) ); + hb_compGenMessage( hb_compIdentifierNew( szResult, TRUE ), bIsObject ); hb_xfree( szResult ); } @@ -4793,14 +4803,14 @@ static void hb_compOutputFile( void ) } } -int hb_compCompile( char * szPrg, int argc, char * argv[] ) +int hb_compCompile( char * szPrg, int argc, char * argv[], BOOL bSingleFile ) { int iStatus = EXIT_SUCCESS; - PHB_FNAME pFileName; HB_TRACE(HB_TR_DEBUG, ("hb_pp_compCompile(%s,%i)", szPrg, argc)); - hb_comp_pFileName = hb_fsFNameSplit( szPrg ); + hb_comp_pMainFileName = hb_fsFNameSplit( szPrg ); + hb_comp_pFileName = hb_comp_pMainFileName; if( hb_comp_pFileName->szName ) { @@ -4812,7 +4822,7 @@ int hb_compCompile( char * szPrg, int argc, char * argv[] ) hb_fsFNameMerge( szFileName, hb_comp_pFileName ); - if( hb_comp_bPPO ) + if( hb_comp_bPPO && bSingleFile ) { hb_comp_pFilePpo = hb_fsFNameSplit( szPrg ); hb_compPpoFile(); @@ -4840,59 +4850,62 @@ int hb_compCompile( char * szPrg, int argc, char * argv[] ) hb_comp_szFile = szFileName; - if( ! hb_comp_bQuiet ) + if( bSingleFile ) { - if( hb_comp_bPPO ) - printf( "Compiling '%s' and generating preprocessed output to '%s'...\n", szFileName, szPpoName ); - else - printf( "Compiling '%s'...\n", szFileName ); - } + if( ! hb_comp_bQuiet ) + { + if( hb_comp_bPPO ) + printf( "Compiling '%s' and generating preprocessed output to '%s'...\n", szFileName, szPpoName ); + else + printf( "Compiling '%s'...\n", szFileName ); + } - /* Generate the starting procedure frame */ - if( hb_comp_bStartProc ) - { - hb_compFunctionAdd( hb_compIdentifierNew( hb_strupr( hb_strdup( hb_comp_pFileName->szName ) ), FALSE ), HB_FS_PUBLIC, FUN_PROCEDURE ); + /* Generate the starting procedure frame */ + if( hb_comp_bStartProc ) + { + hb_compFunctionAdd( hb_compIdentifierNew( hb_strupr( hb_strdup( hb_comp_pFileName->szName ) ), FALSE ), HB_FS_PUBLIC, FUN_PROCEDURE ); + } + else + { + /* Don't pass the name of module if the code for starting procedure + * will be not generated. The name cannot be placed as first symbol + * because this symbol can be used as function call or memvar's name. + */ + hb_compFunctionAdd( hb_compIdentifierNew( "", TRUE ), HB_FS_PUBLIC, FUN_PROCEDURE ); + } + + yyparse(); + + if( hb_comp_bPPO && hb_comp_yyppo ) + { + fclose( hb_comp_yyppo ); + hb_comp_yyppo = NULL; + if( hb_comp_pFilePpo ) + hb_xfree( hb_comp_pFilePpo ); + hb_comp_pFilePpo = NULL; + } } else { - /* Don't pass the name of module if the code for starting procedure - * will be not generated. The name cannot be placed as first symbol - * because this symbol can be used as function call or memvar's name. - */ - hb_compFunctionAdd( hb_compIdentifierNew( "", TRUE ), HB_FS_PUBLIC, FUN_PROCEDURE ); + printf( "Reading '%s'...\n", szFileName ); } - - yyparse(); - - if( hb_comp_bPPO && hb_comp_yyppo ) - { - fclose( hb_comp_yyppo ); - hb_comp_yyppo = NULL; - if( hb_comp_pFilePpo ) - hb_xfree( hb_comp_pFilePpo ); - hb_comp_pFilePpo = NULL; - } - - /* Saving main file. */ - pFileName = hb_comp_pFileName; - - /* Open refernced modules. */ + + /* Open refernced modules (using DO ... WITh statement + * or from @.clp command line option + */ while( hb_comp_pAutoOpen ) { PAUTOOPEN pAutoOpen = hb_comp_pAutoOpen; - hb_comp_pAutoOpen = hb_comp_pAutoOpen->pNext; - if( ! hb_compFunctionFind( pAutoOpen->szName ) ) - hb_compAutoOpen( pAutoOpen->szName, &bSkipGen ); + hb_compAutoOpen( pAutoOpen->szName, &bSkipGen, bSingleFile ); + + hb_comp_pAutoOpen = hb_comp_pAutoOpen->pNext; hb_xfree( pAutoOpen->szName ); hb_xfree( pAutoOpen ); } - /* Restoring main file. */ - hb_comp_pFileName = pFileName; - /* Begin of finalization phase. */ /* fix all previous function returns offsets */ @@ -4955,17 +4968,34 @@ int hb_compCompile( char * szPrg, int argc, char * argv[] ) hb_compOutputFile(); if( ! hb_comp_bStartProc ) - --hb_comp_iFunctionCnt; + { + /* remove function frames with no names */ + PFUNCTION *pFunPtr = &hb_comp_functions.pFirst; + + while( *pFunPtr ) + { + if( ! (*pFunPtr)->szName[0] ) + { + *pFunPtr = hb_compFunctionKill( *pFunPtr ); + hb_comp_functions.iCount--; + } + else + { + hb_compOptimizeFrames( *pFunPtr ); + + if( szFirstFunction == NULL && + ! ( ( *pFunPtr )->cScope & (HB_FS_INIT || HB_FS_EXIT) ) ) + { + szFirstFunction = ( *pFunPtr )->szName; + } + pFunPtr = &(*pFunPtr)->pNext; + } + } + } pFunc = hb_comp_functions.pFirst; while( pFunc ) { - hb_compOptimizeFrames( pFunc ); - - if( szFirstFunction == NULL && pFunc->szName[0] && ! ( pFunc->cScope & HB_FS_INIT || pFunc->cScope & HB_FS_EXIT ) ) - { - szFirstFunction = pFunc->szName; - } pFunc = pFunc->pNext; } @@ -5019,6 +5049,14 @@ static void hb_compCompileEnd( void ) if( hb_comp_pFileName ) { + if( hb_comp_pFileName != hb_comp_pMainFileName && hb_comp_pFileName ) + { + /* currently compiled file was autoopened - close also + * the main module + */ + hb_xfree( hb_comp_pMainFileName ); + hb_comp_pMainFileName = NULL; + } hb_xfree( hb_comp_pFileName ); hb_comp_pFileName = NULL; } @@ -5191,9 +5229,10 @@ BOOL hb_compAutoOpenFind( char * szName ) return FALSE; } -int hb_compAutoOpen( char * szPrg, BOOL * pbSkipGen ) +int hb_compAutoOpen( char * szPrg, BOOL * pbSkipGen, BOOL bSingleFile ) { int iStatus = EXIT_SUCCESS; + PHB_FNAME pMainFileName = hb_comp_pFileName; hb_comp_pFileName = hb_fsFNameSplit( szPrg ); @@ -5211,6 +5250,8 @@ int hb_compAutoOpen( char * szPrg, BOOL * pbSkipGen ) { hb_comp_pFileName->szExtension = ".ppo"; hb_fsFNameMerge( szPpoName, hb_comp_pFileName ); + if( hb_comp_yyppo ) + fclose( hb_comp_yyppo ); hb_comp_yyppo = fopen( szPpoName, "w" ); if( ! hb_comp_yyppo ) { @@ -5243,7 +5284,9 @@ int hb_compAutoOpen( char * szPrg, BOOL * pbSkipGen ) /* Generate the starting procedure frame */ if( hb_comp_bStartProc ) - hb_compFunctionAdd( hb_strupr( hb_strdup( hb_comp_pFileName->szName ) ), HB_FS_PUBLIC, FUN_PROCEDURE ); + hb_compFunctionAdd( hb_compIdentifierNew( hb_strupr( hb_comp_pFileName->szName ), TRUE ) , HB_FS_PUBLIC, FUN_PROCEDURE ); + else if( ! bSingleFile ) + hb_compFunctionAdd( hb_compIdentifierNew( "", TRUE ), HB_FS_PUBLIC, FUN_PROCEDURE ); { int i = hb_comp_iExitLevel ; @@ -5292,6 +5335,7 @@ int hb_compAutoOpen( char * szPrg, BOOL * pbSkipGen ) } hb_xfree( hb_comp_pFileName ); + hb_comp_pFileName = pMainFileName; return iStatus; } diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index 4717f84aea..89203f43dc 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -1488,7 +1488,7 @@ Separator {SpaceTab} BEGIN 0; yyless( yyleng-4 ); if( hb_comp_iState == DO ) - { /* DO with */ + { /* DO with WITH */ hb_comp_iState =IDENTIFIER; yylval.string = hb_compIdentifierNew( "WITH", TRUE ); return IDENTIFIER; @@ -1499,6 +1499,21 @@ Separator {SpaceTab} return WITH; } } +"object" { + BEGIN 0; + if( hb_comp_iState == LOOKUP ) + { + hb_comp_iState = WITHOBJECT; + return WITHOBJECT; + } + else + { + yyless( yyleng-6 ); + hb_comp_iState =WITH; + return WITH; + } + + } [\)] { /* ( with ) or with() */ BEGIN 0; unput( yytext[ yyleng-1 ] ); diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index eebbf35864..3747e31747 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -101,6 +101,7 @@ static void hb_compSwitchStart( void ); static void hb_compSwitchAdd( HB_EXPR_PTR ); static void hb_compSwitchEnd( void ); +static HB_EXPR_PTR hb_compCheckPassByRef( HB_EXPR_PTR pExpr ); #ifdef HARBOUR_YYDEBUG #define YYDEBUG 1 /* Parser debug information support */ @@ -157,6 +158,7 @@ USHORT hb_comp_wIfCounter = 0; USHORT hb_comp_wWhileCounter = 0; USHORT hb_comp_wCaseCounter = 0; USHORT hb_comp_wSwitchCounter= 0; +USHORT hb_comp_wWithObjectCnt= 0; BOOL hb_comp_long_optimize = TRUE; BOOL hb_comp_bTextSubst = TRUE; @@ -167,6 +169,12 @@ static HB_RTVAR_PTR hb_comp_rtvars = NULL; static HB_SWITCHCMD_PTR hb_comp_pSwitch = NULL; static HB_ELSEIF_PTR hb_comp_elseif = NULL; +/* Controls if passing by reference '@' is allowed */ +#define HB_PASSBYREF_OFF 0 +#define HB_PASSBYREF_FUNCALL 1 +#define HB_PASSBYREF_ARRAY 2 +static int hb_comp_bPassByRef = HB_PASSBYREF_OFF; + char * hb_comp_szAnnounce = NULL; /* ANNOUNCEd procedure */ static void hb_compDebugStart( void ) { }; @@ -178,6 +186,7 @@ static void hb_compDebugStart( void ) { }; char * string; /* to hold a string returned by lex */ int iNumber; /* to hold a temporary integer number */ HB_LONG lNumber; /* to hold a temporary long number */ + BOOL bTrue; struct { int iNumber; /* to hold a number returned by lex */ @@ -217,10 +226,10 @@ static void hb_compDebugStart( void ) { }; %token MACROVAR MACROTEXT %token AS_ARRAY AS_BLOCK AS_CHARACTER AS_CLASS AS_DATE AS_LOGICAL AS_NUMERIC AS_OBJECT AS_VARIANT DECLARE OPTIONAL DECLARE_CLASS DECLARE_MEMBER %token AS_ARRAY_ARRAY AS_BLOCK_ARRAY AS_CHARACTER_ARRAY AS_CLASS_ARRAY AS_DATE_ARRAY AS_LOGICAL_ARRAY AS_NUMERIC_ARRAY AS_OBJECT_ARRAY -%token PROCREQ GET +%token PROCREQ %token CBSTART DOIDENT %token FOREACH DESCEND -%token DOSWITCH +%token DOSWITCH WITHOBJECT %token NUM_DATE /*the lowest precedence*/ @@ -262,7 +271,7 @@ static void hb_compDebugStart( void ) { }; %type Descend %type WhileBegin %type IfElseIf Cases -%type Argument ArgList ElemList BlockExpList BlockVarList BlockNoVar +%type ArgList ElemList BlockExpList BlockVarList BlockNoVar %type DoName DoProc DoArgument DoArgList %type PareExpList1 PareExpList2 PareExpList3 PareExpListN %type ExpList ExpList1 ExpList2 ExpList3 @@ -279,7 +288,7 @@ static void hb_compDebugStart( void ) { }; %type MacroExpr MacroExprAlias %type AliasId AliasVar AliasExpr %type VariableAt VariableAtAlias -%type FunCall FunCallAlias +%type FunIdentCall FunCall FunCallAlias %type ObjectData ObjectDataAlias %type ObjectMethod ObjectMethodAlias %type IfInline IfInlineAlias @@ -312,7 +321,6 @@ Source : Crlf | Statement | Line | ProcReq - | GET {/* Dummy - We need to use the GET token which is used by harbour.sly so both will generate same harboury.h */} | error Crlf { yyclearin; yyerrok; } | Source Crlf | Source VarDefs @@ -388,6 +396,7 @@ ParamList : IdentName AsType { hb_compVariableAdd( $1, hb_comp_c * stop compilation if invalid syntax will be used. */ Statement : ExecFlow { hb_comp_bDontGenLineNum = TRUE; } CrlfStmnt { } + | WithObject CrlfStmnt { } | IfInline CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } | FunCall CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } | AliasExpr CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } @@ -480,7 +489,6 @@ Statement : ExecFlow { hb_comp_bDontGenLineNum = TRUE; } CrlfStmnt { } else hb_compGenWarning( hb_comp_szWarnings, 'W', HB_COMP_WARN_DUPL_ANNOUNCE, $2, NULL ); } Crlf - ; CrlfStmnt : { hb_compLinePushIfInside(); } Crlf @@ -586,7 +594,7 @@ SelfAlias : SelfValue ALIASOP { $$ = $1; } /* Literal array */ -Array : '{' ElemList '}' { $$ = hb_compExprNewArray( $2 ); } +Array : '{' {$$=hb_comp_bPassByRef;hb_comp_bPassByRef=HB_PASSBYREF_ARRAY;} ElemList '}' { $$ = hb_compExprNewArray( $3 ); hb_comp_bPassByRef=$2; } ; ArrayAlias : Array ALIASOP { $$ = $1; } @@ -714,20 +722,16 @@ VariableAtAlias : VariableAt ALIASOP { $$ = $1; } /* Function call */ -FunCall : IdentName '(' ArgList ')' { $$ = hb_compExprNewFunCall( hb_compExprNewFunName( $1 ), $3 ); } - | MacroVar '(' ArgList ')' { $$ = hb_compExprNewFunCall( $1, $3 ); } - | MacroExpr '(' ArgList ')' { $$ = hb_compExprNewFunCall( $1, $3 ); } +FunIdentCall: IdentName '(' {$$=hb_comp_bPassByRef;hb_comp_bPassByRef=HB_PASSBYREF_FUNCALL;} ArgList ')' { $$ = hb_compExprNewFunCall( hb_compExprNewFunName( $1 ), $4 ); hb_comp_bPassByRef=$3; } + ; + +FunCall : FunIdentCall { $$ = $1; } + | MacroVar '(' {$$=hb_comp_bPassByRef;hb_comp_bPassByRef=HB_PASSBYREF_FUNCALL;} ArgList ')' { $$ = hb_compExprNewFunCall( $1, $4 ); hb_comp_bPassByRef=$3; } + | MacroExpr '(' {$$=hb_comp_bPassByRef;hb_comp_bPassByRef=HB_PASSBYREF_FUNCALL;} ArgList ')' { $$ = hb_compExprNewFunCall( $1, $4 ); hb_comp_bPassByRef=$3; } ; -ArgList : Argument { $$ = hb_compExprNewArgList( $1 ); } - | ArgList ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } - ; - -Argument : EmptyExpression { $$ = $1; } - | '@' IdentName { $$ = hb_compExprNewVarRef( $2 ); } - | '@' IdentName '(' ArgList ')' { $$ = hb_compExprNewFunRef( $2 ); hb_compExprDelete( $4 ); } - | '@' MacroVar { $$ = hb_compExprNewRef( $2 ); } - | '@' AliasVar { $$ = hb_compExprNewRef( $2 ); } +ArgList : EmptyExpression { $$ = hb_compExprNewArgList( $1 ); } + | ArgList ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } ; FunCallAlias : FunCall ALIASOP { $$ = $1; } @@ -759,6 +763,10 @@ ObjectData : NumValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } | VariableAt ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } | ObjectMethod ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } | ObjectData ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | ':' SendId { if( hb_comp_wWithObjectCnt == 0 ) + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_WITHOBJECT, NULL, NULL ); + $$ = hb_compExprNewSend( NULL, $2 ); + } ; ObjectDataAlias : ObjectData ALIASOP { $$ = $1; } @@ -766,12 +774,13 @@ ObjectDataAlias : ObjectData ALIASOP { $$ = $1; } /* Object's method */ -ObjectMethod : ObjectData '(' ArgList ')' { $$ = hb_compExprNewMethodCall( $1, $3 ); } +ObjectMethod : ObjectData '(' {$$=hb_comp_bPassByRef;hb_comp_bPassByRef=HB_PASSBYREF_FUNCALL;} ArgList ')' { $$ = hb_compExprNewMethodCall( $1, $4 ); hb_comp_bPassByRef=$3; } ; ObjectMethodAlias : ObjectMethod ALIASOP { $$ = $1; } ; + /* NOTE: We have to distinguish IdentName here because it is repeated * in DoArgument (a part of DO WITH .. statement) * where it generates different action. @@ -814,6 +823,10 @@ Expression : Variable { $$ = $1; } | PareExpList { $$ = $1; } | Variable { hb_comp_cVarType = ' ';} StrongType { $$ = $1; } | PareExpList { hb_comp_cVarType = ' ';} StrongType { $$ = $1; } + | '@' IdentName { $$ = hb_compCheckPassByRef( hb_compExprNewVarRef( $2 ) ); } + | '@' FunIdentCall { $$ = hb_compExprAsSymbol( $2 ); hb_compExprDelete( $2 ); $$ = hb_compCheckPassByRef( hb_compExprNewFunRef( $$ ) ); } + | '@' MacroVar { $$ = hb_compCheckPassByRef( hb_compExprNewRef( $2 ) ); } + | '@' AliasVar { $$ = hb_compCheckPassByRef( hb_compExprNewRef( $2 ) ); } ; EmptyExpression: /* nothing => nil */ { $$ = hb_compExprNewEmpty(); } @@ -1085,8 +1098,8 @@ IndexList : '[' Expression { $$ = hb_compExprNewArrayAt( $$ = hb_compExprNewCodeBlock($1.string,$1.isMacro,$1.lateEval); } BlockNoVar @@ -1139,23 +1152,23 @@ PareExpList : PareExpList1 { $$ = $1; } PareExpListAlias : PareExpList ALIASOP { $$ = $1; } ; -ExpList1 : '(' Argument { $$ = hb_compExprNewList( $2 ); } +ExpList1 : '(' EmptyExpression { $$ = hb_compExprNewList( $2 ); } ; -ExpList2 : ExpList1 ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } +ExpList2 : ExpList1 ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } ; -ExpList3 : ExpList2 ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } +ExpList3 : ExpList2 ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } ; -ExpList : ExpList3 ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } - | ExpList ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } +ExpList : ExpList3 ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } + | ExpList ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } ; IfInline : IIF PareExpList3 { $$ = hb_compExprNewIIF( $2 ); } - | IF ExpList1 ',' Argument ',' + | IF ExpList1 ',' EmptyExpression ',' { $$ = hb_compExprAddListExpr( $2, $4 ); } - Argument ')' + EmptyExpression ')' { $$ = hb_compExprNewIIF( hb_compExprAddListExpr( $6, $7 ) ); } ; @@ -1400,10 +1413,11 @@ DummyArgList : DummyArgument {} ; DummyArgument : EmptyExpression {} + ; +/* | '@' IdentName {} | '@' IdentName '(' DummyArgList ')' {} - ; - +*/ FormalList : IdentName AsType { hb_compDeclaredParameterAdd( $1, hb_comp_cVarType ); } | '@' IdentName AsType { hb_compDeclaredParameterAdd( $2, hb_comp_cVarType + VT_OFFSET_BYREF ); } | '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( $2, 'F' ); hb_compExprDelete( $4 );} @@ -1886,13 +1900,28 @@ DoArgList : ',' { $$ = hb_compExprAddListExpr( hb_compExp DoArgument : IdentName { $$ = hb_compExprNewVarRef( $1 ); } | '@' IdentName { $$ = hb_compExprNewVarRef( $2 ); } - | '@' IdentName '(' ArgList ')' { $$ = hb_compExprNewFunRef( $2 ); hb_compExprDelete( $4 ); } + | '@' FunIdentCall { $$ = $2; } | SimpleExpression { $$ = $1; } | PareExpList { $$ = $1; } | '@' MacroVar { $$ = hb_compExprNewRef( $2 ); } | '@' AliasVar { $$ = hb_compExprNewRef( $2 ); } ; +WithObject : WITHOBJECT Expression Crlf + { + hb_compExprDelete( hb_compExprGenPush( $2 ) ); + hb_compGenPCode1( HB_P_WITHOBJECTSTART ); + hb_comp_wWithObjectCnt++; + } + EmptyStatements + END + { + --hb_comp_wWithObjectCnt; + hb_compGenPCode1( HB_P_WITHOBJECTEND ); + } + | WITHOBJECT Expression Crlf END { hb_compExprDelete( $2 ); } + ; + Crlf : '\n' { hb_comp_bError = FALSE; } | ';' { hb_comp_bDontGenLineNum = TRUE; } ; @@ -2666,3 +2695,11 @@ void hb_compSwitchKill( ) } } +static HB_EXPR_PTR hb_compCheckPassByRef( HB_EXPR_PTR pExpr ) +{ + if( !( hb_comp_bPassByRef & (HB_PASSBYREF_FUNCALL | HB_PASSBYREF_ARRAY) ) ) + { + hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_INVALID_REFER, hb_compExprAsSymbol( pExpr ), NULL ); + } + return pExpr; +} diff --git a/harbour/source/compiler/hbdead.c b/harbour/source/compiler/hbdead.c index 6176bacde5..20bc868882 100644 --- a/harbour/source/compiler/hbdead.c +++ b/harbour/source/compiler/hbdead.c @@ -453,6 +453,9 @@ static PHB_CODETRACE_FUNC s_codeTraceFuncTable[ HB_P_LAST_PCODE ] = hb_p_default, /* HB_P_MINUSEQ */ hb_p_default, /* HB_P_MULTEQ */ hb_p_default, /* HB_P_DIVEQ */ + hb_p_default, /* HB_P_WITHOBJECTSTART */ + hb_p_default, /* HB_P_WITHOBJECTMESSAGE */ + hb_p_default /* HB_P_WITHOBJECTEND */ }; void hb_compCodeTraceMarkDead( PFUNCTION pFunc ) diff --git a/harbour/source/compiler/hbfix.c b/harbour/source/compiler/hbfix.c index 5c2f4550ce..8189f22a29 100644 --- a/harbour/source/compiler/hbfix.c +++ b/harbour/source/compiler/hbfix.c @@ -632,7 +632,10 @@ static HB_FIX_FUNC_PTR s_fixlocals_table[] = NULL, /* HB_P_PLUSEQ */ NULL, /* HB_P_MINUSEQ */ NULL, /* HB_P_MULTEQ */ - NULL /* HB_P_DIVEQ */ + NULL, /* HB_P_DIVEQ */ + NULL, /* HB_P_WITHOBJECTSTART */ + NULL, /* HB_P_WITHOBJECTMESSAGE */ + NULL /* HB_P_WITHOBJECTEND */ }; void hb_compFixFuncPCode( PFUNCTION pFunc ) diff --git a/harbour/source/compiler/hbfunchk.c b/harbour/source/compiler/hbfunchk.c index 5ad200831f..d455365839 100644 --- a/harbour/source/compiler/hbfunchk.c +++ b/harbour/source/compiler/hbfunchk.c @@ -115,7 +115,7 @@ static HB_FUNCINFO hb_StdFunc[] = { 0 , 0, 0 } }; -void hb_compFunCallCheck( char * szFuncCall, int iArgs ) +BOOL hb_compFunCallCheck( char * szFuncCall, int iArgs ) { HB_FUNCINFO * f = hb_StdFunc; int i = 0; @@ -152,12 +152,15 @@ void hb_compFunCallCheck( char * szFuncCall, int iArgs ) sprintf( szMsg, "\nPassed: %i, expected: %i - %i", iArgs, f[ iPos ].iMinParam, f[ iPos ].iMaxParam ); hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_CHECKING_ARGS, szFuncCall, szMsg ); + return FALSE; } else { /* Clipper way */ hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_CHECKING_ARGS, szFuncCall, NULL ); + return FALSE; } } } + return TRUE; } diff --git a/harbour/source/compiler/hbgenerr.c b/harbour/source/compiler/hbgenerr.c index 6293a851c0..97415b44ff 100644 --- a/harbour/source/compiler/hbgenerr.c +++ b/harbour/source/compiler/hbgenerr.c @@ -91,7 +91,8 @@ char * hb_comp_szErrors[] = "String too long for SWITCH", "Invalid date constant \'%s\'", "Memory buffer overflow", - "Memory corruption detected" + "Memory corruption detected", + "Implicit send operator with no WITH OBJECT in sight" }; /* Table with parse warnings */ diff --git a/harbour/source/compiler/hblbl.c b/harbour/source/compiler/hblbl.c index 752a2f33b8..2d90719fd0 100644 --- a/harbour/source/compiler/hblbl.c +++ b/harbour/source/compiler/hblbl.c @@ -175,6 +175,15 @@ static HB_LABEL_FUNC( hb_p_enumstart ) return 3; } +static HB_LABEL_FUNC( hb_p_withobjectstart ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + cargo->fWithObject = TRUE; + return 1; +} + /* NOTE: The order of functions have to match the order of opcodes * mnemonics */ @@ -326,6 +335,9 @@ static PHB_LABEL_FUNC s_GenLabelFuncTable[ HB_P_LAST_PCODE ] = NULL, /* HB_P_MINUSEQ */ NULL, /* HB_P_MULTEQ */ NULL, /* HB_P_DIVEQ */ + hb_p_withobjectstart, /* HB_P_WITHOBJECTSTART */ + NULL, /* HB_P_WITHOBJECTMESSAGE */ + NULL /* HB_P_WITHOBJECTEND */ }; void hb_compGenLabelTable( PFUNCTION pFunc, PHB_LABEL_INFO label_info ) diff --git a/harbour/source/compiler/hbpcode.c b/harbour/source/compiler/hbpcode.c index 6d9c32def5..d81896d2a6 100644 --- a/harbour/source/compiler/hbpcode.c +++ b/harbour/source/compiler/hbpcode.c @@ -249,7 +249,10 @@ const BYTE hb_comp_pcode_len[] = { 1, /* HB_P_PLUSEQ, */ 1, /* HB_P_MINUSEQ, */ 1, /* HB_P_MULTEQ, */ - 1 /* HB_P_DIVEQ, */ + 1, /* HB_P_DIVEQ, */ + 1, /* HB_P_WITHOBJECTSTART, */ + 3, /* HB_P_WITHOBJECTMESSAGE, */ + 1 /* HB_P-WITHOBJECTEND, */ }; /* @@ -403,7 +406,10 @@ static HB_PCODE_FUNC_PTR s_psize_table[] = NULL, /* HB_P_PLUSEQ */ NULL, /* HB_P_MINUSEQ */ NULL, /* HB_P_MULTEQ */ - NULL /* HB_P_DIVEQ */ + NULL, /* HB_P_DIVEQ */ + NULL, /* HB_P_WITHOBJECTSTART */ + NULL, /* HB_P_WITHOBJECTMESSAGE */ + NULL /* HB_P_WITHOBJECTEND */ }; LONG hb_compPCodeSize( PFUNCTION pFunc, ULONG ulOffset ) diff --git a/harbour/source/compiler/hbstripl.c b/harbour/source/compiler/hbstripl.c index 59c72ed9d6..b89d7367c2 100644 --- a/harbour/source/compiler/hbstripl.c +++ b/harbour/source/compiler/hbstripl.c @@ -221,7 +221,10 @@ static PHB_STRIP_FUNC s_stripLines_table[] = NULL, /* HB_P_PLUSEQ */ NULL, /* HB_P_MINUSEQ */ NULL, /* HB_P_MULTEQ */ - NULL /* HB_P_DIVEQ */ + NULL, /* HB_P_DIVEQ */ + NULL, /* HB_P_WITHOBJECTSTART */ + NULL, /* HB_P_WITHOBJECTMESSAGE */ + NULL /* HB_P_WITHOBJECTEND */ }; void hb_compStripFuncLines( PFUNCTION pFunc ) diff --git a/harbour/source/macro/macroa.c b/harbour/source/macro/macroa.c index c3bb635839..6dfa8f10c9 100644 --- a/harbour/source/macro/macroa.c +++ b/harbour/source/macro/macroa.c @@ -5,7 +5,7 @@ /* hbexpra.c is also included from ../compiler/expropta.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.19 - ignore this magic number - this is used to force compilation + * 1.20 - ignore this magic number - this is used to force compilation */ #define HB_MACRO_SUPPORT diff --git a/harbour/source/macro/macrob.c b/harbour/source/macro/macrob.c index 8c4257b195..94d1c609b8 100644 --- a/harbour/source/macro/macrob.c +++ b/harbour/source/macro/macrob.c @@ -5,7 +5,7 @@ /* hbexprb.c is also included from ../compiler/exproptb.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.16 - ignore this magic number - this is used to force compilation + * 1.17 - ignore this magic number - this is used to force compilation */ #define HB_MACRO_SUPPORT diff --git a/harbour/source/macro/macroc.c b/harbour/source/macro/macroc.c index 02d07efc35..5262cff19c 100644 --- a/harbour/source/macro/macroc.c +++ b/harbour/source/macro/macroc.c @@ -5,7 +5,7 @@ /* hbexprc.c is also included from ../compiler/exproptc.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.8 - ignore this magic number - this is used to force compilation + * 1.9 - ignore this magic number - this is used to force compilation */ #define HB_MACRO_SUPPORT diff --git a/harbour/source/pp/ppcomp.c b/harbour/source/pp/ppcomp.c index 1064778cb4..022c900614 100644 --- a/harbour/source/pp/ppcomp.c +++ b/harbour/source/pp/ppcomp.c @@ -362,7 +362,7 @@ static void pp_ParseBuffer( PFILE pFile, int *plLine ) *s_szLine = '\0'; else { - hb_pp_ParseExpression( ptr, s_szOutLine ); + hb_pp_ParseExpression( ptr, s_szOutLine, TRUE ); } } else @@ -378,7 +378,7 @@ static void pp_ParseBuffer( PFILE pFile, int *plLine ) { if( hb_pp_nCondCompile == 0 || hb_pp_aCondCompile[ hb_pp_nCondCompile - 1 ] ) { - hb_pp_ParseExpression( ptr, s_szOutLine ); + hb_pp_ParseExpression( ptr, s_szOutLine, TRUE ); HB_SKIPTABSPACES( ptr ); bCont = ( *ptr == '#' ); diff --git a/harbour/source/pp/ppcore.c b/harbour/source/pp/ppcore.c index f4438b82cd..5efaf05f8a 100644 --- a/harbour/source/pp/ppcore.c +++ b/harbour/source/pp/ppcore.c @@ -106,7 +106,7 @@ static int WorkTranslate( char *, char *, COMMANDS *, int * ); static int CommandStuff( char *, char *, char *, int *, BOOL, BOOL ); static int RemoveSlash( char * ); static int WorkMarkers( char **, char **, char *, int *, BOOL, BOOL ); -static int getExpReal( char *, char **, BOOL, int, BOOL ); +static int getExpReal( char *, char **, BOOL, int, BOOL, BOOL ); static BOOL isExpres( char *, BOOL ); static BOOL TestOptional( char *, char * ); static BOOL CheckOptional( char *, char *, char *, int *, BOOL, BOOL ); @@ -720,8 +720,13 @@ int hb_pp_ParseDefine( char *sLine ) } lastdef = hb_pp_AddDefine( defname, ( *sLine == '\0' ) ? NULL : sLine ); - lastdef->npars = npars; - lastdef->pars = cParams; + if( lastdef ) + { + lastdef->npars = npars; + lastdef->pars = cParams; + } + else if( cParams ) + hb_xfree( cParams ); } else hb_compGenError( hb_pp_szErrors, 'F', HB_PP_ERR_DEFINE_ABSENT, NULL, NULL ); @@ -750,6 +755,8 @@ DEFINES *hb_pp_AddDefine( char *defname, char *value ) if( stdef->value ) hb_xfree( stdef->value ); } + else + return NULL; } else { @@ -1411,7 +1418,7 @@ static COMMANDS *AddTranslate( char *traname ) return sttra; } -int hb_pp_ParseExpression( char *sLine, char *sOutLine ) +int hb_pp_ParseExpression( char *sLine, char *sOutLine, BOOL bSplitLines ) { #if !defined(HB_PP_DEBUG_MEMORY) static char rpatt[PATTERN_SIZE]; @@ -1442,7 +1449,10 @@ int hb_pp_ParseExpression( char *sLine, char *sOutLine ) { ptro = sOutLine; ptri = sLine + isdvig; - ipos = md_strAt( ";", 1, ptri, TRUE, FALSE, FALSE, MD_STR_AT_IGNORECASE ); + if( bSplitLines ) + ipos = md_strAt( ";", 1, ptri, TRUE, FALSE, FALSE, MD_STR_AT_IGNORECASE ); + else + ipos = 0; if( ipos > 0 ) { @@ -1886,6 +1896,7 @@ static int CommandStuff( char *ptrmp, char *inputLine, char *ptro, int *lenres, char *ptri = inputLine, *ptr, tmpname[MAX_NAME]; int isWordInside = 0; char szMatch[2]; + char *ptrmpatt = ptrmp; /* printf( "MP: >%s<\nIn: >%s<\n", ptrmp, ptri ); @@ -1907,17 +1918,23 @@ static int CommandStuff( char *ptrmp, char *inputLine, char *ptro, int *lenres, HB_SKIPTABSPACES( ptrmp ); if( *ptrmp == HB_PP_OPT_START && !s_numBrackets && !strtopti ) { + /* Store start position of outermost optional in pattern */ strtopti = ptrmp; } - if( !s_numBrackets && strtopti && strtptri != ptri && ( ISNAME( ( BYTE ) * ptri ) || *ptri == '&' ) ) + if( !s_numBrackets && strtopti && strtptri != ptri && + ( ISNAME( ( BYTE ) * ptri ) || *ptri == '&' ) ) { + /* Input stream starts with a word or macro -store the position + * which matches the outermost optional in pattern + */ strtptri = ptri; ptrmp = strtopti; ptr = ptri; - ipos = NextName( &ptr, tmpname ); + ipos = NextName( &ptr, tmpname ); /* get starting keyword */ ipos = md_strAt( tmpname, ipos, strtopti, TRUE, TRUE, TRUE, MD_STR_AT_USESUBCASE ); if( ipos && TestOptional( strtopti, strtopti + ipos - 2 ) ) { + /* the keyword from input is found in the pattern */ ptr = strtopti + ipos - 2; ptr = PrevSquare( ptr, strtopti, NULL ); if( ptr ) @@ -1936,7 +1953,17 @@ static int CommandStuff( char *ptrmp, char *inputLine, char *ptro, int *lenres, ptrmp++; if( !CheckOptional( ptrmp, ptri, ptro, lenres, com_or_tra, com_or_xcom ) ) { + char *ptr = ptrmp; SkipOptional( &ptrmp ); + if( !ptrmp[0] && *ptri && ptr != ptrmpatt+1 && ptri != inputLine ) + { + /* Start scanning from the beginning + * end of pattern but still there is an input stream to parse + * + */ + ptrmp = ptrmpatt; + strtopti = NULL; + } } break; @@ -1979,9 +2006,18 @@ static int CommandStuff( char *ptrmp, char *inputLine, char *ptro, int *lenres, } else { + char *ptr = ptrmp; if( !isWordInside ) strtopti = NULL; ptrmp++; + if( !ptrmp[0] && *ptri && ptr != ptrmpatt+1 && ptri != inputLine ) + { + /* Start scanning from the beginning + * end of pattern but still there is an input stream to parse + */ + ptrmp = ptrmpatt; + strtopti = NULL; + } } s_numBrackets--; } @@ -2287,7 +2323,7 @@ static int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres, BOOL if( *( exppatt + 2 ) == '4' ) /* ---- extended match marker */ { if( !lenreal ) - lenreal = getExpReal( s_expreal, ptri, FALSE, maxlenreal, FALSE ); + lenreal = getExpReal( s_expreal, ptri, FALSE, maxlenreal, FALSE, FALSE ); { SearnRep( exppatt, s_expreal, lenreal, ptro, lenres ); } @@ -2331,24 +2367,19 @@ static int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres, BOOL */ if( **ptri == '&' ) { + char * ptrmacro = *ptri; /* save current position */ + *ptri += 1; HB_SKIPTABSPACES( *ptri ); if( **ptri == '(' ) /* macro expression &( expr ) */ { -/* Commented out this line to avoid a compiler warning. Please review. [vszakats] */ -/* lenreal = IsMacroVar( *ptri, com_or_tra ); */ - *ptri += 1; - lenreal = getExpReal( s_expreal + 2, ptri, FALSE, maxlenreal, FALSE ); - if( **ptri == ')' ) - { - *ptri += 1; - } + lenreal = getExpReal( s_expreal + 2, ptri, TRUE, maxlenreal, FALSE, TRUE ); if( !( **ptri == '\0' || **ptri == ' ' ) && com_or_tra ) break; s_expreal[0] = '&'; s_expreal[1] = '('; - lenreal += 3; - s_expreal[lenreal - 1] = ')'; + lenreal +=3; + s_expreal[lenreal-1] = ')'; SearnRep( exppatt, s_expreal, lenreal, ptro, lenres ); rezrestr = 1; } @@ -2357,19 +2388,63 @@ static int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres, BOOL lenreal = IsMacroVar( *ptri, com_or_tra ); if( lenreal > 0 ) { - strncpy( s_expreal + 1, *ptri, lenreal ); - s_expreal[0] = '&'; - s_expreal[lenreal + 1] = '\0'; - *ptri += lenreal; - SearnRep( exppatt, s_expreal, lenreal + 1, ptro, lenres ); - rezrestr = 1; - break; + if( ! com_or_tra ) + { + /* translate */ + strncpy( s_expreal + 1, *ptri, lenreal ); + s_expreal[0] = '&'; + s_expreal[lenreal + 1] = '\0'; + *ptri += lenreal; + SearnRep( exppatt, s_expreal, lenreal + 1, ptro, lenres ); + rezrestr = 1; + break; + } + else + { + char * ptmp = *ptri + lenreal; + HB_SKIPTABSPACES( ptmp ); + if( ! IsInStr( *ptmp, ":/+*-%^=<>[{.," ) || + (*ptmp && ptmp[0]=='+' && ptmp[1]=='+') || + (*ptmp && ptmp[0]=='-' && ptmp[1]=='-') ) + { + /* NOTE: + * Clipper usually bounds to left the '++' and '--' + * operators which means that the following code: + * #command XCALL => ( ) + * XCALL &a ++b + * is preprocessed into: + * &a( ++b ) + * However if used with restricted macro match marker: + * #command MCALL => ( ) + * then + * MCALL &a ++b + * is preprocessed into: + * &a ++( b ) + */ + strncpy( s_expreal + 1, *ptri, lenreal ); + s_expreal[0] = '&'; + s_expreal[lenreal + 1] = '\0'; + *ptri += lenreal; + SearnRep( exppatt, s_expreal, lenreal + 1, ptro, lenres ); + rezrestr = 1; + break; + } + else + { +#if defined(HB_PP_DEBUG_MEMORY) + hb_xfree( ( void * ) exppatt ); +#endif + *ptri = ptrmacro; /* restore '&' char */ + return 0; + } + } } else { #if defined(HB_PP_DEBUG_MEMORY) hb_xfree( ( void * ) exppatt ); #endif + *ptri -= 1; /* restore '&' char */ return 0; } } @@ -2409,17 +2484,6 @@ static int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres, BOOL if( rezrestr == 0 ) { /* If restricted match marker doesn't correspond to real parameter */ - /* rglab: Thu Sep 2 21:27:29 2004 - I don't know why 'if' code - was below, anyway it is the same as the new line - if( s_numBrackets ) - { - return 0; - } - else - { - return 0; - } - */ #if defined(HB_PP_DEBUG_MEMORY) hb_xfree( ( void * ) exppatt ); #endif @@ -2430,7 +2494,7 @@ static int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres, BOOL { if( !lenreal ) { - lenreal = getExpReal( s_expreal, ptri, TRUE, maxlenreal, FALSE ); + lenreal = getExpReal( s_expreal, ptri, TRUE, maxlenreal, FALSE, FALSE ); } if( lenreal ) @@ -2450,7 +2514,7 @@ static int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres, BOOL /* Copying a real expression to 's_expreal' */ if( !lenreal ) { - lenreal = getExpReal( s_expreal, ptri, FALSE, maxlenreal, FALSE ); + lenreal = getExpReal( s_expreal, ptri, FALSE, maxlenreal, FALSE, FALSE ); } /* @@ -2476,7 +2540,7 @@ static int WorkMarkers( char **ptrmp, char **ptri, char *ptro, int *lenres, BOOL return 1; } -static int getExpReal( char *expreal, char **ptri, BOOL prlist, int maxrez, BOOL bStrict ) +static int getExpReal( char *expreal, char **ptri, BOOL prlist, int maxrez, BOOL bStrict, BOOL bInBrackets ) { int lens = 0; char *sZnaki = "+-=><*/$.:#%!^"; @@ -2484,16 +2548,24 @@ static int getExpReal( char *expreal, char **ptri, BOOL prlist, int maxrez, BOOL int StBr1 = 0, StBr2 = 0, StBr3 = 0; BOOL rez = FALSE; BOOL bMacro = FALSE; + BOOL bBrackets = FALSE; char *cStart = expreal; char cLastSep = '\0'; char cLastChar = '\0'; - HB_TRACE( HB_TR_DEBUG, ( "getExpReal(%s, %p, %d, %d, %d)", expreal, ptri, prlist, maxrez, bStrict ) ); + HB_TRACE( HB_TR_DEBUG, ( "getExpReal(%s, %p, %d, %d, %d, %d)", expreal, ptri, prlist, maxrez, bStrict, bInBrackets ) ); HB_SKIPTABSPACES( *ptri ); + if( **ptri == '(' && bInBrackets ) + { + /* scan expression including start and end brackets */ + bBrackets = TRUE; + ( * ptri )++; + prlist = TRUE; + } State = ( **ptri == '\'' || **ptri == '\"' || **ptri == '[' ) ? STATE_EXPRES : STATE_ID; - + while( **ptri != '\0' && !rez && lens < maxrez ) { if( State == STATE_EXPRES || ( cLastChar && strchr( "({[.|,$!#=<>^%*/+-", cLastChar ) ) ) @@ -2685,7 +2757,7 @@ static int getExpReal( char *expreal, char **ptri, BOOL prlist, int maxrez, BOOL StBr1--; if( StBr1 == 0 && StBr2 == 0 && StBr3 == 0 ) { - State = STATE_ID_END; + State = STATE_ID_END; } } else if( **ptri == ']' ) @@ -2730,6 +2802,46 @@ static int getExpReal( char *expreal, char **ptri, BOOL prlist, int maxrez, BOOL rez = TRUE; } } + else if( ( **ptri == '+' && *( *ptri + 1 ) == '+' ) || ( **ptri == '-' && *( *ptri + 1 ) == '-' ) ) + { + cLastChar = **ptri; + + if( expreal ) + { + *expreal++ = **ptri; + } + (*ptri)++; + lens++; + + if( expreal ) + { + *expreal++ = **ptri; + } + (*ptri)++; + lens++; + + if( State == STATE_ID ) + { + // Prefix ONLY when lens == 0 (2) oterwise MUST be a postfix. + if( lens == 2 ) + { + while( **ptri == ' ' && lens < maxrez ) + { + if( expreal ) + { + *expreal++ = **ptri; + } + (*ptri)++; + lens++; + } + } + else + { + State = ( StBr1 == 0 && StBr2 == 0 && StBr3 == 0 )? STATE_ID_END: STATE_BRACKET; + } + } + continue; + } else if( IsInStr( **ptri, sZnaki ) ) { cLastSep = ','; @@ -2789,6 +2901,10 @@ static int getExpReal( char *expreal, char **ptri, BOOL prlist, int maxrez, BOOL } else if( **ptri == ')' && StBr1 == 0 ) { + if( bBrackets ) + { + ( *ptri )++; + } rez = TRUE; } else if( **ptri == ']' && StBr2 == 0 ) @@ -2955,7 +3071,7 @@ static BOOL isExpres( char *stroka, BOOL prlist ) #endif l1 = strlen( stroka ); - l2 = getExpReal( NULL, &stroka, prlist, HB_PP_STR_SIZE, TRUE ); + l2 = getExpReal( NULL, &stroka, prlist, HB_PP_STR_SIZE, TRUE, FALSE ); #if 0 printf( "Len1: %i Len2: %i RealExp: >%s< Last: %c\n", l1, l2, stroka - l2, ( stroka - l2 )[l1 - 1] ); @@ -3276,17 +3392,42 @@ static void SearnRep( char *exppatt, char *expreal, int lenreal, char *ptro, int { if( *( ptrOut + ifou + 2 ) != '0' && *( exppatt + 1 ) ) { - if( lastchar == '0' ) - lastchar = *( ptrOut + ifou + 2 ); - if( lastchar != *( ptrOut + ifou + 2 ) ) + isdvig = ptrOut - ptro + ifou; + do { - isdvig += ifou + 3; + if( lastchar == '0' ) + lastchar = *( ptrOut + ifou + 2 ); + if( lastchar != *( ptrOut + ifou + 2 ) ) + { + ifou +=3; + ptrOut = ptrOut + ifou; + continue; + } + + *lenres += ReplacePattern( exppatt[2], expreal, lenreal, ptrOut + ifou - 1, *lenres - ifou + 1 ); + ptrOut = ptrOut + ifou; + } + while( ( ifou = md_strAt( exppatt, ( *( exppatt + 1 ) ) ? 2 : 1, ptrOut, FALSE, FALSE, TRUE, MD_STR_AT_USESUBCASE ) ) > 0 ); + if( ! s_Repeate ) + { + lastchar++; ptrOut = ptro + isdvig; + isdvig = 0; continue; } + return; + } + else if( lastchar == '0' ) + { + *lenres += ReplacePattern( exppatt[2], expreal, lenreal, ptrOut + ifou - 1, *lenres - isdvig - ifou + 1 ); + isdvig += ifou - 1; + + } + else + { + ptrOut += ifou + 1; + continue; } - *lenres += ReplacePattern( exppatt[2], expreal, lenreal, ptrOut + ifou - 1, *lenres - isdvig - ifou + 1 ); - isdvig += ifou - 1; } else if( !s_bReplacePat ) isdvig += ifou; @@ -3326,7 +3467,11 @@ static BOOL ScanMacro( char *expreal, int lenitem, int *pNewLen ) { i++; } - if( expreal[i] == '\0' || expreal[i] == ',' || expreal[i] == ')' || expreal[i] == ' ' ) + while( expreal[i] == ' ' || expreal[i] == '\t' ) + { + i++; + } + if( expreal[i] == '\0' || expreal[i] == ',' || expreal[i] == ')' ) /* || expreal[i] == ' ' )*/ { return TRUE; } @@ -4120,18 +4265,21 @@ static int stroncpy( char *ptro, char *ptri, int lens ) static BOOL truncmp( char **ptro, char **ptri, BOOL lTrunc ) { char *ptrb = *ptro, co, ci; - + HB_TRACE( HB_TR_DEBUG, ( "truncmp(%p, %p, %d)", ptro, ptri, lTrunc ) ); + for( ; **ptri != ' ' && **ptri != '\t' && **ptri != ',' && **ptri != HB_PP_OPT_START && **ptri != HB_PP_OPT_END && **ptri != HB_PP_MATCH_MARK && **ptri != '\0' && toupper( **ptri ) == toupper( **ptro ); ( *ptro )++, ( *ptri )++ ) ; co = *( *ptro - 1 ); ci = **ptri; + if( ( ( ci == ' ' || ci == ',' || ci == HB_PP_OPT_START || ci == HB_PP_OPT_END || ci == HB_PP_MATCH_MARK || ci == '\0' ) && - ( ( !ISNAME( ( BYTE ) ** ptro ) && ISNAME( ( BYTE ) co ) ) || ( !ISNAME( ( BYTE ) co ) ) ) ) ) + ( ( !ISNAME( ( BYTE ) ** ptro ) && ISNAME( ( BYTE ) co ) ) || + ( !ISNAME( ( BYTE ) co ) ) ) ) ) return FALSE; else if( lTrunc && *ptro - ptrb >= 4 && ISNAME( ( BYTE ) ci ) && !ISNAME( ( BYTE ) ** ptro ) && ISNAME( ( BYTE ) co ) ) { diff --git a/harbour/source/pp/pplib.c b/harbour/source/pp/pplib.c index a0e3c061db..88ea0a65d3 100644 --- a/harbour/source/pp/pplib.c +++ b/harbour/source/pp/pplib.c @@ -193,7 +193,7 @@ HB_FUNC( __PREPROCESS ) if( !hb_pp_topDefine ) hb_pp_Table(); - if( hb_pp_ParseExpression( ptr, pOut ) > 0 ) + if( hb_pp_ParseExpression( ptr, pOut, FALSE ) > 0 ) { /* Some error here? */ } diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 4a76f4b629..5a8fc27413 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -224,6 +224,8 @@ HB_SYMB hb_symEval = { "__EVAL", {HB_FS_PUBLIC}, {hb_vmDoBlock}, NUL HB_SYMB hb_symEnumIndex = { "__ENUMINDEX", {HB_FS_MESSAGE}, {NULL}, NULL }; HB_SYMB hb_symEnumBase = { "__ENUMBASE", {HB_FS_MESSAGE}, {NULL}, NULL }; HB_SYMB hb_symEnumValue = { "__ENUMVALUE", {HB_FS_MESSAGE}, {NULL}, NULL }; +HB_SYMB hb_symWithObjectPush = { "__WITHOBJECT", {HB_FS_MESSAGE}, {NULL}, NULL }; +HB_SYMB hb_symWithObjectPop = { "___WITHOBJECT", {HB_FS_MESSAGE}, {NULL}, NULL }; static HB_ITEM s_aStatics; /* Harbour array to hold all application statics variables */ @@ -261,8 +263,9 @@ static LONG s_lRecoverBase; #define HB_RECOVER_ADDRESS -3 #define HB_RECOVER_VALUE -4 -/* Stores the position on the stack of current FOR EACh envelope -*/ +/* Stores the position on the stack of current WITH OBJECT envelope */ +static LONG s_lWithObjectBase = 0; + /* Stores level of procedures call stack */ static ULONG s_ulProcLevel = 0; @@ -413,6 +416,8 @@ HB_EXPORT void hb_vmInit( BOOL bStartMainProc ) hb_dynsymNew( &hb_symEnumIndex ); hb_dynsymNew( &hb_symEnumBase ); hb_dynsymNew( &hb_symEnumValue ); + hb_dynsymNew( &hb_symWithObjectPush ); + hb_dynsymNew( &hb_symWithObjectPop ); hb_setInitialize(); /* initialize Sets */ hb_conInit(); /* initialize Console */ @@ -593,6 +598,7 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) LONG lForEachBase = 0; /* Stores the position on the stack of current FOR EACH envelope */ ULONG ulPrivateBase; BOOL bDynCode = pSymbols == NULL || ( pSymbols->scope.value & HB_FS_DYNCODE ) != 0; + LONG lWithObjectBase = s_lWithObjectBase; #ifndef HB_NO_PROFILER ULONG ulLastOpcode = 0; /* opcodes profiler support */ ULONG ulPastClock = 0; /* opcodes profiler support */ @@ -1837,6 +1843,33 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) break; } + /* WITH OBJECT */ + + case HB_P_WITHOBJECTMESSAGE: + hb_vmPushSymbol( pSymbols + HB_PCODE_MKUSHORT( &( pCode[ w + 1 ] ) ) ); + hb_vmPush( hb_stackItem( s_lWithObjectBase ) ); + w += 3; + break; + + case HB_P_WITHOBJECTSTART: + { + /* The object is pushed directly before this pcode */ + /* store position of current WITH OBJECT frame */ + HB_ITEM_PTR pItem = hb_stackAllocItem(); + pItem->type = HB_IT_LONG; + pItem->item.asLong.value = s_lWithObjectBase; + s_lWithObjectBase = hb_stackTopOffset() - 2; + w += 1; + } + break; + + case HB_P_WITHOBJECTEND: + s_lWithObjectBase = ( hb_stackItemFromTop( -1 ) )->item.asLong.value; + hb_stackDec(); + hb_stackPop(); /* remove implicit object */ + w += 1; + break; + /* misc */ case HB_P_NOOP: @@ -1865,16 +1898,28 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) if( bCanRecover ) { /* - * There is the BEGIN/END sequence deifined in current + * There is the BEGIN/END sequence defined in current * procedure/function - use it to continue opcodes execution */ - while( lForEachBase > s_lRecoverBase ) + while( lForEachBase > s_lRecoverBase || s_lWithObjectBase >= s_lRecoverBase ) { - /* remove FOR EACH stack frame so there is no orphan - * item pointers hanging - */ - hb_stackRemove( lForEachBase ); - lForEachBase = hb_vmEnumEnd(); + if( lForEachBase > s_lWithObjectBase ) + { + /* remove FOR EACH stack frame so there is no orphan + * item pointers hanging + */ + hb_stackRemove( lForEachBase ); + lForEachBase = hb_vmEnumEnd(); + } + else if( lForEachBase < s_lWithObjectBase ) + { + /* BREAK was issued inside the WITH OBJECT + * restore previous frame + */ + hb_stackRemove( s_lWithObjectBase + 2 ); + s_lWithObjectBase = ( hb_stackItemFromTop( -1 ) )->item.asLong.value; + hb_stackDec(); + } } /* @@ -1910,6 +1955,11 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) if( pSymbols ) hb_memvarSetPrivatesBase( ulPrivateBase ); + + /* Restore previous WITH OBJECT frame if the RETURN statement + * was placed inside WITH OBJECT/END + */ + s_lWithObjectBase = lWithObjectBase; } /* ------------------------------- */ @@ -4009,38 +4059,52 @@ HB_EXPORT void hb_vmSend( USHORT uiParams ) if( bNotHandled ) { - PHB_SYMB pExecSym; - BOOL lPopSuper; - - pExecSym = hb_objGetMethod( pSelf, pSym, &lPopSuper ); - if( pExecSym && pExecSym->value.pFunPtr ) + if( pSym->pDynSym == hb_symWithObjectPush.pDynSym && s_lWithObjectBase ) { -#ifndef HB_NO_PROFILER - if( bProfiler ) - pMethod = hb_mthRequested(); -#endif - if( hb_bTracePrgCalls ) - HB_TRACE(HB_TR_ALWAYS, ("Calling: %s:%s", hb_objGetClsName( pSelf ), pSym->szName)); - - if( pExecSym->scope.value & HB_FS_PCODEFUNC ) - /* Running pCode dynamic function from .HRB */ - hb_vmExecute( pExecSym->value.pCodeFunc->pCode, - pExecSym->value.pCodeFunc->pSymbols ); - else - pExecSym->value.pFunPtr(); - -#ifndef HB_NO_PROFILER - if( bProfiler ) - hb_mthAddTime( pMethod, clock() - ulClock ); -#endif + /* push current WITH OBJECT object */ + hb_itemCopy( &hb_stack.Return, hb_stackItem( s_lWithObjectBase ) ); + } + else if( pSym->pDynSym == hb_symWithObjectPop.pDynSym && s_lWithObjectBase ) + { + /* replace current WITH OBJECT object */ + hb_itemCopy( hb_stackItem( s_lWithObjectBase ), hb_stackItemFromBase( 1 ) ); + hb_itemCopy( &hb_stack.Return, hb_stackItem( s_lWithObjectBase ) ); } - else if( pSym->szName[ 0 ] == '_' ) - hb_errRT_BASE_SubstR( EG_NOVARMETHOD, 1005, NULL, pSym->szName + 1, HB_ERR_ARGS_SELFPARAMS ); else - hb_errRT_BASE_SubstR( EG_NOMETHOD, 1004, NULL, pSym->szName, HB_ERR_ARGS_SELFPARAMS ); + { + PHB_SYMB pExecSym; + BOOL lPopSuper; - if( lPopSuper ) - hb_objPopSuperCast( pSelf ); + pExecSym = hb_objGetMethod( pSelf, pSym, &lPopSuper ); + if( pExecSym && pExecSym->value.pFunPtr ) + { +#ifndef HB_NO_PROFILER + if( bProfiler ) + pMethod = hb_mthRequested(); +#endif + if( hb_bTracePrgCalls ) + HB_TRACE(HB_TR_ALWAYS, ("Calling: %s:%s", hb_objGetClsName( pSelf ), pSym->szName)); + + if( pExecSym->scope.value & HB_FS_PCODEFUNC ) + /* Running pCode dynamic function from .HRB */ + hb_vmExecute( pExecSym->value.pCodeFunc->pCode, + pExecSym->value.pCodeFunc->pSymbols ); + else + pExecSym->value.pFunPtr(); + +#ifndef HB_NO_PROFILER + if( bProfiler ) + hb_mthAddTime( pMethod, clock() - ulClock ); +#endif + } + else if( pSym->szName[ 0 ] == '_' ) + hb_errRT_BASE_SubstR( EG_NOVARMETHOD, 1005, NULL, pSym->szName + 1, HB_ERR_ARGS_SELFPARAMS ); + else + hb_errRT_BASE_SubstR( EG_NOMETHOD, 1004, NULL, pSym->szName, HB_ERR_ARGS_SELFPARAMS ); + + if( lPopSuper ) + hb_objPopSuperCast( pSelf ); + } } if( s_bDebugging ) @@ -5982,13 +6046,25 @@ HB_EXPORT BOOL hb_xvmSeqEnd( LONG * plForEachBase ) { if( plForEachBase ) { - while( *plForEachBase > s_lRecoverBase ) + while( *plForEachBase > s_lRecoverBase || s_lWithObjectBase >= s_lRecoverBase ) { - /* remove FOR EACH stack frame so there is no orphan - * item pointers hanging - */ - hb_stackRemove( *plForEachBase ); - *plForEachBase = hb_vmEnumEnd(); + if( *plForEachBase > s_lWithObjectBase ) + { + /* remove FOR EACH stack frame so there is no orphan + * item pointers hanging + */ + hb_stackRemove( *plForEachBase ); + *plForEachBase = hb_vmEnumEnd(); + } + else if( *plForEachBase < s_lWithObjectBase ) + { + /* BREAK was issued inside the WITH OBJECT + * restore previous frame + */ + hb_stackRemove( s_lWithObjectBase + 1 ); + s_lWithObjectBase = ( hb_stackItemFromTop(-1) )->item.asLong.value; + hb_stackDec(); + } } } /* @@ -7786,6 +7862,35 @@ HB_EXPORT BOOL hb_xvmMacroText( void ) HB_XVM_RETURN } +HB_EXPORT void hb_xvmWithObjectStart( void ) +{ + HB_ITEM_PTR pItem; + + HB_TRACE(HB_TR_DEBUG, ("hb_xvmWithObjectStart()")); + + /* The object is pushed directly before this pcode */ + /* store position of current WITH OBJECT frame */ + pItem = hb_stackAllocItem(); + pItem->type = HB_IT_LONG; + pItem->item.asLong.value = s_lWithObjectBase; + s_lWithObjectBase = hb_stackTopOffset() - 2; +} + +HB_EXPORT void hb_xvmWithObjectEnd( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_xvmWithObjectEnd()")); + + s_lWithObjectBase = ( hb_stackItemFromTop( -1 ) )->item.asLong.value; + hb_stackDec(); + hb_stackPop(); /* remove implicit object */ +} + +HB_EXPORT LONG hb_xvmWithObjectBase( LONG * plWithObjectBase ) +{ + if( plWithObjectBase ) + s_lWithObjectBase = *plWithObjectBase; + return s_lWithObjectBase; +} /* ------------------------------------------------------------------------ */ /* The debugger support functions */ /* ------------------------------------------------------------------------ */ diff --git a/harbour/source/vm/macro.c b/harbour/source/vm/macro.c index d6601eecf3..20c9ca1035 100644 --- a/harbour/source/vm/macro.c +++ b/harbour/source/vm/macro.c @@ -1294,7 +1294,7 @@ void hb_compGenPushDate( HB_LONG lNumber, HB_MACRO_DECL ) } /* sends a message to an object */ -void hb_compGenMessage( char * szMsgName, HB_MACRO_DECL ) +void hb_compGenMessage( char * szMsgName, BOOL bIsObject, HB_MACRO_DECL ) { /* Find the address of passed symbol - create the symbol if doesn't exist */ @@ -1307,11 +1307,12 @@ void hb_compGenMessage( char * szMsgName, HB_MACRO_DECL ) HB_PUT_PTR( byBuf, pSym ); hb_compGenPCodeN( byBuf, sizeof( pSym ), HB_MACRO_PARAM ); } + HB_SYMBOL_UNUSED( bIsObject ); /* used in full compiler only */ /* hb_compGenPCodeN( ( BYTE * ) &pSym, sizeof( pSym ), HB_MACRO_PARAM ); */ } /* generates an underscore-symbol name for a data assignment */ -void hb_compGenMessageData( char * szMsg, HB_MACRO_DECL ) +void hb_compGenMessageData( char * szMsg, BOOL bIsObject, HB_MACRO_DECL ) { char * szResult; @@ -1322,7 +1323,7 @@ void hb_compGenMessageData( char * szMsg, HB_MACRO_DECL ) strcpy( szResult, "_" ); strcat( szResult, szMsg ); - hb_compGenMessage( szResult, HB_MACRO_PARAM ); + hb_compGenMessage( szResult, bIsObject, HB_MACRO_PARAM ); hb_xfree( szResult ); } diff --git a/harbour/tests/Makefile b/harbour/tests/Makefile index 75f74a0385..c015d0444f 100644 --- a/harbour/tests/Makefile +++ b/harbour/tests/Makefile @@ -97,7 +97,6 @@ PRG_SOURCES=\ overload.prg \ parexpr.prg \ passref.prg \ - pretest.prg \ procline.prg \ procname.prg \ readhrb.prg \ diff --git a/harbour/tests/pretest.prg b/harbour/tests/pretest.prg deleted file mode 100644 index 4433c9a25e..0000000000 --- a/harbour/tests/pretest.prg +++ /dev/null @@ -1,421 +0,0 @@ -#command TEXT TO VAR => #pragma __stream|%s||:= -#command CTEXT TO VAR => #pragma __cstream|%s||:= - -/* Testing match markers */ - -PROCEDURE MAIN() -LOCAL in, out, pre -LOCAL nCnt:=0 -LOCAL nRes:=0 - - __PP_INIT() - - -/* ---------------------------------------------------------------------*/ - - in := "#xtranslate CCC => QOUT( [2] [, [][3]] )"+HB_OSNewLine()+; - "CCC b" - pre := "QOUT(b[2] ,bb[3] )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) -/*------------*/ - in := "#xtranslate AAA [A [B ] ] => Qout([][, ])" - __PreProcess( in ) -/*------------*/ - in:= "AAA" - pre :="Qout()" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ - in:= "AAA A a" - pre :="Qout(a )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ - in:= "AAA A a B b" - pre :="Qout(a ,b )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ -CTEXT TO VAR in -#define RED {255,0,0}\n -#xcommand SET TOOLTIP TO OF
=> -SM( TTH (<"form">), 1, RGB([1], -\[2\], -[, [ 3 ] ]), 0)\n -SET TOOLTIP TO RED OF form1 -ENDTEXT -TEXT TO VAR pre -SM(TTH ("form1"),1,RGB({255,0,0}[1],{255,0,0}[2],{255,0,0},{255,0,0}[ 3 ] ),0) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ - in :="#command ZZZ [] => QOUT([[1]])" - __PreProcess( in ) - in :="ZZZ a" - pre :="QOUT(a[1] )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ - in :="ZZZ" - pre :="QOUT()" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ - in := "ZZZ a[1]+2" - pre := "QOUT(a[1]+2[1] )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ -CTEXT TO VAR in -#xtranslate _HMG_a => _HMG\[137\]\n -v:= _bro[ a( _HMG_a [i] ) ] -ENDTEXT - pre :="v:= _bro[ a( _HMG[137] [i] ) ]" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ -CTEXT TO VAR in -#define clas( x ) (x)\n -#xtranslate ( { [] } => (():New(

)\n -a :=clas( TEST{ 1,2,3} ) -ENDTEXT - pre := "a :=(TEST():New(1,2,3) )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ -CTEXT TO VAR in -#define DATENEW 1\n -#define DATEOLD(x) x\n -#define datediff(x,y) ( DATEOLD(x) - DATENEW )\n -\n -#command datediff1(,) => ( DATEOLD() - DATENEW )\n -x := datediff( x, y ) -ENDTEXT - pre := "x := (x - 1 )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -/*------------*/ - //REGULAR - in := "#command _REGULAR_() => rm( )" - __PreProcess( in ) - - in := "_REGULAR_(a)" - pre :="rm(a )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := '_REGULAR_("a")' - pre :='rm("a" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_REGULAR_('a')" - pre :='rm("a" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -CTEXT TO VAR in -_REGULAR_(["'a'"]) -ENDTEXT -CTEXT TO VAR pre -rm(["'a'"] ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_REGULAR_(&a.1)" - pre :="rm(&a.1 )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_REGULAR_(&a)" - pre :="rm(&a )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_REGULAR_(&a.)" - pre :="rm(&a. )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_REGULAR_(&(a))" - pre :="rm(&(a) )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_REGULAR_(&a[1])" - pre :="rm(&a[1] )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_REGULAR_(a[1])" - pre :="rm(a[1] )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -CTEXT TO VAR in -_REGULAR_("['']") -ENDTEXT -CTEXT TO VAR pre -rm("['']" ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - - //NORMAL - in := '#command _NORMAL_M() => nm( <"z"> )' - __PreProcess( in ) - - in := "_NORMAL_M(a)" - pre :='nm("a" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := '_NORMAL_M("a")' - pre :=[nm('"a"' )] - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_NORMAL_M('a')" - pre :=[nm('"a"' )] - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -CTEXT TO VAR in -_NORMAL_M(["'a'"]) -ENDTEXT -CTEXT TO VAR pre -nm([["'a'"]] ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_NORMAL_M(&a.1)" - pre :='nm("&a.1" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_NORMAL_M(&a)" - pre :="nm(a )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_NORMAL_M(&a.)" - pre :="nm(a )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_NORMAL_M(&(a))" - pre :="nm((a) )" - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_NORMAL_M(&a[1])" - pre :='nm("&a[1]" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_NORMAL_M(a[1])" - pre :='nm("a[1]" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -CTEXT TO VAR in -_NORMAL_M("['']") -ENDTEXT -CTEXT TO VAR pre -nm(["['']"] ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - - //SMART - in := '#command _SMART_M() => sm( <(z)> )' - __PreProcess( in ) - - in := "_SMART_M(a)" - pre :='sm("a" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := '_SMART_M("a")' - pre :='sm("a" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_SMART_M('a')" - pre :='sm("a" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -CTEXT TO VAR in -_SMART_M(["'a'"]) -ENDTEXT -CTEXT TO VAR pre -sm(["'a'"] ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_SMART_M(&a.1)" - pre :='sm("&a.1" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_SMART_M(&a)" - pre :='sm(a )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_SMART_M(&a.)" - pre :='sm(a )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_SMART_M(&(a))" - pre :='sm((a) )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_SMART_M(&a[1])" - pre :='sm("&a[1]" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_SMART_M(a[1])" - pre :='sm("a[1]" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -CTEXT TO VAR in -_SMART_M("['']") -ENDTEXT -CTEXT TO VAR pre -sm("['']" ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - - - //DUMB - in := '#command _DUMB_M() => dm( # )' - __PreProcess( in ) - - in := "_DUMB_M(a)" - pre :='dm("a" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := '_DUMB_M("a")' - pre :=[dm('"a"' )] - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_DUMB_M('a')" - pre :=[dm('"a"' )] - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -CTEXT TO VAR in -_DUMB_M(["'a'"]) -ENDTEXT -CTEXT TO VAR pre -dm([["'a'"]] ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_DUMB_M(&a.1)" - pre :='dm("&a.1" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_DUMB_M(&a)" - pre :='dm("&a" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_DUMB_M(&a.)" - pre :='dm("&a." )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_DUMB_M(&(a))" - pre :='dm("&(a)" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_DUMB_M(&a[1])" - pre :='dm("&a[1]" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := "_DUMB_M(a[1])" - pre :='dm("a[1]" )' - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - -CTEXT TO VAR in -_DUMB_M("['']") -ENDTEXT -CTEXT TO VAR pre -dm(["['']"] ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - - // REGULAR list -CTEXT TO VAR in -#command _REGULAR_L() => rl( )\n -_REGULAR_L(a,"a",'a',["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &a.a, a, a) -ENDTEXT -CTEXT TO VAR pre -rl(a,"a","a",["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &a.a, a, a ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - // NORMAL list -CTEXT TO VAR in -#command _NORMAL_L() => nl( <"z"> )\n -_NORMAL_L(n,"n",'a',["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &.a, &a.a, a, a) -ENDTEXT -CTEXT TO VAR pre -nl("n",'"n"','"a"',[["'a'"]],["['a']"],['["a"]'],"&a.1",a,a,a,(a),"&a[1]","&a.[1]",a,"&a&a","&.a","&a.a","a","a" ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - // SMART list -CTEXT TO VAR in -#command _SMART_L() => sl( <(z)> )\n -_SMART_L(a,"a",'a',["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &.a, &a.a, a, a) -ENDTEXT -CTEXT TO VAR pre -sl("a","a","a",["'a'"],"['a']",'["a"]',"&a.1",a,a,a,(a),"&a[1]","&a.[1]",a,"&a&a","&.a","&a.a","a","a" ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - // DUMB list -CTEXT TO VAR in -#command _DUMB_L() => dl( # )\n -_DUMB_L(a,"a",'a',["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &.a, &a.a, a, a) -ENDTEXT -CTEXT TO VAR pre -dl([a,"a","a",["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &.a, &a.a, a, a] ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - in := " -index on LEFT( f1 , 10 ) to _tst" -CTEXT TO VAR pre -dbCreateIndex( "_tst", "LEFT( f1 , 10 )", {||LEFT( f1 , 10 )}, if( .F., .t., NIL ) ) -ENDTEXT - nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) - - - -/* ---------------------------------------------------------------------*/ - __PP_FREE() - - ? "Total count =", nCnt - ? "Valid results =", nRes - ? "Failed results=", nCnt - nRes - - RETURN - -PROCEDURE PrePrepare( in ) -LOCAL len, i, cin, cout - - len := MLCOUNT( in ) - FOR i:=1 TO len - cin := ALLTRIM( MEMOLINE(in, 192, i) ) - __PreProcess( cin ) - NEXT - -RETURN - -FUNCTION PreRun( in, pre ) -LOCAL len, i, cin, cout -LOCAL out:='' - - len := MLCOUNT( in ) - FOR i:=1 TO len - cin := ALLTRIM( MEMOLINE(in, 1024, i) ) - out += __PreProcess( cin ) - NEXT - -RETURN out - -FUNCTION PreResult( pre, out, pCnt ) - - pCnt++ - IF( pre == out ) - RETURN 1 - ELSE - ? pre - ? out - ? " => FAILED in LINE: ", PROCLINE(1) - ENDIF - -RETURN 0 \ No newline at end of file diff --git a/harbour/utils/hbpptest/Makefile b/harbour/utils/hbpptest/Makefile new file mode 100644 index 0000000000..ec59ee540e --- /dev/null +++ b/harbour/utils/hbpptest/Makefile @@ -0,0 +1,28 @@ +# +# $Id$ +# + +ifeq ($(HB_MAIN),) + HB_MAIN = std +endif + +ROOT = ../../ + +PRG_SOURCES=\ + pretest.prg \ + +PRG_MAIN=pretest.prg + +LIBS=\ + debug \ + vm \ + rtl \ + lang \ + rdd \ + rtl \ + vm \ + macro \ + pp \ + common \ + +include $(TOP)$(ROOT)config/bin.cf diff --git a/harbour/utils/hbpptest/pretest.prg b/harbour/utils/hbpptest/pretest.prg new file mode 100644 index 0000000000..28d342b4d0 --- /dev/null +++ b/harbour/utils/hbpptest/pretest.prg @@ -0,0 +1,1008 @@ +// +// $Id$ +// + +#command TEXT TO VAR => #pragma __stream|%s||:= +#command CTEXT TO VAR => #pragma __cstream|%s||:= + +/* Testing preprocessor */ + +PROCEDURE MAIN() +LOCAL in, out, pre +LOCAL nCnt:=0 +LOCAL nRes:=0 + + __PP_INIT() + +/* ---------------------------------------------------------------------*/ + in := "#xtranslate CCC => QOUT( [2] [, [][3]] )"+HB_OSNewLine()+; + "CCC b" + pre := "QOUT(b[2] ,bb[3] )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) +/*------------*/ + in := "#xtranslate AAA [A [B ] ] => Qout([][, ])" + __PreProcess( in ) +/*------------*/ + in:= "AAA" + pre :="Qout()" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ + in:= "AAA A a" + pre :="Qout(a )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ + in:= "AAA A a B b" + pre :="Qout(a ,b )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ +CTEXT TO VAR in +#define RED {255,0,0}\n +#xcommand SET TOOLTIP TO OF => +SM( TTH (<"form">), 1, RGB([1], +\[2\], +[, [ 3 ] ]), 0)\n +SET TOOLTIP TO RED OF form1 +ENDTEXT +TEXT TO VAR pre +SM(TTH ("form1"),1,RGB({255,0,0}[1],{255,0,0}[2],{255,0,0},{255,0,0}[ 3 ] ),0) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ + in :="#command ZZZ [] => QOUT([[1]])" + __PreProcess( in ) + in :="ZZZ a" + pre :="QOUT(a[1] )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ + in :="ZZZ" + pre :="QOUT()" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ + in := "ZZZ a[1]+2" + pre := "QOUT(a[1]+2[1] )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ +CTEXT TO VAR in +#xtranslate _HMG_a => _HMG\[137\]\n +v:= _bro[ a( _HMG_a [i] ) ] +ENDTEXT + pre :="v:= _bro[ a( _HMG[137] [i] ) ]" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ +CTEXT TO VAR in +#define clas( x ) (x)\n +#xtranslate ( { [] } => (():New(

)\n +a :=clas( TEST{ 1,2,3} ) +ENDTEXT + pre := "a :=(TEST():New(1,2,3) )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ +CTEXT TO VAR in +#define DATENEW 1\n +#define DATEOLD(x) x\n +#define datediff(x,y) ( DATEOLD(x) - DATENEW )\n +\n +#command datediff1(,) => ( DATEOLD() - DATENEW )\n +x := datediff( x, y ) +ENDTEXT + pre := "x := (x - 1 )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +/*------------*/ + //REGULAR + in := "#command _REGULAR_() => rm( )" + __PreProcess( in ) + + in := "_REGULAR_(a)" + pre :="rm(a )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := '_REGULAR_("a")' + pre :='rm("a" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_REGULAR_('a')" + pre :='rm("a" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +_REGULAR_(["'a'"]) +ENDTEXT +CTEXT TO VAR pre +rm(["'a'"] ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_REGULAR_(&a.1)" + pre :="rm(&a.1 )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_REGULAR_(&a)" + pre :="rm(&a )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_REGULAR_(&a.)" + pre :="rm(&a. )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_REGULAR_(&(a))" + pre :="rm(&(a) )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_REGULAR_(&a[1])" + pre :="rm(&a[1] )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_REGULAR_(a[1])" + pre :="rm(a[1] )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +_REGULAR_("['']") +ENDTEXT +CTEXT TO VAR pre +rm("['']" ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + + //NORMAL + in := '#command _NORMAL_M() => nm( <"z"> )' + __PreProcess( in ) + + in := "_NORMAL_M(a)" + pre :='nm("a" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := '_NORMAL_M("a")' + pre :=[nm('"a"' )] + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_NORMAL_M('a')" + pre :=[nm('"a"' )] + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +_NORMAL_M(["'a'"]) +ENDTEXT +CTEXT TO VAR pre +nm([["'a'"]] ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_NORMAL_M(&a.1)" + pre :='nm("&a.1" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_NORMAL_M(&a)" + pre :="nm(a )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_NORMAL_M(&a.)" + pre :="nm(a )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_NORMAL_M(&(a))" + pre :="nm((a) )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_NORMAL_M(&a[1])" + pre :='nm("&a[1]" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_NORMAL_M(a[1])" + pre :='nm("a[1]" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +_NORMAL_M("['']") +ENDTEXT +CTEXT TO VAR pre +nm(["['']"] ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + + //SMART + in := '#command _SMART_M() => sm( <(z)> )' + __PreProcess( in ) + + in := "_SMART_M(a)" + pre :='sm("a" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := '_SMART_M("a")' + pre :='sm("a" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_SMART_M('a')" + pre :='sm("a" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +_SMART_M(["'a'"]) +ENDTEXT +CTEXT TO VAR pre +sm(["'a'"] ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_SMART_M(&a.1)" + pre :='sm("&a.1" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_SMART_M(&a)" + pre :='sm(a )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_SMART_M(&a.)" + pre :='sm(a )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_SMART_M(&(a))" + pre :='sm((a) )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_SMART_M(&a[1])" + pre :='sm("&a[1]" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_SMART_M(a[1])" + pre :='sm("a[1]" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +_SMART_M("['']") +ENDTEXT +CTEXT TO VAR pre +sm("['']" ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + + + //DUMB + in := '#command _DUMB_M() => dm( # )' + __PreProcess( in ) + + in := "_DUMB_M(a)" + pre :='dm("a" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := '_DUMB_M("a")' + pre :=[dm('"a"' )] + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_DUMB_M('a')" + pre :=[dm('"a"' )] + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +_DUMB_M(["'a'"]) +ENDTEXT +CTEXT TO VAR pre +dm([["'a'"]] ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_DUMB_M(&a.1)" + pre :='dm("&a.1" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_DUMB_M(&a)" + pre :='dm("&a" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_DUMB_M(&a.)" + pre :='dm("&a." )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_DUMB_M(&(a))" + pre :='dm("&(a)" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_DUMB_M(&a[1])" + pre :='dm("&a[1]" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "_DUMB_M(a[1])" + pre :='dm("a[1]" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +_DUMB_M("['']") +ENDTEXT +CTEXT TO VAR pre +dm(["['']"] ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + + // REGULAR list +CTEXT TO VAR in +#command _REGULAR_L() => rl( )\n +_REGULAR_L(a,"a",'a',["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &a.a, a, a) +ENDTEXT +CTEXT TO VAR pre +rl(a,"a","a",["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &a.a, a, a ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + // NORMAL list +CTEXT TO VAR in +#command _NORMAL_L() => nl( <"z"> )\n +_NORMAL_L(n,"n",'a',["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &.a, &a.a, a, a) +ENDTEXT +CTEXT TO VAR pre +nl("n",'"n"','"a"',[["'a'"]],["['a']"],['["a"]'],"&a.1",a,a,a,(a),"&a[1]","&a.[1]","&a. [2]","&a&a","&.a","&a.a","a","a" ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + // SMART list +CTEXT TO VAR in +#command _SMART_L() => sl( <(z)> )\n +_SMART_L(a,"a",'a',["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &.a, &a.a, a, a) +ENDTEXT +CTEXT TO VAR pre +sl("a","a","a",["'a'"],"['a']",'["a"]',"&a.1",a,a,a,(a),"&a[1]","&a.[1]","&a. [2]","&a&a","&.a","&a.a","a","a" ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + // DUMB list +CTEXT TO VAR in +#command _DUMB_L() => dl( # )\n +_DUMB_L(a,"a",'a',["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &.a, &a.a, a, a) +ENDTEXT +CTEXT TO VAR pre +dl([a,"a","a",["'a'"],"['a']",'["a"]',&a.1,&a,&a.,&a. ,&(a),&a[1],&a.[1],&a. [2],&a&a, &.a, &a.a, a, a] ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := " +index on LEFT( f1 , 10 ) to _tst" +CTEXT TO VAR pre +dbCreateIndex( "_tst", "LEFT( f1 , 10 )", {||LEFT( f1 , 10 )}, if( .F., .t., NIL ) ) +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +TEXT TO VAR in +#xcommand SET [, ] WITH => +:=[; :=] +ENDTEXT + __PreProcess( in ) + in := "SET v1, v2, v3 WITH 0" + pre := "v1:=0; v2:=0 ; v3:=0 " + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +TEXT TO VAR in +#xcommand INSERT INTO ( [, ] ) VALUES ( +[, ] ) => if
->( dbappend() )
-> := [
-> := ]
->( dbunlock() ) endif + +ENDTEXT + __PreProcess( in ) +TEXT TO VAR in +insert into test ( FIRST, LAST, STREET ) values ( "first", "last", "street" ) +ENDTEXT +TEXT TO VAR pre +if test->(dbappend() ) test->FIRST := "first" test->LAST := "last" test->STREET := "street" test->(dbunlock() ) endif +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +TEXT TO VAR in +#xcommand INSERT2 INTO
( [, ] ) VALUES ( +[, ] ) => +if
->( dbappend() ) ; +
-> := ; + [
-> := ; ] +
->( dbunlock() ) ; +endif +ENDTEXT + __PreProcess( in ) +TEXT TO VAR in +insert2 into test ( FIRST, LAST, STREET ) + values ( "first", "last", "street" ) +ENDTEXT +TEXT TO VAR pre +if test->(dbappend() ) ; test->FIRST := "first" ; test->LAST := "last" ; test->STREET := "street" ; test->(dbunlock() ) ;endif +ENDTEXT + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "#define F1( n ) F2( n, N )" + __PreProcess( in ) + in := "F1( 1 )" + pre := "F2(1 ,N )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "#define F3( nN, Nn ) F2( nN, Nn, NN, nn, N, n )" + __PreProcess( in ) + in := "F3( 1, 2 )" + pre := "F2(1,2 ,NN,nn,N,n )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +TEXT TO VAR in +#command MYCOMMAND [] [MYCLAUSE ] => + MyFunction( {} [, ] ) +ENDTEXT + __PreProcess( in ) + in := 'MYCOMMAND MYCLAUSE 321 "HELLO"' + pre := 'MyFunction({"HELLO"} ,321 )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := 'MYCOMMAND MYCLAUSE 321 "HELLO","all"' + pre := 'MyFunction({"HELLO","all"} ,321 )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := 'MYCOMMAND "HELLO","all" MYCLAUSE 321' + pre := 'MyFunction({"HELLO","all"} ,321 )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +TEXT TO VAR in +#command MYCOMMAND2 [] [MYCLAUSE ] [ALL] => + MyFunction( {} [, ] ) +ENDTEXT + __PreProcess( in ) + pre := 'MyFunction({"HELLO"} ,321 )' + in := 'MYCOMMAND2 MYCLAUSE 321 "HELLO"' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + in := 'MYCOMMAND2 MYCLAUSE 321 "HELLO" ALL' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := 'MYCOMMAND2 ALL MYCLAUSE 321 "HELLO"' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := 'MYCOMMAND2 MYCLAUSE 321 "HELLO" ALL' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := 'MYCOMMAND2 MYCLAUSE 321 ALL "HELLO"' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + +TEXT TO VAR in +#command MYCOMMAND3 [] [MYCLAUSE ] [] => + MyFunction( {} [, ] [,<.all.>] ) +ENDTEXT + __PreProcess( in ) + in := 'MYCOMMAND3 ALL MYCLAUSE 321 "HELLO","WORLD"' + pre := 'MyFunction({"HELLO","WORLD"} ,321 ,.T. )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := 'MYCOMMAND3 MYCLAUSE 321 ALL "HELLO"' + pre := 'MyFunction({"HELLO"} ,321 ,.T. )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := 'MYCOMMAND3 MYCLAUSE 321 "HELLO" ALL' + pre := 'MyFunction({"HELLO"} ,321 ,.T. )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := 'MYCOMMAND3 MYCLAUSE 321 "HELLO"' + pre := 'MyFunction({"HELLO"} ,321 )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + + /* Special restricted macro match marker (used in SET FILTER TO command */ + in := "SET FILTER TO &cVar." + pre := "if ( Empty(cVar) ) ; dbClearFilter() ; else ; dbSetFilter({||&cVar.},cVar) ; end" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "SET FILTER TO &(cVar .AND. &cVar)" + pre := "if ( Empty((cVar .AND. &cVar)) ) ; dbClearFilter() ; else ; dbSetFilter({||&(cVar .AND. &cVar)},(cVar .AND. &cVar)) ; end" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "SET FILTER TO &cVar. .AND. cVar" + pre := 'dbSetFilter( {||&cVar. .AND. cVar}, "&cVar. .AND. cVar" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +#xtranslate XTRANS(( => normal( <(x)> )\n +#xtranslate XTRANS(( => macro( <(x)> ) +ENDTEXT + PrePrepare( in ) + + in := "XTRANS( cVar (" + pre := 'normal("cVar" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &cVar (" + pre := 'macro(cVar )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &cVar+1 (" + pre := 'normal("&cVar+1" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &cVar. (" + pre := 'macro(cVar )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( (&cVar.) (" + pre := 'XTRANS( (&cVar.) (' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &(cVar) (" + pre := 'macro((cVar) )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &cVar[3] (" + pre := 'normal("&cVar[3]" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &cVar. [3] (" + pre := 'normal("&cVar. [3]" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &(cVar [3],&cvar) (" + pre := 'macro((cVar [3],&cvar) )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( (&cVar. [3],&cvar) (" + pre := 'XTRANS( (&cVar. [3],&cvar) (' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &cVar.1+5 (" + pre := 'normal("&cVar.1+5" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &cVar .AND. cVar (" + pre := 'normal("&cVar .AND. cVar" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "XTRANS( &cVar. .AND. cVar (" + pre := 'normal("&cVar. .AND. cVar" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +#xtranslate MXCALL => ()\n +#xtranslate MYCALL => ( , 'mycall' )\n +#xtranslate MZCALL => ( , "mzcall" )\n +#command FOO FOO => <(x)>+<(y)>\n +#translate BAR BAR => <(x)>+<(y)> +ENDTEXT + PrePrepare( in ) + + in := "MYCALL &cVar ++cVar" + pre := '&cVar(++cVar,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MZCALL &cVar ++cVar" + pre := '&cVar ++(cVar,"mzcall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar+1 &cVar" + pre := '&cVar(+1,"mycall" ) &cVar' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MZCALL &cVar+1 &cVar" + pre := '&cVar+1(&cVar,"mzcall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar" + pre := '(&cVar)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar." + pre := '(&cVar.)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar.1" + pre := '(&cVar.1)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar + 1" + pre := '(&cVar) + 1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar &cVar" + pre := '&cVar(&cVar,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar. &cVar." + pre := '&cVar.(&cVar.,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar.1 &cVar.1" + pre := '&cVar.1(&cVar.1,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar ++cVar" + pre := '&cVar(++cVar,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar. --cVar" + pre := '&cVar.(--cVar,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar.1 !cVar" + pre := '&cVar.1(!cVar,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar+1 &cVar" + pre := '&cVar(+1,"mycall" ) &cVar' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar.+1 &cVar." + pre := '&cVar.(+1,"mycall" ) &cVar.' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar.1+1 &cVar.1" + pre := '&cVar.1(+1,"mycall" ) &cVar.1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar +1 &cVar" + pre := '&cVar(+1,"mycall" ) &cVar' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar. +1 &cVar." + pre := '&cVar.(+1,"mycall" ) &cVar.' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar.1 +1 &cVar.1" + pre := '&cVar.1(+1,"mycall" ) &cVar.1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar +1" + pre := '&cVar(+1,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar. +1" + pre := '&cVar.(+1,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MYCALL &cVar.1 +1" + pre := '&cVar.1(+1,"mycall" )' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "FOO &cVar FOO &var." + pre := 'cVar+var' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "BAR &cVar BAR &var." + pre := 'cVar+var' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "FOO &cVar FOO &var.+1" + pre := 'FOO &cVar FOO &var.+1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "BAR &cVar BAR &var.+1" + pre := 'cVar+var+1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar()" + pre := '(&cVar)()' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar++" + pre := '(&cVar)++' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "(MXCALL &cVar)++" + pre := '((&cVar))++' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar.()" + pre := '(&cVar.)()' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar.++" + pre := '(&cVar.)++' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "(MXCALL &cVar.)++" + pre := '((&cVar.))++' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar.1 ()" + pre := '(&cVar.1) ()' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MXCALL &cVar.1 ++" + pre := '(&cVar.1) ++' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "(MXCALL &cVar.1) ++" + pre := '((&cVar.1)) ++' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +CTEXT TO VAR in +#translate MTRANSLATE => normal_t(<"x">)\n +#translate MTRANSLATE => macro_t(<(x)>)\n +#command MCOMMAND => normal_c(<"x">)\n +#command MCOMMAND => macro_c(<(x)>) +ENDTEXT + PrePrepare( in ) + + in := "MTRANSLATE &cVar" + pre :='macro_t(cVar)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar." + pre :='macro_t(cVar)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &(cVar)" + pre :='macro_t((cVar))' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE & (cVar)" + pre :='macro_t((cVar))' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar&cVar" + pre :='macro_t("&cVar&cVar")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar+1" + pre :='macro_t(cVar)+1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar.+1" + pre :='macro_t(cVar)+1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar. .AND. .T." + pre :='macro_t(cVar) .AND. .T.' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar++" + pre :='macro_t(cVar)++' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar.++" + pre :='macro_t(cVar)++' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar+=1" + pre :='macro_t(cVar)+=1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar.-=2" + pre :='macro_t(cVar)-=2' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar*=1" + pre :='macro_t(cVar)*=1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar/=2" + pre :='macro_t(cVar)/=2' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar%=1" + pre :='macro_t(cVar)%=1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar^=2" + pre :='macro_t(cVar)^=2' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar:=1" + pre :='macro_t(cVar):=1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar. .AND. .T." + pre :='macro_t(cVar) .AND. .T.' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar .AND. .T." + pre :='macro_t(cVar) .AND. .T.' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &(cVar) +1" + pre :='macro_t((cVar)) +1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE & (cVar) +1" + pre :='macro_t((cVar)) +1' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar.&cVar." + pre :='macro_t("&cVar.&cVar.")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar.&cVar.&cVar&cVar" + pre :='macro_t("&cVar.&cVar.&cVar&cVar")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MTRANSLATE &cVar.&(cVar)" + pre :='macro_t("&cVar.&")(cVar)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + + /* command */ + in := "MCOMMAND &cVar" + pre :='macro_c(cVar)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar." + pre :='macro_c(cVar)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &(cVar)" + pre :='macro_c((cVar))' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND & (cVar)" + pre :='macro_c((cVar))' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar&cVar" + pre :='macro_c("&cVar&cVar")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar+1" + pre :='normal_c("&cVar+1")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar.+1" + pre :='normal_c("&cVar.+1")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar. .AND. .T." + pre :='normal_c("&cVar. .AND. .T.")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar++" + pre :='normal_c("&cVar++")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar.++" + pre :='normal_c("&cVar.++")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar+=1" + pre :='normal_c("&cVar+=1")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar.-=2" + pre :='normal_c("&cVar.-=2")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar*=1" + pre :='normal_c("&cVar*=1")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar/=2" + pre :='normal_c("&cVar/=2")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar%=12" + pre :='normal_c("&cVar%=12")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar^=2" + pre :='normal_c("&cVar^=2")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar:=1" + pre :='normal_c("&cVar:=1")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar. .AND. .T." + pre :='normal_c("&cVar. .AND. .T.")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar .AND. .T." + pre :='normal_c("&cVar .AND. .T.")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &(cVar) +1" + pre :='normal_c((cVar) +1)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND & (cVar) +1" + pre :='normal_c( (cVar) +1)' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar.&cVar." + pre :='macro_c("&cVar.&cVar.")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar.&cVar.&cVar&cVar2" + pre :='macro_c("&cVar.&cVar.&cVar&cVar2")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "MCOMMAND &cVar.&(cVar)" + pre :='normal_c("&cVar.&(cVar)")' + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + /* repeated optional clauses */ +TEXT TO VAR in +#xcommand SET [, ] WITH => +:= [; :=] +ENDTEXT + __PreProcess( in ) + in := "SET v1 WITH 0" + pre := "v1:=0 " + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "SET v1, v2 WITH 0" + pre := "v1:=0 ; v2:=0 " + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "SET v1, v2, v3 WITH 0" + pre := "v1:=0 ; v2:=0 ; v3:=0 " + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "SET v1, v2, v3, v4 WITH 0" + pre := "v1:=0 ; v2:=0 ; v3:=0 ; v4:=0 " + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + +TEXT TO VAR in +#command AVG [, ] TO [, ] => + AVERAGE( {||:=+} [, {||:=+} ] ) +ENDTEXT + __PreProcess( in ) + in := "AVG f1 TO s1" + pre := "AVERAGE({||s1:=s1+f1} )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "AVG f1, f2 TO s1, s2" + pre := "AVERAGE({||s1:=s1+f1} ,{||s2:=s2+f2} )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + in := "AVG f1, f2, f3 TO s1, s2, s3" + pre := "AVERAGE({||s1:=s1+f1} ,{||s2:=s2+f2} ,{||s3:=s3+f3} )" + nRes += PreResult( pre, PreRun( in, pre ), @nCnt ) + + + +/* ---------------------------------------------------------------------*/ + __PP_FREE() + + ? "Total count =", nCnt + ? "Valid results =", nRes + ? "Failed results=", nCnt - nRes + + RETURN + +PROCEDURE PrePrepare( in ) +LOCAL len, i, cin, cout + + len := MLCOUNT( in ) + FOR i:=1 TO len + cin := ALLTRIM( MEMOLINE(in, 192, i) ) + __PreProcess( cin ) + NEXT + +RETURN + +FUNCTION PreRun( in, pre ) +LOCAL len, i, cin, cout +LOCAL out:='' + + len := MLCOUNT( in ) + FOR i:=1 TO len + cin := ALLTRIM( MEMOLINE(in, 1024, i) ) + out += __PreProcess( cin ) + NEXT + +RETURN out + +FUNCTION PreResult( pre, out, pCnt ) +LOCAL i + + pCnt++ + IF( pre == out ) + RETURN 1 + ELSE + ? pre + ? out + ? " => FAILED in LINE: ", PROCLINE(1) + i := 1 + WHILE SUBSTR(pre,i,1) == SUBSTR(out,i,1) + i++ + ENDDO + ? SUBSTR( pre, i ) + ? SUBSTR( out, i ) + ENDIF + +RETURN 0 \ No newline at end of file