From ee515d47179f21ea1b23b551d17abfc673e89d61 Mon Sep 17 00:00:00 2001 From: Ryszard Glab Date: Tue, 16 Nov 1999 21:06:31 +0000 Subject: [PATCH] ChangeLog 19991116-21:55 --- harbour/ChangeLog | 55 + harbour/doc/compiler.txt | 40 +- harbour/include/compiler.h | 399 ++- harbour/include/hberrors.h | 10 +- harbour/include/hbpp.h | 4 +- harbour/include/pcode.h | 4 +- harbour/source/compiler/expropt.c | 5135 +++++++++++++++++++++++++-- harbour/source/compiler/genc.c | 187 +- harbour/source/compiler/genhrb.c | 36 +- harbour/source/compiler/genjava.c | 32 +- harbour/source/compiler/genobj32.c | 38 +- harbour/source/compiler/harbour.c | 3334 +++++++++++++++++- harbour/source/compiler/harbour.l | 561 ++- harbour/source/compiler/harbour.y | 5174 +++++----------------------- harbour/source/debug/debugger.prg | 25 +- harbour/source/pp/hbpp.c | 30 +- harbour/source/pp/hbppint.c | 2 +- harbour/source/pp/hbpplib.c | 8 +- harbour/source/pp/stdalone/hbpp.c | 38 +- harbour/source/vm/hvm.c | 77 +- 20 files changed, 10071 insertions(+), 5118 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 8020464710..97518d7a35 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,58 @@ +19991116-21:55 GMT+1 Ryszard Glab + + * source/compiler/harbour.y + * source/compiler/harbour.l + * source/compiler/harbour.c + * source/compiler/expropt.c + * source/compiler/genc.c + * source/compiler/genhrb.c + * source/compiler/genobj32.c + * source/compiler/genjava.c + * new implementation of grammar rules - many new syntax supported + * new expression optimizer + * start of introducing new functions' naming scheme 'hb_comp' + * nonprintable characters (CR/LF/TAB, etc.) are inserted into + generated C code using hexdecimal numbers instead of quoted char + (they can appear as a result of expression optimization) + + * source/pp/hbpp.c + * source/pp/hbppint.c + * source/pp/hblib.c + * source/pp/stdalone/hbpp.c + * changes to support new functions' naming scheme 'hb_comp' + + *include/pcode.h + *HB_P_ARRAYAAT -> HB_P_ARRAYPUSH + HB_P_ARRAYAPUT -> HB_P_ARRAYPOP - it removes value from the stack + This is compatible with the handling of usual variables + + *source/debug/debugger.prg + * corrected the following syntax: + something other := another + for example: + ? 2 + a:=5 -1 + This syntax is not allowed in Clipper and in new Harbour rules too + It should be used: + ? 2 + (a:=5) -1 + + * doc/compiler.txt + * added description of incompatibility with Clipper in object + handling + + * include/compiler.h + * new structures related to expression optimizer + + * include/hberrors.h + * new errors: Invalid type, invalid syntax, invalid alias + * new warning: meaningless expression + + * source/vm/hvm.c + * change in handling of HB_P_FORTEST opcode used in FOR/NEXT loop + * Renamed ArrayAt -> ArrayPush + * Renamed ArrayPut -> ArrayPop - it removes the value from the + eval stack now + + 19991116-15:05 GMT+1 Victor Szel * source/rtl/memvars.c ! __MSAVE() Modified to save MEMVARs with names longer than 10 chars, the diff --git a/harbour/doc/compiler.txt b/harbour/doc/compiler.txt index 6b4c2d6cf6..377bb9ec16 100644 --- a/harbour/doc/compiler.txt +++ b/harbour/doc/compiler.txt @@ -151,7 +151,7 @@ Compilation in batch mode. Known incompatibilities between harbour and clipper compilers ============================================================= -NOTE: +NOTE: If you want 100% compatible compiler and runtime libraries then you have to define HARBOUR_STRICT_CLIPPER_COMPATIBILITY option. This option should be defined in include/hbsetup.h file (in fact this @@ -160,10 +160,10 @@ characters only). This change have to be done before invoking the make utility. -Handling of undeclared variables +Handling of undeclared variables -------------------------------- When a value is assigned to an undeclared variable and '-v' command -line option is not used then the Clipper compiler assumes that the variable +line option is not used then the Clipper compiler assumes that the variable is a PRIVATE or a PUBLIC variable and generates POPM (pop memvar) opcode. When a value of undeclared variable is accessed and '-v' command line option is not used the Clipper compiler generates PUSHV (push variable) @@ -171,8 +171,8 @@ opcode that determines the type of variable at runtime. If the field with requested name exists in a current workarea then its value is used. If there is no field then a PRIVATE or a PUBLIC variable is used (if exists). - The Harbour compiler generates an opcode to determine the type of variable -at runtime (POPVARIABLE or PUSHVARIABLE) in both cases (assignment and access). + The Harbour compiler generates an opcode to determine the type of variable +at runtime (POPVARIABLE or PUSHVARIABLE) in both cases (assignment and access). The difference can be checked by the following code: @@ -208,3 +208,33 @@ why the Harbour compiler uses the usual PUSHMEMVARREF opcode in such cases. Notice that the runtime behavior is the same in Clipper and in Harbour - the generated opcodes are different only. + +Handling of object messages +--------------------------- + The HARBOUR_STRICT_CLIPPER_COMPATIBILITY setting determines +the way the chained send messages are handled. + +For example, the following code: + +a:b( COUNT() ):c += 1 + +will be handled as: + +a:b( COUNT() ):c := a:b( COUNT() ):c + 1 + +in strict Clipper compatibility mode and + +temp := a:b( COUNT() ), temp:c += 1 + +in non-strict mode. + + In practice in Clipper it will call COUNT() function two times: the +first time before addition and the second one after addition - in Harbour, +COUNT() function will be called only once, before addition. + + The Harbour (non-strict) method is: +1) faster +2) it guarantees that the same instance variable of the same object will + be changed + +(See also: source/compiler/expropt.c) diff --git a/harbour/include/compiler.h b/harbour/include/compiler.h index c0c203cf4c..05025bafd1 100644 --- a/harbour/include/compiler.h +++ b/harbour/include/compiler.h @@ -36,10 +36,40 @@ #ifndef HB_COMPILER_H_ #define HB_COMPILER_H_ +#include +#include +#include +#include +#include /* required for allocating and freeing memory */ +#include +#include + +#include "hbsetup.h" +#include "extend.h" +#include "pcode.h" /* pcode values */ +#include "hberrors.h" #include "hbpp.h" +#include "hbver.h" /* compiler related declarations */ +typedef struct /* #include support */ +{ + FILE * handle; /* handle of the opened file */ + void * pBuffer; /* buffer used by yacc */ + char * szFileName; /* name of the file */ + void * pPrev; /* pointer to the previous opened file */ + void * pNext; /* pointer to the next opened file */ + int iLine; /* currently processed line number */ +} _FILE, * PFILE; /* structure to hold an opened PRG or CH */ + +typedef struct +{ + PFILE pLast; /* pointer to the last opened file */ + int iFiles; /* number of files currently opened */ +} FILES; /* structure to control several opened PRGs and CHs */ + + /* locals, static, public variables support */ typedef struct _VAR { @@ -50,6 +80,9 @@ typedef struct _VAR struct _VAR * pNext; /* pointer to next defined variable */ } VAR, * PVAR; +/* pcode chunks bytes size */ +#define PCODE_CHUNK 100 + /* structure to hold a Clipper defined function */ typedef struct __FUNC /* functions definition support */ { @@ -65,7 +98,6 @@ typedef struct __FUNC /* functions definition support */ BYTE * pCode; /* pointer to a memory block where pcode is stored */ ULONG lPCodeSize; /* total memory size for pcode */ ULONG lPCodePos; /* actual pcode offset */ - LONG lLastPushPos; /* pointer to last push operation, used by push/pop optimizer */ int iStaticsBase; /* base for this function statics */ struct __FUNC * pOwner; /* pointer to the function/procedure that owns the codeblock */ struct __FUNC * pNext; /* pointer to the next defined function */ @@ -96,8 +128,63 @@ typedef struct int iCount; /* number of defined symbols */ } SYMBOLS; -extern PFUNCTION GetFunction( char * szFunName ); /* locates a previously defined function */ -extern USHORT GetFunctionPos( char * szSymbolName ); /* returns the index + 1 of a function on the functions defined list */ +typedef struct HB_EXPR_ +{ + union + { + char *asString; /* literal strings */ + char *asSymbol; /* variable name */ + BOOL asLogical; /* logical value */ + struct + { + long lVal; /* long value */ + double dVal; /* double value */ + unsigned char bDec; /* unsigned char used intentionally */ + unsigned char NumType; /* used to distinguish LONG and DOUBLE */ + } asNum; + struct + { + struct HB_EXPR_ *pVar; /* macro variable */ + char * szNameExt; /* text after the macro terminator */ + } asMacro; + struct + { + struct HB_EXPR_ *pExprList; /* list elements */ + struct HB_EXPR_ *pIndex; /* array index, others */ + } asList; + struct + { + struct HB_EXPR_ *pAlias; /* alias expression */ + char * szVarName; /* aliased variable */ + struct HB_EXPR_ *pExpList; /* aliased expression list */ + } asAlias; + struct + { + char * szFunName; /* function name */ + struct HB_EXPR_ *pParms; /* function call parameters */ + } asFunCall; + struct + { + struct HB_EXPR_ *pObject; /* object */ + char * szMessage; /* message */ + struct HB_EXPR_ *pParms; /* method parameters */ + } asMessage; + struct + { + struct HB_EXPR_ *pLeft; /* object */ + struct HB_EXPR_ *pRight; /* object */ + } asOperator; + } value; + ULONG ulLength; + unsigned char ExprType; /* internal expression type */ + USHORT ValType; /* language level value type */ + struct HB_EXPR_ *pNext; /* next expression in the list of expressions */ +} HB_EXPR, *HB_EXPR_PTR; + + + +extern PFUNCTION GetFunction( char * szFunName ); /* locates a previously defined function */ +extern USHORT GetFunctionPos( char * szSymbolName ); /* returns the index + 1 of a function on the functions defined list */ extern void * hb_xgrab( ULONG lSize ); /* allocates memory, exists on failure */ extern void * hb_xrealloc( void * pMem, ULONG lSize ); /* reallocates memory */ @@ -106,24 +193,18 @@ extern void hb_xfree( void * pMem ); /* frees memory */ char * yy_strdup( char * p ); /* this will exit if there is not enough memory */ char * yy_strupr( char * p ); +#if 0 +static void __yy_memcpy( char * from, char * to, int count ); /* Bison prototype */ +#endif + extern USHORT FixSymbolPos( USHORT ); /* converts symbol's compile-time position into generation-time position */ extern PFUNCTION GetFuncall( char * szFunName ); /* locates a previously defined called function */ extern PVAR GetVar( PVAR pVars, USHORT wOrder ); /* returns a variable if defined or zero */ -extern PCOMSYMBOL GetSymbol( char *, USHORT * ); /* returns a symbol pointer from the symbol table */ -extern PCOMSYMBOL GetSymbolOrd( USHORT ); /* returns a symbol based on its index on the symbol table */ +extern PCOMSYMBOL hb_compGetSymbol( char *, USHORT * ); /* returns a symbol pointer from the symbol table */ +extern PCOMSYMBOL hb_compGetSymbolOrd( USHORT ); /* returns a symbol based on its index on the symbol table */ extern PFUNCTION KillFunction( PFUNCTION ); /* releases all memory allocated by function and returns the next one */ extern PCOMSYMBOL KillSymbol( PCOMSYMBOL ); /* releases all memory allocated by symbol and returns the next one */ -extern FUNCTIONS functions, funcalls; -extern PFUNCTION _pInitFunc; -extern SYMBOLS symbols; -extern PHB_FNAME _pFileName; -extern BOOL _bQuiet; -extern BOOL _bStartProc; -extern char _szPrefix[ 20 ]; /* holds the prefix added to the generated symbol init function name (in C output currently) */ -extern BOOL _bGenCVerbose; -extern char * _szCErrors[]; - #define VS_LOCAL 1 #define VS_STATIC 2 #define VS_FIELD 4 @@ -132,12 +213,286 @@ extern char * _szCErrors[]; #define VS_PUBLIC 128 #define VS_MEMVAR ( VS_PUBLIC | VS_PRIVATE ) -/* flags for bFlags member */ -#define FUN_STATEMENTS 1 /* Function have at least one executable statement */ -#define FUN_USES_STATICS 2 /* Function uses static variables */ -#define FUN_PROCEDURE 4 /* This is a procedure that shouldn't return value */ -#define FUN_ILLEGAL_INIT 8 /* Attempt to initialize static variable with a function call */ -#define FUN_USES_LOCAL_PARAMS 16 /* parameters are declared using () */ -#define FUN_WITH_RETURN 32 /* there was RETURN statement in previous line */ +/* + * flags for bFlags member +*/ +#define FUN_STATEMENTS 1 /* Function have at least one executable statement */ +#define FUN_USES_STATICS 2 /* Function uses static variables */ +#define FUN_PROCEDURE 4 /* This is a procedure that shouldn't return value */ +#define FUN_ILLEGAL_INIT 8 /* Attempt to initialize static variable with a function call */ +#define FUN_USES_LOCAL_PARAMS 16 /* parameters are declared using () */ +#define FUN_WITH_RETURN 32 /* there was RETURN statement in previous line */ + +/* Support for aliased expressions + */ +typedef struct _ALIASID +{ + char type; + union { + int iAlias; + char * szAlias; + } alias; + struct _ALIASID * pPrev; +} ALIASID, *ALIASID_PTR; + +#define ALIAS_NUMBER 1 +#define ALIAS_NAME 2 +#define ALIAS_EVAL 3 + +typedef struct __EXTERN +{ + char * szName; + struct __EXTERN * pNext; +} _EXTERN, * PEXTERN; /* support structure for extern symbols */ +/* as they have to be placed on the symbol table later than the first public symbol */ + +typedef struct _LOOPEXIT +{ + ULONG ulOffset; + int iLine; + USHORT wSeqCounter; + struct _LOOPEXIT * pLoopList; + struct _LOOPEXIT * pExitList; + struct _LOOPEXIT * pNext; +} LOOPEXIT, * PTR_LOOPEXIT; /* support structure for EXIT and LOOP statements */ + + +typedef struct __ELSEIF +{ + ULONG ulOffset; + struct __ELSEIF * pNext; +} _ELSEIF, * PELSEIF; /* support structure for else if pcode fixups */ + +/* Support for parenthesized expressions + */ +typedef struct _EXPLIST +{ + BYTE * prevPCode; /* pcode buffer used at the start of expression */ + ULONG prevSize; + ULONG prevPos; + BYTE * exprPCode; /* pcode buffer for current expression */ + ULONG exprSize; + struct _EXPLIST *pPrev; /* previous expression in the list */ + struct _EXPLIST *pNext; /* next expression in the list */ +} EXPLIST, *EXPLIST_PTR; + +/* production related functions */ +void AliasAddInt( int ); +void AliasAddExp( void ); +void AliasAddStr( char * ); +void AliasPush( void ); +void AliasPop( void ); +void AliasSwap( void ); +void AliasAdd( ALIASID_PTR ); +void AliasRemove( void ); + +void ExpListPush( void ); /* pushes the new expression on the stack */ +void ExpListPop( int ); /* pops previous N expressions */ + +PFUNCTION hb_compAddFunCall( char * szFuntionName ); +void hb_compAddExtern( char * szExternName ); /* defines a new extern name */ +void hb_compAddVar( char * szVarName, char cType ); /* add a new param, local, static variable to a function definition or a public or private */ +PCOMSYMBOL hb_compAddSymbol( char *, USHORT * ); +void CheckDuplVars( PVAR pVars, char * szVarName, int iVarScope ); /*checks for duplicate variables definitions */ +void Dec( void ); /* generates the pcode to decrement the latest value on the virtual machine stack */ +void hb_compGenDoProc( BYTE bParams ); /* generates the pcode to execute a Clipper function discarding its result */ +void Duplicate( void ); /* duplicates the virtual machine latest stack latest value and places it on the stack */ +void DupPCode( ULONG ulStart ); /* duplicates the current generated pcode from an offset */ +void FieldPCode( BYTE , char * ); /* generates the pcode for database field */ +void FixElseIfs( void * pIfElseIfs ); /* implements the ElseIfs pcode fixups */ +void FixReturns( void ); /* fixes all last defined function returns jumps offsets */ +void Function( BYTE bParams ); /* generates the pcode to execute a Clipper function pushing its result */ +PFUNCTION FunctionNew( char *, char ); /* creates and initialises the _FUNC structure */ +void hb_compFunDef( char * szFunName, HB_SYMBOLSCOPE cScope, int iType ); /* starts a new Clipper language function definition */ +void GenArray( int iElements ); /* instructs the virtual machine to build an array and load elemnst from the stack */ +void hb_compGenBreak( void ); /* generate code for BREAK statement */ +void * GenElseIf( void * pFirstElseIf, ULONG ulOffset ); /* generates a support structure for elseifs pcode fixups */ +void hb_compGenExterns( void ); /* generates the symbols for the EXTERN names */ +void GenIfInline( void ); /* generates pcodes for IIF( expr1, expr2, expr3 ) */ +int GetFieldVarPos( char *, PFUNCTION ); /* return if passed name is a field variable */ +int GetMemvarPos( char *, PFUNCTION ); /* return if passed name is a memvar variable */ +USHORT GetVarPos( PVAR pVars, char * szVarName ); /* returns the order + 1 of a variable if defined or zero */ +int GetLocalVarPos( char * szVarName ); /* returns the order + 1 of a local variable */ +void Inc( void ); /* generates the pcode to increment the latest value on the virtual machine stack */ +ULONG hb_compGenJump( LONG lOffset ); /* generates the pcode to jump to a specific offset */ +ULONG hb_compGenJumpFalse( LONG lOffset ); /* generates the pcode to jump if false */ +void hb_compGenJumpHere( ULONG ulOffset ); /* returns the pcode pos where to set a jump offset */ +void hb_compGenJumpThere( ULONG ulFrom, ULONG ulTo ); /* sets a jump offset */ +ULONG hb_compGenJumpTrue( LONG lOffset ); /* generates the pcode to jump if true */ +void Line( void ); /* generates the pcode with the currently compiled source code line */ +void LineDebug( void ); /* generates the pcode with the currently compiled source code line */ +void LineBody( void ); /* generates the pcode with the currently compiled source code line */ +void VariablePCode( BYTE , char * ); /* generates the pcode for undeclared variable */ +void MemvarPCode( BYTE , char * ); /* generates the pcode for memvar variable */ +void hb_compGenMessage( char * szMsgName ); /* sends a message to an object */ +void hb_compGenMessageData( char * szMsg ); /* generates an underscore-symbol name for a data assignment */ +void hb_compGenPopVar( char * szVarName ); /* generates the pcode to pop a value from the virtual machine stack onto a variable */ +void hb_compGenPushDouble( double fNumber, BYTE bDec ); /* Pushes a number on the virtual machine stack */ +void hb_compGenPushFunCall( char * ); /* generates the pcode to push function's call */ +void hb_compGenPushVar( char * szVarName ); /* generates the pcode to push a variable value to the virtual machine stack */ +void hb_compGenPushVarRef( char * szVarName ); /* generates the pcode to push a variable by reference to the virtual machine stack */ +void hb_compGenPushInteger( int iNumber ); /* Pushes a integer number on the virtual machine stack */ +void hb_compGenPushLogical( int iTrueFalse ); /* pushes a logical value on the virtual machine stack */ +void hb_compGenPushLong( long lNumber ); /* Pushes a long number on the virtual machine stack */ +void hb_compGenPushNil( void ); /* Pushes nil on the virtual machine stack */ +void hb_compGenPushString( char * szText, ULONG ulLen ); /* Pushes a string on the virtual machine stack */ +void hb_compPushSymbol( char * szSymbolName, int iIsFunction ); /* Pushes a symbol on to the Virtual machine stack */ + +/* Codeblocks */ +void hb_compCodeBlockStart( void ); /* starts a codeblock creation */ +void hb_compCodeBlockEnd( void ); /* end of codeblock creation */ + + +void hb_compGenPushFunRef( char * ); + +void hb_compGenPCode1( BYTE ); /* generates 1 byte of pcode */ +void hb_compGenPCode3( BYTE, BYTE, BYTE ); /* generates 3 bytes of pcode */ +void hb_compGenPCodeN( BYTE * pBuffer, ULONG ulSize ); /* copy bytes to a pcode buffer */ + +ULONG SequenceBegin( void ); +ULONG SequenceEnd( void ); +void SequenceFinish( ULONG, int ); + +/* Managing value type */ +extern void ValTypePush( char cType ); /* Pushes the type of expression (used with -w3 option */ +extern void ValTypePop( int ); +extern void ValTypePlus( void ); +extern void ValTypeRelational( void ); +extern void ValTypeCheck( char, int, int ); +extern void ValTypeCheck2( char, int, int ); +extern char ValTypeGet( void ); +extern void ValTypePut( char ); +extern void ValTypeAssign( char * ); +extern void ValTypeReset( void ); + +/* support for FIELD declaration */ +void FieldsSetAlias( char *, int ); +int FieldsCount( void ); + +/* Static variables */ +void hb_compStaticDefStart( void ); +void hb_compStaticDefEnd( void ); + +HB_EXPR_PTR hb_compErrorStatic( char *, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compErrorType( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compErrorIndex( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compErrorSyntax( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compErrorLValue( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compErrorBound( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compErrorAlias( HB_EXPR_PTR ); +void hb_compErrorDuplVar( char * ); +HB_EXPR_PTR hb_compWarnMeaningless( HB_EXPR_PTR ); + +void hb_compCheckArgs( char *, int ); + +void hb_compGenError( char* _szErrors[], char cPrefix, int iError, char * szError1, char * szError2 ); +void hb_compGenWarning( char* _szWarnings[], char cPrefix, int iWarning, char * szWarning1, char * szWarning2); + +/* variable used by compiler + */ +extern FUNCTIONS hb_comp_functions, hb_comp_funcalls; +extern SYMBOLS hb_comp_symbols; +extern PATHNAMES * hb_comp_pIncludePath; +extern PFUNCTION hb_comp_pInitFunc; +extern PHB_FNAME hb_comp_pFileName; +extern BOOL hb_comp_bStartProc; +extern BOOL hb_comp_bLineNumbers; +extern BOOL hb_comp_bQuiet; +extern BOOL hb_comp_bRestrictSymbolLength; +extern BOOL hb_comp_bShortCuts; +extern int hb_comp_iWarnings; +extern BOOL hb_comp_bAnyWarning; +extern BOOL hb_comp_bAutoMemvarAssume; +extern BOOL hb_comp_bForceMemvars; +extern BOOL hb_comp_bDebugInfo; +extern char hb_comp_szPrefix[ 20 ]; +extern BOOL hb_comp_bGenCVerbose; +extern int hb_comp_iExitLevel; +extern int hb_comp_iFunctionCnt; +extern BOOL hb_comp_bExternal; +extern char hb_comp_cVarType; +extern int hb_comp_iVarScope; +extern BOOL hb_comp_bDontGenLineNum; +extern FILES hb_comp_files; +extern int hb_comp_iStaticCnt; +extern int hb_comp_iErrorCount; +extern PTR_LOOPEXIT hb_comp_pLoops; + +extern USHORT hb_comp_wSeqCounter; +extern USHORT hb_comp_wForCounter; +extern USHORT hb_comp_wIfCounter; +extern USHORT hb_comp_wWhileCounter; +extern USHORT hb_comp_wCaseCounter; + +extern char * hb_comp_szCErrors[]; +extern char * hb_comp_szCWarnings[]; + + +HB_EXPR_PTR hb_compExprNewEmpty( void ); +HB_EXPR_PTR hb_compExprNewNil( void ); +HB_EXPR_PTR hb_compExprNewDouble( double, unsigned char ); +HB_EXPR_PTR hb_compExprNewLong( LONG ); +HB_EXPR_PTR hb_compExprNewString( char * ); +HB_EXPR_PTR hb_compExprNewLogical( int ); +HB_EXPR_PTR hb_compExprNewSelf( void ); +HB_EXPR_PTR hb_compExprNewCodeBlock( void ); +HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewVar( char * ); +HB_EXPR_PTR hb_compExprNewAliasVar( HB_EXPR_PTR, char * ); +HB_EXPR_PTR hb_compExprNewAliasExpr( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewSymbol( char * ); +HB_EXPR_PTR hb_compExprNewEQ( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewNE( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewLT( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewLE( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewGT( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewGE( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewIN( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewPlus( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewMinus( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewMult( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewDiv( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewMod( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewPower( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewAssign( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewEqual( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewPlusEq( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewMinusEq( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewMultEq( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewDivEq( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewModEq( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewExpEq( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewPostInc( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewPostDec( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewPreInc( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewPreDec( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewAnd( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewOr( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewNot( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewNegate( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewMacro( HB_EXPR_PTR, char * ); +HB_EXPR_PTR hb_compExprNewVarRef( char * ); +HB_EXPR_PTR hb_compExprNewFunRef( char * ); +HB_EXPR_PTR hb_compExprNewCodeblockExpr( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewFunCall( char *, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewFunCallArg( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewSend( HB_EXPR_PTR, char * ); +HB_EXPR_PTR hb_compExprNewMethodCall( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewList( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewArgList( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprAddListExpr( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewIIF( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprReduce( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprAssign( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprAssignStatic( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR ); +ULONG hb_compExprListLen( HB_EXPR_PTR ); +void hb_compExprDelete( HB_EXPR_PTR ); +char * hb_compExprDescription( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR, char *, BYTE ); #endif /* HB_COMPILER_H_ */ diff --git a/harbour/include/hberrors.h b/harbour/include/hberrors.h index a6e830fd62..3e29ea41a4 100644 --- a/harbour/include/hberrors.h +++ b/harbour/include/hberrors.h @@ -76,7 +76,10 @@ #define ERR_BADPARAM 35 #define ERR_BADFILENAME 36 #define ERR_MAYHEM_IN_CASE 37 -#define ERR_ALIASEXP 38 +#define ERR_INVALID_TYPE 38 +#define ERR_INVALID_ALIAS 39 +#define ERR_INVALID_INDEX 40 +#define ERR_INVALID_BOUND 41 #define WARN_AMBIGUOUS_VAR 1 #define WARN_MEMVAR_ASSUMED 2 @@ -93,6 +96,7 @@ #define WARN_OPERAND_SUSPECT 13 #define WARN_LOGICAL_SUSPECT 14 #define WARN_NUMERIC_SUSPECT 15 +#define WARN_MEANINGLESS 16 /* * Errors generated by Harbour preprocessor @@ -113,7 +117,7 @@ #define WARN_NONDIRECTIVE 1 -extern void GenError( char * _szErrors[], char, int, char *, char * ); /* generic parsing error management function */ -extern void GenWarning( char * _szWarnings[], char, int, char *, char * ); /* generic parsing warning management function */ +extern void hb_compGenError( char * _szErrors[], char, int, char *, char * ); /* generic parsing error management function */ +extern void hb_compGenWarning( char * _szWarnings[], char, int, char *, char * ); /* generic parsing warning management function */ #endif /* HB_ERRORS_H_ */ diff --git a/harbour/include/hbpp.h b/harbour/include/hbpp.h index 005627efa3..2dc3ccd49a 100644 --- a/harbour/include/hbpp.h +++ b/harbour/include/hbpp.h @@ -111,10 +111,10 @@ extern void hb_xfree( void * pMem ); /* frees memory */ /* Needed support variables, but not contained in HBPP.C */ -extern PATHNAMES * _pIncludePath; -extern PHB_FNAME _pFileName; extern DEFINES * topDefine; extern COMMANDS * topCommand; extern COMMANDS * topTranslate; +#include "compiler.h" + #endif /* HB_PP_H_ */ diff --git a/harbour/include/pcode.h b/harbour/include/pcode.h index eb07839c64..3d6e64e968 100644 --- a/harbour/include/pcode.h +++ b/harbour/include/pcode.h @@ -39,8 +39,8 @@ typedef enum { HB_P_AND, /* peforms the logical AND of two latest stack values, removes them and places result */ - HB_P_ARRAYAT, /* places on the virtual machine stack an array element */ - HB_P_ARRAYPUT, /* sets array element, the array and the index are both on the stack */ + HB_P_ARRAYPUSH, /* places on the virtual machine stack an array element */ + HB_P_ARRAYPOP, /* pops a value from the eval stack into an array element */ HB_P_ARRAYDIM, /* instructs the virtual machine to build an array with some specific dimensions */ HB_P_ARRAYGEN, /* instructs the virtual machine to build an array and load elemnst from the stack */ HB_P_EQUAL, /* check if the latest two values on the stack are equal, removing them and leaving there the result */ diff --git a/harbour/source/compiler/expropt.c b/harbour/source/compiler/expropt.c index b0d3a5fbec..79c5e062f0 100644 --- a/harbour/source/compiler/expropt.c +++ b/harbour/source/compiler/expropt.c @@ -6,7 +6,7 @@ * Harbour Project source code: * Compiler Expression Optimizer * - * Copyright 1999 Ron Pinkas + * Copyright 1999 Ryszard Glab * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -33,258 +33,4965 @@ * */ -#include -#include -#include -#include "extend.h" +/* TODO: + * Correct post- and pre- operations to correctly handle the following code + * a[ i++ ]++ + * Notice: in current implementation (an in Clipper too) 'i++' is evaluated + * two times! This causes that the new value (after incrementation) is + * stored in next element of the array. + */ + #include "compiler.h" -#include "hberrors.h" -extern int _iWarnings; -extern char * _szCWarnings[]; +/* memory allocation + */ +#define HB_XGRAB( size ) hb_xgrab( (size) ) +#define HB_XFREE( pPtr ) hb_xfree( (void *)(pPtr) ) -typedef struct + +/* Definitions of function templates used in expression's message + * handling + */ +#define HB_EXPR_FUNC( proc ) HB_EXPR_PTR proc( HB_EXPR_PTR pSelf, int iMessage ) +typedef HB_EXPR_FUNC( HB_EXPR_FUNC_ ); +typedef HB_EXPR_FUNC_ *HB_EXPR_FUNC_PTR; +#define HB_EXPR_USE( pSelf, iMessage ) \ + s_ExprTable[ (pSelf)->ExprType ]( (pSelf), (iMessage) ) + +typedef HB_EXPR_PTR HB_EXPR_ACTION( HB_EXPR_PTR pSelf, int iMessage ); + +/* This structure holds local variables declared in a codeblock + */ +typedef struct HB_CBVAR_ { - char cType; -} -STACK_VAL_TYPE, * PSTACK_VAL_TYPE; + char * szName; + BYTE bType; + struct HB_CBVAR_ * pNext; +} HB_CBVAR, *HB_CBVAR_PTR; +/* value types seen at language level + */ +#define HB_EV_UNKNOWN 0 +#define HB_EV_NIL 1 +#define HB_EV_NUMERIC 2 +#define HB_EV_STRING 4 +#define HB_EV_CODEBLOCK 8 +#define HB_EV_LOGICAL 16 +#define HB_EV_OBJECT 32 +#define HB_EV_ARRAY 64 +#define HB_EV_SYMBOL 128 +#define HB_EV_VARREF 256 +#define HB_EV_FUNREF 512 -static PSTACK_VAL_TYPE pStackValType = NULL; /* compile time stack values linked list */ -static long lStackTop = 0; -static long lStackLen; - -#define debug_msg2( x, y ) -#define debug_msg( x ) - - -void ValTypePush( char cType ) +/* messages sent to expressions + */ +typedef enum { - if( _iWarnings ) - { - if( pStackValType == NULL ) - { - lStackTop = 1; /* start from the one */ - lStackLen = 64; - pStackValType = ( PSTACK_VAL_TYPE ) hb_xgrab( sizeof( STACK_VAL_TYPE ) * lStackLen ); - } - else if( lStackTop == lStackLen ) - { - lStackLen += 64; - pStackValType = ( PSTACK_VAL_TYPE ) hb_xrealloc( pStackValType, sizeof( STACK_VAL_TYPE ) * lStackLen ); - } + HB_EA_REDUCE = 0, /* reduce the expression into optimized one */ + HB_EA_ARRAY_AT, /* check if the expession can be used as array */ + HB_EA_ARRAY_INDEX, /* check if the expession can be used as index */ + HB_EA_LVALUE, /* check if the expression can be used as lvalue (left side of an assigment) */ + HB_EA_PUSH_PCODE, /* generate the pcodes to push the value of expression */ + HB_EA_POP_PCODE, /* generate the pcodes to pop the value of expression */ + HB_EA_PUSH_POP, /* generate the pcodes to push and pop the expression */ + HB_EA_STATEMENT, /* generate the pcodes for a statement */ + HB_EA_DELETE /* delete components of the expression */ +} HB_EXPR_MESSAGE; - pStackValType[ lStackTop++ ].cType = cType; +/* additional definitions used to distinguish numeric expressions + */ +#define HB_ET_LONG 1 +#define HB_ET_DOUBLE 2 - debug_msg2( "\nValTypePush( %c )", cType ); - } +/* types of expressions + * NOTE: the order of these definition is important - change it carefully + * All types <= HB_ET_FUNREF are constant values + * All types <= HB_ET_VARIABLE are a simple values + * All types > HB_ET_VARIABLE are operators + */ +typedef enum +{ + HB_ET_NONE = 0, + HB_ET_NIL, + HB_ET_NUMERIC, + HB_ET_STRING, + HB_ET_CODEBLOCK, + HB_ET_LOGICAL, + HB_ET_SELF, + HB_ET_ARRAY, + HB_ET_VARREF, + HB_ET_FUNREF, + HB_ET_IIF, + HB_ET_LIST, + HB_ET_ARGLIST, + HB_ET_ARRAYAT, + HB_ET_MACRO, + HB_ET_FUNCALL, + HB_ET_ALIASVAR, + HB_ET_ALIASEXPR, + HB_ET_SEND, + HB_ET_SYMBOL, + HB_ET_VARIABLE, + HB_EO_POSTINC, /* post-operators -> lowest precedence */ + HB_EO_POSTDEC, + HB_EO_ASSIGN, /* assigments */ + HB_EO_PLUSEQ, + HB_EO_MINUSEQ, + HB_EO_MULTEQ, + HB_EO_DIVEQ, + HB_EO_MODEQ, + HB_EO_EXPEQ, + HB_EO_OR, /* logical operators */ + HB_EO_AND, + HB_EO_NOT, + HB_EO_EQUAL, /* relational operators */ + HB_EO_EQ, + HB_EO_LT, + HB_EO_GT, + HB_EO_LE, + HB_EO_GE, + HB_EO_NE, + HB_EO_IN, + HB_EO_PLUS, /* addition */ + HB_EO_MINUS, + HB_EO_MULT, /* multiple */ + HB_EO_DIV, + HB_EO_MOD, + HB_EO_POWER, + HB_EO_NEGATE, /* sign operator */ + HB_EO_PREINC, + HB_EO_PREDEC /* pre-operators -> the highest precedence */ +} HB_EXPR_OPERATOR; + +/* forward declaration of callback functions + */ +static HB_EXPR_FUNC( hb_compExprUseDummy ); +static HB_EXPR_FUNC( hb_compExprUseNil ); +static HB_EXPR_FUNC( hb_compExprUseNumeric ); +static HB_EXPR_FUNC( hb_compExprUseString ); +static HB_EXPR_FUNC( hb_compExprUseCodeblock ); +static HB_EXPR_FUNC( hb_compExprUseLogical ); +static HB_EXPR_FUNC( hb_compExprUseSelf ); +static HB_EXPR_FUNC( hb_compExprUseArray ); +static HB_EXPR_FUNC( hb_compExprUseVarRef ); +static HB_EXPR_FUNC( hb_compExprUseFunRef ); +static HB_EXPR_FUNC( hb_compExprUseIIF ); +static HB_EXPR_FUNC( hb_compExprUseList ); +static HB_EXPR_FUNC( hb_compExprUseArgList ); +static HB_EXPR_FUNC( hb_compExprUseArrayAt ); +static HB_EXPR_FUNC( hb_compExprUseMacro ); +static HB_EXPR_FUNC( hb_compExprUseFunCall ); +static HB_EXPR_FUNC( hb_compExprUseAliasVar ); +static HB_EXPR_FUNC( hb_compExprUseAliasExpr ); +static HB_EXPR_FUNC( hb_compExprUseSend ); +static HB_EXPR_FUNC( hb_compExprUseSymbol ); +static HB_EXPR_FUNC( hb_compExprUseVariable ); +static HB_EXPR_FUNC( hb_compExprUseAssign ); +static HB_EXPR_FUNC( hb_compExprUseEqual ); +static HB_EXPR_FUNC( hb_compExprUsePlus ); +static HB_EXPR_FUNC( hb_compExprUseMinus ); +static HB_EXPR_FUNC( hb_compExprUseMult ); +static HB_EXPR_FUNC( hb_compExprUseDiv ); +static HB_EXPR_FUNC( hb_compExprUseMod ); +static HB_EXPR_FUNC( hb_compExprUsePower ); +static HB_EXPR_FUNC( hb_compExprUsePostInc ); +static HB_EXPR_FUNC( hb_compExprUsePostDec ); +static HB_EXPR_FUNC( hb_compExprUsePreInc ); +static HB_EXPR_FUNC( hb_compExprUsePreDec ); +static HB_EXPR_FUNC( hb_compExprUsePlusEq ); +static HB_EXPR_FUNC( hb_compExprUseMinusEq ); +static HB_EXPR_FUNC( hb_compExprUseMultEq ); +static HB_EXPR_FUNC( hb_compExprUseDivEq ); +static HB_EXPR_FUNC( hb_compExprUseModEq ); +static HB_EXPR_FUNC( hb_compExprUseExpEq ); +static HB_EXPR_FUNC( hb_compExprUseAnd ); +static HB_EXPR_FUNC( hb_compExprUseOr ); +static HB_EXPR_FUNC( hb_compExprUseNot ); +static HB_EXPR_FUNC( hb_compExprUseEQ ); +static HB_EXPR_FUNC( hb_compExprUseLT ); +static HB_EXPR_FUNC( hb_compExprUseGT ); +static HB_EXPR_FUNC( hb_compExprUseLE ); +static HB_EXPR_FUNC( hb_compExprUseGE ); +static HB_EXPR_FUNC( hb_compExprUseNE ); +static HB_EXPR_FUNC( hb_compExprUseIN ); +static HB_EXPR_FUNC( hb_compExprUseNegate ); + +static HB_EXPR_FUNC_PTR s_ExprTable[] = { + hb_compExprUseDummy, + hb_compExprUseNil, + hb_compExprUseNumeric, + hb_compExprUseString, + hb_compExprUseCodeblock, + hb_compExprUseLogical, + hb_compExprUseSelf, + hb_compExprUseArray, + hb_compExprUseVarRef, + hb_compExprUseFunRef, + hb_compExprUseIIF, + hb_compExprUseList, + hb_compExprUseArgList, + hb_compExprUseArrayAt, + hb_compExprUseMacro, + hb_compExprUseFunCall, + hb_compExprUseAliasVar, + hb_compExprUseAliasExpr, + hb_compExprUseSend, + hb_compExprUseSymbol, + hb_compExprUseVariable, + hb_compExprUsePostInc, /* post-operators -> lowest precedence */ + hb_compExprUsePostDec, + hb_compExprUseAssign, /* assigments */ + hb_compExprUsePlusEq, + hb_compExprUseMinusEq, + hb_compExprUseMultEq, + hb_compExprUseDivEq, + hb_compExprUseModEq, + hb_compExprUseExpEq, + hb_compExprUseOr, /* logical operators */ + hb_compExprUseAnd, + hb_compExprUseNot, + hb_compExprUseEqual, /* relational operators */ + hb_compExprUseEQ, + hb_compExprUseLT, + hb_compExprUseGT, + hb_compExprUseLE, + hb_compExprUseGE, + hb_compExprUseNE, + hb_compExprUseIN, + hb_compExprUsePlus, /* addition */ + hb_compExprUseMinus, + hb_compExprUseMult, /* multiple */ + hb_compExprUseDiv, + hb_compExprUseMod, + hb_compExprUsePower, + hb_compExprUseNegate, /* sign operator */ + hb_compExprUsePreInc, + hb_compExprUsePreDec /* highest precedence */ +}; + +/* Table with operators precedence + * NOTE: + * HB_ET_NIL is used for an ordinary values and post- operators + * HB_ET_NONE is used for invalid syntax, e.g. var := var1 += 2 + */ +static unsigned char s_PrecedTable[] = { + HB_ET_NIL, /* HB_ET_NONE = 0, */ + HB_ET_NIL, /* HB_ET_NIL, */ + HB_ET_NIL, /* HB_ET_NUMERIC, */ + HB_ET_NIL, /* HB_ET_STRING, */ + HB_ET_NIL, /* HB_ET_CODEBLOCK, */ + HB_ET_NIL, /* HB_ET_LOGICAL, */ + HB_ET_NIL, /* HB_ET_SELF, */ + HB_ET_NIL, /* HB_ET_ARRAY, */ + HB_ET_NIL, /* HB_ET_VARREF, */ + HB_ET_NIL, /* HB_ET_FUNREF, */ + HB_ET_NIL, /* HB_ET_IIF, */ + HB_ET_NIL, /* HB_ET_LIST, */ + HB_ET_NIL, /* HB_ET_ARGLIST, */ + HB_ET_NIL, /* HB_ET_ARRAYAT, */ + HB_ET_NIL, /* HB_ET_MACRO, */ + HB_ET_NIL, /* HB_ET_FUNCALL, */ + HB_ET_NIL, /* HB_ET_ALIASVAR, */ + HB_ET_NIL, /* HB_ET_ALIASEXPR, */ + HB_ET_NIL, /* HB_ET_SEND, */ + HB_ET_NIL, /* HB_ET_SYMBOL, */ + HB_ET_NIL, /* HB_ET_VARIABLE, */ + HB_ET_NIL, /* HB_EO_POSTINC, post-operators */ + HB_ET_NIL, /* HB_EO_POSTDEC, */ + HB_ET_NONE, /* HB_EO_ASSIGN, assigments */ + HB_ET_NONE, /* HB_EO_PLUSEQ, Invalid syntax */ + HB_ET_NONE, /* HB_EO_MINUSEQ, */ + HB_ET_NONE, /* HB_EO_MULTEQ, */ + HB_ET_NONE, /* HB_EO_DIVEQ, */ + HB_ET_NONE, /* HB_EO_MODEQ, */ + HB_ET_NONE, /* HB_EO_EXPEQ, */ + HB_EO_OR, /* HB_EO_OR, logical operators */ + HB_EO_AND, /* HB_EO_AND, */ + HB_ET_NIL, /* HB_EO_NOT, */ + HB_EO_EQUAL, /* HB_EO_EQUAL, relational operators */ + HB_EO_EQUAL, /* HB_EO_EQ, */ + HB_EO_EQUAL, /* HB_EO_LT, */ + HB_EO_EQUAL, /* HB_EO_GT, */ + HB_EO_EQUAL, /* HB_EO_LE, */ + HB_EO_EQUAL, /* HB_EO_GE, */ + HB_EO_EQUAL, /* HB_EO_NE, */ + HB_EO_EQUAL, /* HB_EO_IN, */ + HB_EO_PLUS, /* HB_EO_PLUS, addition */ + HB_EO_PLUS, /* HB_EO_MINUS, */ + HB_EO_MULT, /* HB_EO_MULT, multiple */ + HB_EO_MULT, /* HB_EO_DIV, */ + HB_EO_MULT, /* HB_EO_MOD, */ + HB_EO_POWER, /* HB_EO_POWER, */ + HB_ET_NIL, /* HB_EO_NEGATE, sign operator */ + HB_ET_NIL, /* HB_EO_PREINC, */ + HB_ET_NIL /* HB_EO_PREDEC, pre-operators */ +}; + +static char * s_OperTable[] = { + "", + "NIL", + "Numeric", + "String", + "Codeblock", + "Logical", + "SELF", + "Array", + "@", + "@", + "IIF", + ",", + ",", + "[", + "&", + "()", + "->", + "->", + ":", + "", + "", + "++", /* post-operators -> lowest precedence */ + "--", + ":=", /* assigments */ + "+=", + "-=", + "*=", + "/=", + "%=", + "^=", + ".OR.", /* logical operators */ + ".AND.", + ".NOT.", + "=", /* relational operators */ + "==", + "<", + ">", + "<=", + ">=", + "!=", + "$", + "+", /* addition */ + "-", + "*", /* multiple */ + "/", + "%", + "^", + "-", /* sign operator */ + "++", + "--" +}; + +/* Forward declarations + */ +static void hb_compExprDelOperator( HB_EXPR_PTR ); + +static ULONG hb_compExprListReduce( HB_EXPR_PTR ); +static void hb_compExprPushOperEq( HB_EXPR_PTR, BYTE ); +static void hb_compExprUseOperEq( HB_EXPR_PTR, BYTE ); +static void hb_compExprPushPreOp( HB_EXPR_PTR, BYTE ); +static void hb_compExprPushPostOp( HB_EXPR_PTR, BYTE ); +static void hb_compExprUsePreOp( HB_EXPR_PTR, BYTE ); + +static HB_CBVAR_PTR hb_compExprCBVarNew( char *, BYTE ); +static void hb_compExprCBVarDel( HB_CBVAR_PTR ); + +/* ************************************************************************ */ + +HB_EXPR_PTR hb_compExprNew( int iType ) +{ + HB_EXPR_PTR pExpr = ( HB_EXPR_PTR ) HB_XGRAB( sizeof( HB_EXPR ) ); + + pExpr->ExprType = iType; + pExpr->pNext = NULL; + pExpr->ValType = HB_EV_UNKNOWN; + + return pExpr; } -void ValTypePop( int iCount ) +void hb_compExprDelete( HB_EXPR_PTR pExpr ) { - if( _iWarnings ) - { - debug_msg2( "\nValTypePop( %i )", iCount ); - if( lStackTop ) - { - while( lStackTop && iCount-- ) - --lStackTop; - } - else - debug_msg( "\nValTypePop() Compile time stack underflow\n"); - } + HB_EXPR_USE( pExpr, HB_EA_DELETE ); + HB_XFREE( pExpr ); } -void ValTypePlus( void ) +char * hb_compExprDescription( HB_EXPR_PTR pExpr ) { - if( _iWarnings ) + if( pExpr ) + return s_OperTable[ pExpr->ExprType ]; + else + return s_OperTable[ 0 ]; +} + +HB_EXPR_PTR hb_compExprNewEmpty( void ) +{ + return hb_compExprNew( HB_ET_NONE ); +} + +HB_EXPR_PTR hb_compExprNewDouble( double dValue, unsigned char ucDec ) +{ + HB_EXPR_PTR pExpr =hb_compExprNew( HB_ET_NUMERIC ); + + pExpr->value.asNum.dVal = dValue; + pExpr->value.asNum.bDec = ucDec; + pExpr->value.asNum.NumType = HB_ET_DOUBLE; + pExpr->ValType = HB_EV_NUMERIC; + + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewLong( long lValue ) +{ + HB_EXPR_PTR pExpr =hb_compExprNew( HB_ET_NUMERIC ); + + pExpr->value.asNum.lVal = lValue; + pExpr->value.asNum.bDec = 0; + pExpr->value.asNum.NumType = HB_ET_LONG; + pExpr->ValType = HB_EV_NUMERIC; + + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewString( char *szValue ) +{ + HB_EXPR_PTR pExpr =hb_compExprNew( HB_ET_STRING ); + + pExpr->value.asString = szValue; + pExpr->ulLength = strlen( szValue ); + pExpr->ValType = HB_EV_STRING; + + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewCodeBlock( void ) +{ + HB_EXPR_PTR pExpr =hb_compExprNew( HB_ET_CODEBLOCK ); + + pExpr->value.asList.pExprList = NULL; + pExpr->value.asList.pIndex = NULL; /* this will hold local variables declarations */ + pExpr->ValType = HB_EV_CODEBLOCK; + + return pExpr; +} + +/* Add a new local variable declaration + */ +HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, BYTE bType ) +{ + HB_CBVAR_PTR pVar; + + if( pCB->value.asList.pIndex ) { - debug_msg( "\nValTypePlus()" ); - - if( lStackTop > 2 ) /* at least two expressions are required */ + /* add it to the end of the list + */ + pVar = ( HB_CBVAR_PTR ) pCB->value.asList.pIndex; + while( pVar ) { - PSTACK_VAL_TYPE pOperand1 = NULL, pOperand2; - char sType1[ 2 ], sType2[ 2 ], cType = ' '; + if( strcmp( szVarName, pVar->szName ) == 0 ) + hb_compErrorDuplVar( szVarName ); - --lStackTop; - pOperand2 = pStackValType + lStackTop; - sType2[ 0 ] = pOperand2->cType; - sType2[ 1 ] = '\0'; - - /* skip back to the 1st. operand */ - pOperand1 = pStackValType + lStackTop - 1; - sType1[ 0 ] = pOperand1->cType; - sType1[ 1 ] = '\0'; - - /* TODO: Adding numerical to date - * - */ - if( pOperand1->cType != ' ' && pOperand2->cType != ' ' && pOperand1->cType != pOperand2->cType ) - GenWarning( _szCWarnings, 'W', WARN_OPERANDS_INCOMPATBLE, sType1, sType2 ); - else if( pOperand2->cType != ' ' && pOperand1->cType == ' ' ) - GenWarning( _szCWarnings, 'W', WARN_OPERAND_SUSPECT, sType2, NULL ); - else if( pOperand1->cType != ' ' && pOperand2->cType == ' ' ) - GenWarning( _szCWarnings, 'W', WARN_OPERAND_SUSPECT, sType1, NULL ); + if( pVar->pNext ) + pVar = pVar->pNext; else - cType = pOperand1->cType; - - /* compile time 1st. operand has to be released *but* result will be pushed and type as calculated */ - pOperand1->cType = cType; - } - else - debug_msg( " Compile time stack underflow" ); - } -} - -void ValTypeRelational( void ) -{ - if( _iWarnings ) - { - debug_msg( "\nValTypeRelational()" ); - - if( lStackTop > 2 ) /* at least two expressions are required */ - { - PSTACK_VAL_TYPE pOperand1 = NULL, pOperand2; - char sType1[ 2 ], sType2[ 2 ]; - - /* 2nd. Operand (stack top)*/ - --lStackTop; - pOperand2 = pStackValType + lStackTop; - sType2[ 0 ] = pOperand2->cType; - sType2[ 1 ] = '\0'; - - /* skip back to the 1st. operand */ - pOperand1 = pStackValType + lStackTop - 1; - sType1[ 0 ] = pOperand1->cType; - sType1[ 1 ] = '\0'; - - if( pOperand1->cType != ' ' && pOperand2->cType != ' ' && pOperand1->cType != pOperand2->cType ) - GenWarning( _szCWarnings, 'W', WARN_OPERANDS_INCOMPATBLE, sType1, sType2 ); - else if( pOperand2->cType != ' ' && pOperand1->cType == ' ' ) - GenWarning( _szCWarnings, 'W', WARN_OPERAND_SUSPECT, sType2, NULL ); - else if( pOperand1->cType != ' ' && pOperand2->cType == ' ' ) - GenWarning( _szCWarnings, 'W', WARN_OPERAND_SUSPECT, sType1, NULL ); - - /* compile time 1st. operand has to be released *but* result will be pushed and of type logical */ - pOperand1->cType = 'L'; - } - else - debug_msg( " Compile time stack underflow" ); - } -} - -void ValTypeCheck( char cExpected, int iExpWarning, int iSuspWarning ) -{ - if( _iWarnings ) - { - if( lStackTop ) - { - if( pStackValType[ lStackTop - 1 ].cType == ' ' ) - GenWarning( _szCWarnings, 'W', iSuspWarning, NULL, NULL ); - else if( pStackValType[ lStackTop -1 ].cType != cExpected ) { - char sType[ 2 ]; - - sType[ 0 ] = pStackValType[ lStackTop -1 ].cType; - sType[ 1 ] = '\0'; - - GenWarning( _szCWarnings, 'W', iExpWarning, sType, NULL ); + pVar->pNext = hb_compExprCBVarNew( szVarName, bType ); + pVar = NULL; } } - else - debug_msg2( "\nValTypeCheck( %c ) Compile time stack underflow", cExpected ); } + else + pCB->value.asList.pIndex = ( HB_EXPR_PTR ) hb_compExprCBVarNew( szVarName, bType ); + + return pCB; } -void ValTypeCheck2( char cExpected, int iExpWarning, int iSuspWarning ) +HB_EXPR_PTR hb_compExprNewLogical( int iValue ) { - if( _iWarnings ) + HB_EXPR_PTR pExpr =hb_compExprNew( HB_ET_LOGICAL ); + + pExpr->value.asLogical = iValue; + pExpr->ValType = HB_EV_LOGICAL; + + return pExpr; +} + + +HB_EXPR_PTR hb_compExprNewNil( void ) +{ + HB_EXPR_PTR pExpr =hb_compExprNew( HB_ET_NIL ); + + pExpr->ValType = HB_EV_NIL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewSelf( void ) +{ + HB_EXPR_PTR pExpr =hb_compExprNew( HB_ET_SELF ); + + pExpr->ValType = HB_EV_OBJECT; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewVarRef( char * szVarName ) +{ + HB_EXPR_PTR pExpr =hb_compExprNew( HB_ET_VARREF ); + + pExpr->value.asSymbol = szVarName; + pExpr->ValType = HB_EV_VARREF; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewFunRef( char * szFunName ) +{ + HB_EXPR_PTR pExpr =hb_compExprNew( HB_ET_FUNREF ); + + pExpr->value.asSymbol = szFunName; + pExpr->ValType = HB_EV_FUNREF; + return pExpr; +} + +/* Create a new IIF() expression or set arguments + * + * pIIF is a list of three expressions + */ +HB_EXPR_PTR hb_compExprNewIIF( HB_EXPR_PTR pExpr ) +{ + HB_EXPR_PTR pTmp; + + pExpr->ExprType = HB_ET_IIF; + + pTmp = pExpr->value.asList.pExprList; /* get first expression */ + if( pTmp->ExprType == HB_ET_NONE ) { - debug_msg2( "\nValTypeCheck2( %c )", cExpected ); + /* there is no conditional expression e.g. IIF( , true, false ) + */ + hb_compErrorSyntax( pExpr ); + } + return pExpr; +} - if( lStackTop > 2 ) /* at least two expressions are required */ +/* Create function call + */ +HB_EXPR_PTR hb_compExprNewFunCall( char *szFunName, HB_EXPR_PTR pParms ) +{ + HB_EXPR_PTR pExpr = NULL; + int iCount; + + iCount = hb_compExprListLen( pParms ); + /* Check the special case when no parameters are passed - in this case + * pParms is an expression of type HB_ET_NONE and we shouldn't + * replace it with NIL value + */ + if( iCount == 1 && pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) + --iCount; + hb_compCheckArgs( szFunName, iCount ); + if( ( strcmp( "CHR", szFunName ) == 0 ) && iCount ) + { + /* try to change it into a string */ + HB_EXPR_PTR pArg = pParms->value.asList.pExprList; + + if( pArg->ExprType == HB_ET_NUMERIC ) { - PSTACK_VAL_TYPE pOperand1 = NULL, pOperand2; - char sType1[ 2 ], sType2[ 2 ]; + pExpr = hb_compExprNew( HB_ET_STRING ); + pExpr->ulLength = 1; + pExpr->ValType = HB_EV_STRING; + pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); + if( pArg->value.asNum.NumType == HB_ET_LONG ) + pExpr->value.asString[ 0 ] = ( pArg->value.asNum.lVal % 256 ); + else + pExpr->value.asString[ 0 ] = ( (long) pArg->value.asNum.dVal % 256 ); + pExpr->value.asString[ 1 ] = '\x0'; + hb_compExprDelete( pParms ); + } + } + if( pExpr == NULL ) + { + pExpr = hb_compExprNew( HB_ET_FUNCALL ); + pExpr->value.asFunCall.pParms = pParms; + pExpr->value.asFunCall.szFunName = szFunName; + } - /* 2nd. Operand (stack top)*/ - pOperand2 = pStackValType + lStackTop - 1; - sType2[ 0 ] = pOperand2->cType; - sType2[ 1 ] = '\0'; + return pExpr; +} - /* skip back to the 1st. operand */ - pOperand1 = pStackValType + lStackTop - 2; - sType1[ 0 ] = pOperand1->cType; - sType1[ 1 ] = '\0'; +/* Creates a new literal array { item1, item2, ... itemN } + * 'pArrList' is a list of array elements + */ +HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR pArrList ) +{ + HB_EXPR_PTR pExpr; - if( pOperand1->cType != cExpected && pOperand1->cType != ' ' ) - GenWarning( _szCWarnings, 'W', iExpWarning, sType1, NULL ); - else if( pOperand1->cType == ' ' ) - GenWarning( _szCWarnings, 'W', iSuspWarning, NULL, NULL ); + pArrList->ExprType = HB_ET_ARRAY; /* change type from ET_LIST */ + pArrList->ValType = HB_EV_ARRAY; + pArrList->ulLength = 0; - if( pOperand2->cType != cExpected && pOperand2->cType != ' ' ) - GenWarning( _szCWarnings, 'W', iExpWarning, sType2, NULL ); - else if( pOperand2->cType == ' ' ) - GenWarning( _szCWarnings, 'W', iSuspWarning, NULL, NULL ); + pExpr = pArrList->value.asList.pExprList; /* get first element on the list */ + /* Now we need to replace all EO_NONE expressions with ET_NIL expressions + * If EO_NONE is the first expression and there is no more expressions + * then it is an empty array {} and ET_NIL cannot be used + */ + if( pExpr->ExprType == HB_ET_NONE && pExpr->pNext == NULL ) + { + hb_compExprDelete( pExpr ); /* delete EO_NONE expresssion */ + pArrList->value.asList.pExprList = NULL; + } + else + { + /* there are at least one non-empty element specified + */ + while( pExpr ) + { + /* if empty element was specified replace it with NIL value */ + if( pExpr->ExprType == HB_ET_NONE ) + pExpr->ExprType = HB_ET_NIL; + pExpr = pExpr->pNext; + ++pArrList->ulLength; + } + } + pArrList->value.asList.pIndex = NULL; + return pArrList; +} + +/* Creates new array access expression + * pArray[ pIndex ] + * NOTE: In case of multiple indexes it is called recursively + * array[ idx1, idx2 ] => ( array[ idx1 ] )[ idx2 ] + */ +HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_ARRAYAT ); + + /* Check if this expression can be indexed */ + HB_EXPR_USE( pArray, HB_EA_ARRAY_AT ); + /* Check if this expression can be an index */ + HB_EXPR_USE( pIndex, HB_EA_ARRAY_INDEX ); + pExpr->value.asList.pExprList = pArray; + pExpr->value.asList.pIndex = pIndex; + + return pExpr; +} + +/* Creates new macro expression + * pVariable = &variable + * pVariable = &( expression_list ) + * szNameExt = &variable . szNameExt + */ +HB_EXPR_PTR hb_compExprNewMacro( HB_EXPR_PTR pVariable, char * szNameExt ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_MACRO ); + + pExpr->value.asMacro.pVar = pVariable; + pExpr->value.asMacro.szNameExt = szNameExt; + + return pExpr; +} + +/* Creates new aliased variable + * aliasexpr -> identifier + */ +HB_EXPR_PTR hb_compExprNewAliasVar( HB_EXPR_PTR pAlias, char * szVarName ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_ALIASVAR ); + + pExpr->value.asAlias.pAlias = pAlias; + pExpr->value.asAlias.szVarName = szVarName; + pExpr->value.asAlias.pExpList = NULL; + + return pExpr; +} + +/* Creates new aliased expression + * alias_expr -> ( expression ) + */ +HB_EXPR_PTR hb_compExprNewAliasExpr( HB_EXPR_PTR pAlias, HB_EXPR_PTR pExpList ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_ALIASEXPR ); + + pExpr->value.asAlias.pAlias = pAlias; + pExpr->value.asAlias.pExpList = pExpList; + pExpr->value.asAlias.szVarName = NULL; + + return pExpr; +} + +/* Creates new send expression + * pObject : szMessage + */ +HB_EXPR_PTR hb_compExprNewSend( HB_EXPR_PTR pObject, char * szMessage ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_SEND ); + + pExpr->value.asMessage.szMessage = szMessage; + pExpr->value.asMessage.pObject = pObject; + pExpr->value.asMessage.pParms = NULL; + + return pExpr; +} + +/* Creates new method call + * pObject : identifier ( pArgList ) + * + * pObject = is an expression returned by hb_compExprNewSend + * pArgList = list of passed arguments - it will be HB_ET_NONE if no arguments + * are passed + */ +HB_EXPR_PTR hb_compExprNewMethodCall( HB_EXPR_PTR pObject, HB_EXPR_PTR pArgList ) +{ + pObject->value.asMessage.pParms = pArgList; + + return pObject; +} + +/* Creates a list - all elements will be used + * This list can be used to create an array or function's call arguments + */ +HB_EXPR_PTR hb_compExprNewList( HB_EXPR_PTR pFirstItem ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_LIST ); + pExpr->value.asList.pExprList = pFirstItem; + return pExpr; +} + +/* Creates a list of function call arguments + */ +HB_EXPR_PTR hb_compExprNewArgList( HB_EXPR_PTR pFirstItem ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_ARGLIST ); + pExpr->value.asList.pExprList = pFirstItem; + return pExpr; +} + +/* Adds new element to the list + */ +HB_EXPR_PTR hb_compExprAddListExpr( HB_EXPR_PTR pList, HB_EXPR_PTR pNewItem ) +{ + if( pList->value.asList.pExprList ) + { + HB_EXPR_PTR pExpr; + + /* add new item to the end of the list */ + pExpr = pList->value.asList.pExprList; + while( pExpr->pNext ) + pExpr = pExpr->pNext; + pExpr->pNext = pNewItem; + } + else + pList->value.asList.pExprList = pNewItem; + + return pList; +} + +HB_EXPR_PTR hb_compExprNewVar( char * szName ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_VARIABLE ); + pExpr->value.asSymbol = szName; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewSymbol( char * szName ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_SYMBOL ); + pExpr->value.asSymbol = szName; + return pExpr; +} + + +/* ************************************************************************* */ + +HB_EXPR_PTR hb_compExprNewEqual( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EQUAL ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPlus( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PLUS ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMinus( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MINUS ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMult( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MULT ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewDiv( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_DIV ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMod( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MOD ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPower( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POWER ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPostInc( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POSTINC ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPostDec( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_POSTDEC ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPreInc( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PREINC ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPreDec( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PREDEC ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewPlusEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_PLUSEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMinusEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MINUSEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewMultEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MULTEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewDivEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_DIVEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewModEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_MODEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewExpEq( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EXPEQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewAnd( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_AND ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewOr( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_OR ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewNot( HB_EXPR_PTR pNotExpr ) +{ + HB_EXPR_PTR pExpr; + + if( pNotExpr->ExprType == HB_ET_LOGICAL ) + { + pNotExpr->value.asLogical = ! pNotExpr->value.asLogical; + pExpr = pNotExpr; + } + else + { + pExpr = hb_compExprNew( HB_EO_NOT ); + pExpr->value.asOperator.pLeft = pNotExpr; + pExpr->value.asOperator.pRight = NULL; + } + + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewEQ( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_EQ ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewLT( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_LT ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewGT( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_GT ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewLE( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_LE ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewGE( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_GE ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewNE( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_NE ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +HB_EXPR_PTR hb_compExprNewIN( HB_EXPR_PTR pLeftExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_IN ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = NULL; + return pExpr; +} + +/* NOTE: all invalid cases are handled by yacc rules + */ +HB_EXPR_PTR hb_compExprNewNegate( HB_EXPR_PTR pNegExpr ) +{ + HB_EXPR_PTR pExpr; + + if( pNegExpr->ExprType == HB_ET_NUMERIC ) + { + if( pNegExpr->value.asNum.NumType == HB_ET_DOUBLE ) + pNegExpr->value.asNum.dVal = - pNegExpr->value.asNum.dVal; + else + pNegExpr->value.asNum.lVal = - pNegExpr->value.asNum.lVal; + pExpr = pNegExpr; + } + else + { + pExpr = hb_compExprNew( HB_EO_NEGATE ); + pExpr->value.asOperator.pLeft = pNegExpr; + pExpr->value.asOperator.pRight = NULL; + } + return pExpr; +} + + +/* ************************************************************************* */ + +/* Handles (expression := expression) syntax + */ +HB_EXPR_PTR hb_compExprAssign( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_ASSIGN ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = pRightExpr; + return pExpr; +} + +/* It initializes static variable. + * It is called in the following context: + * STATIC sVar := expression + */ +HB_EXPR_PTR hb_compExprAssignStatic( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_ASSIGN ); + pExpr->value.asOperator.pLeft = pLeftExpr; + pExpr->value.asOperator.pRight = HB_EXPR_USE( pRightExpr, HB_EA_REDUCE ); + + if( pRightExpr->ExprType > HB_ET_FUNREF ) + { + /* Illegal initializer for static variable + */ + hb_compErrorStatic( pLeftExpr->value.asSymbol, pRightExpr ); + } + else if( pRightExpr->ExprType == HB_ET_ARRAY ) + { + /* Scan an array for illegal initializers */ + HB_EXPR_PTR pElem = pRightExpr->value.asList.pExprList; + + while( pElem ) + { + if( pElem->ExprType > HB_ET_FUNREF ) + hb_compErrorStatic( pLeftExpr->value.asSymbol, pElem ); + pElem = pElem->pNext; + } + } + + return pExpr; +} + + + +/* Sets the argument of an operation found previously + */ +HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem ) +{ + unsigned char ucRight; + + ucRight = s_PrecedTable[ pItem->ExprType ]; + if( ucRight == HB_ET_NIL ) + { + /* the right side of an operator is an ordinary value + * e.g. a := 1 + */ + pExpr->value.asOperator.pRight = pItem; + } + else if( ucRight == HB_ET_NONE ) + { + /* the right side of an operator is an invalid expression + * e.g. + * a := 1 + b:=2 + * a := 1 + b += 2 + */ + hb_compErrorSyntax( pItem ); + } + else + { + /* the right side of an operator is an expression with other operator + * e.g. a := 2 + b * 3 + * We have to set the proper order of evaluation using + * precedennce rules + */ + unsigned char ucLeft = s_PrecedTable[ pExpr->ExprType ]; + if( ucLeft >= ucRight ) + { + /* Left operator has the same or lower precedence then the right one + * e.g. a * b + c + * pItem -> b + c -> L=b R=c O=+ + * pExpr -> a * -> l=a r= o=* + * + * -> (a * b) + c -> Lelf=(a * b) Right=c Oper=+ + * Left := l (o) L + * Right := R + * Oper := O + */ + pItem->value.asOperator.pLeft = hb_compExprSetOperand( pExpr, pItem->value.asOperator.pLeft ); + pExpr = pItem; } else - debug_msg( " Compile time stack underflow" ); - } -} - - -char ValTypeGet( void ) -{ - return ( lStackTop > 1 ) ? pStackValType[ lStackTop - 1 ].cType : 0; -} - -void ValTypePut( char cType ) -{ - if( _iWarnings ) - { - if( lStackTop > 1 ) - /* reusing the place holder of the result value */ - pStackValType[ lStackTop - 1 ].cType = cType; - else - debug_msg( "\nValTypePut() Compile time stack underflow\n" ); - } -} - -void ValTypeAssign( char *szVarName ) -{ - if( _iWarnings ) - { - if( lStackTop > 2 ) /* at least two expressions are required */ { - PSTACK_VAL_TYPE pLeft = NULL, pRight; - char sType1[ 2 ], sType2[ 2 ]; - - /* 2nd. Operand (stack top)*/ - --lStackTop; - pRight = pStackValType + lStackTop; - sType2[ 0 ] = pRight->cType; - sType2[ 1 ] = '\0'; - - /* skip back to the 1st. operand */ - --lStackTop; - pLeft = pStackValType + lStackTop; - sType1[ 0 ] = pLeft->cType; - sType1[ 1 ] = '\0'; - - if( pRight->cType != ' ' && pLeft->cType == ' ' ) - GenWarning( _szCWarnings, 'W', WARN_ASSIGN_SUSPECT, szVarName, sType2 ); - else if( pRight->cType != ' ' && pRight->cType != pLeft->cType ) - GenWarning( _szCWarnings, 'W', WARN_ASSIGN_TYPE, szVarName, sType1 ); + /* Left operator has a lower precedence then the right one + * e.g. a + b * c + * pItem -> b * c -> L=b R=c O=* + * pExpr -> a + -> l=a r= o=+ + * + * -> a + (b * c) -> Left=a Right=(b * c) Oper=+ + * Left := l + * Right := L (O) R := pItem + * Oper := o + */ + pExpr->value.asOperator.pRight = pItem; } - else - debug_msg( "\nValTypeAssign() Compile time stack underflow\n" ); + } + + return pExpr; +} + +/* Return a number of elements on the linked list + */ +ULONG hb_compExprListLen( HB_EXPR_PTR pExpr ) +{ + ULONG ulLen = 0; + + pExpr = pExpr->value.asList.pExprList; + while( pExpr ) + { + pExpr = pExpr->pNext; + ++ulLen; + } + + return ulLen; +} + +HB_EXPR_PTR hb_compExprReduce( HB_EXPR_PTR pExpr ) +{ + + return HB_EXPR_USE( pExpr, HB_EA_REDUCE ); +} + +/* ************************************************************************* */ + +/* Generates pcode for inline expression used as a statement + * NOTE: It doesn't not leave any value on the eval stack + */ +HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr ) +{ + pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); + HB_EXPR_USE( pExpr, HB_EA_STATEMENT ); + return pExpr; +} + +/* Generates pcode to push an expressions + * NOTE: It pushes a value on the stack and leaves this value on the stack + */ +HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr ) +{ + pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + return pExpr; +} + +/* Generates pcode to pop an expressions + */ +HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR pExpr ) +{ + return HB_EXPR_USE( pExpr, HB_EA_POP_PCODE ); +} + + +/* ************************************************************************* */ + +static HB_EXPR_FUNC( hb_compExprUseDummy ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + break; + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + case HB_EA_ARRAY_INDEX: + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + hb_compGenPCode1( HB_P_PUSHNIL ); + break; + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + case HB_EA_DELETE: + break; + } + return pSelf; +} + +/* actions for HB_ET_NIL expression + */ +static HB_EXPR_FUNC( hb_compExprUseNil ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + break; + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* NIL cannot be used as index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + hb_compGenPCode1( HB_P_PUSHNIL ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + + return pSelf; +} + +/* actions for HB_ET_NUMERIC expression + */ +static HB_EXPR_FUNC( hb_compExprUseNumeric ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + break; + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + if( pSelf->value.asNum.NumType == HB_ET_DOUBLE ) + hb_compGenPushDouble( pSelf->value.asNum.dVal, pSelf->value.asNum.bDec ); + else + hb_compGenPushLong( pSelf->value.asNum.lVal ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + return pSelf; +} + +/* actions for HB_ET_STRING expression + */ +static HB_EXPR_FUNC( hb_compExprUseString ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + break; + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* string cannot be used as index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + hb_compGenPushString( pSelf->value.asString, pSelf->ulLength ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + break; + case HB_EA_DELETE: + HB_XFREE( pSelf->value.asString ); + break; + } + return pSelf; +} + +/* actions for HB_ET_CODEBLOCK expression + */ +static HB_EXPR_FUNC( hb_compExprUseCodeblock ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + break; + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* codeblock cannot be used as index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_CBVAR_PTR pVar; + HB_EXPR_PTR pExpr, pNext; + HB_EXPR_PTR * pPrev; + + hb_compCodeBlockStart(); + /* Define requested local variables + */ + pVar = ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex; + while( pVar ) + { + hb_compAddVar( pVar->szName, pVar->bType ); + pVar =pVar->pNext; + } + pExpr = pSelf->value.asList.pExprList; + pPrev = &pSelf->value.asList.pExprList; + while( pExpr ) + { + /* store next expression in case the current will be reduced + * NOTE: During reduction the expression can be replaced by the + * new one - this will break the linked list of expressions. + */ + pNext = pExpr->pNext; /* store next expression in case the current will be reduced */ + pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); + /* Generate push/pop pcodes for all expresions except the last one + * The value of the last expression is used as a return value + * of a codeblock evaluation + */ + /* NOTE: This will genereate warnings if constant value is + * used as an expression - some operators will generate it too + * e.g. + * EVAL( {|| 3+5, func()} ) + */ + *pPrev = pExpr; /* store a new expression into the previous one */ + pExpr->pNext = pNext; /* restore the link to next expression */ + if( pNext ) + HB_EXPR_USE( pExpr, HB_EA_PUSH_POP ); + else + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + pPrev = &pExpr->pNext; + pExpr = pNext; + } + hb_compCodeBlockEnd(); + } + break; + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + break; + case HB_EA_DELETE: + hb_compExprCBVarDel( ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex ); + hb_compExprDelete( pSelf->value.asList.pExprList ); + break; + } + return pSelf; +} + +/* actions for HB_ET_LOGICAL expression + */ +static HB_EXPR_FUNC( hb_compExprUseLogical ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + break; + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* logical cannot be used as array index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + hb_compGenPushLogical( pSelf->value.asLogical ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + return pSelf; +} + +/* actions for HB_ET_SELF expression + */ +static HB_EXPR_FUNC( hb_compExprUseSelf ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + break; + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); /* QUESTION: Is this OK ? */ + break; + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* SELF cannot be used as array index element */ + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + hb_compGenPCode1( HB_P_PUSHSELF ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + return pSelf; +} + +/* actions for a literal array { , , , ... } + */ +static HB_EXPR_FUNC( hb_compExprUseArray ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + hb_compExprListReduce( pSelf ); + break; + + case HB_EA_ARRAY_AT: + break; + + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); /* array cannot be used as index element */ + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + HB_EXPR_PTR pElem = pSelf->value.asList.pExprList; + /* Push all elements of the array + */ + if( ( pElem == NULL ) || ( pElem->ExprType == HB_ET_NONE && pElem->pNext == NULL ) ) + hb_compGenPCode3( HB_P_ARRAYGEN, 0, 0 ); + else + { + while( pElem ) + { + HB_EXPR_USE( pElem, HB_EA_PUSH_PCODE ); + pElem = pElem->pNext; + } + hb_compGenPCode3( HB_P_ARRAYGEN, HB_LOBYTE( pSelf->ulLength ), HB_HIBYTE( pSelf->ulLength ) ); + } + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + { + HB_EXPR_PTR pElem = pSelf->value.asList.pExprList; + /* Push non-constant values only + */ + while( pElem ) + { + HB_EXPR_USE( pElem, HB_EA_PUSH_POP ); + pElem = pElem->pNext; + } + } + break; + + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + break; + + case HB_EA_DELETE: + { + HB_EXPR_PTR pElem = pSelf->value.asList.pExprList; + /* Delete all elements of the array + */ + while( pElem ) + { + HB_EXPR_USE( pElem, HB_EA_DELETE ); + pElem = pElem->pNext; + } + } + break; + + } + + return pSelf; +} + +/* actions for HB_ET_VARREF expression + */ +static HB_EXPR_FUNC( hb_compExprUseVarRef ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + break; + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + hb_compGenPushVarRef( pSelf->value.asSymbol ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + return pSelf; +} + +/* actions for HB_ET_FUNREF expression + */ +static HB_EXPR_FUNC( hb_compExprUseFunRef ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + break; + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + case HB_EA_ARRAY_INDEX: + break; + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + hb_compGenPushFunCall( pSelf->value.asSymbol ); + hb_compGenPCode1( HB_P_FUNCPTR ); + break; + case HB_EA_POP_PCODE: + break; + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + return pSelf; +} + +/* actions for HB_ET_IIF expression + */ +static HB_EXPR_FUNC( hb_compExprUseIIF ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pExpr; + + hb_compExprListReduce( pSelf ); + + pExpr =pSelf->value.asList.pExprList; /* get conditional expression */ + if( pExpr->ExprType == HB_ET_LOGICAL ) + { + /* the condition was reduced to a logical value: .T. or .F. + */ + if( pExpr->value.asLogical ) + { + /* .T. was specified + */ + pExpr = pExpr->pNext; /* skip to TRUE expression */ + /* delete condition - it is no longer needed + */ + hb_compExprDelete( pSelf->value.asList.pExprList ); + /* assign NULL to a start of expressions list to suppress + * deletion of expression's components - we are deleting them + * here + */ + pSelf->value.asList.pExprList = NULL; + hb_compExprDelete( pSelf ); + /* store the TRUE expression as a result of reduction + */ + pSelf = pExpr; + pExpr = pExpr->pNext; /* skip to FALSE expression */ + hb_compExprDelete( pExpr ); /* delete FALSE expr */ + pSelf->pNext = NULL; + } + else + { + /* .F. was specified + */ + pExpr = pExpr->pNext; /* skip to TRUE expression */ + /* delete condition - it is no longer needed + */ + hb_compExprDelete( pSelf->value.asList.pExprList ); + /* assign NULL to a start of expressions list to suppress + * deletion of expression's components - we are deleting them + * here + */ + pSelf->value.asList.pExprList = NULL; + hb_compExprDelete( pSelf ); + /* store the FALSE expression as a result of reduction + */ + pSelf = pExpr->pNext; + hb_compExprDelete( pExpr ); /* delete TRUE expr */ + pSelf->pNext = NULL; + } + } + /* check if valid expression is passed + */ + else if( ( pExpr->ExprType == HB_ET_DOUBLE ) || + ( pExpr->ExprType == HB_ET_LONG ) || + ( pExpr->ExprType == HB_ET_NIL ) || + ( pExpr->ExprType == HB_ET_STRING ) || + ( pExpr->ExprType == HB_ET_CODEBLOCK ) || + ( pExpr->ExprType == HB_ET_SELF ) || + ( pExpr->ExprType == HB_ET_ARRAY ) ) + { + hb_compErrorType( pExpr ); + } + } + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + /* this is called if all three parts of IIF expression should be generated + */ + LONG lPosFalse, lPosEnd; + HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList; + + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + lPosFalse = hb_compGenJumpFalse( 0 ); + pExpr =pExpr->pNext; + + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + lPosEnd = hb_compGenJump( 0 ); + pExpr =pExpr->pNext; + + hb_compGenJumpHere( lPosFalse ); + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + hb_compGenJumpHere( lPosEnd ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + { + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); /* remove a value if used in statement */ + } + break; + + case HB_EA_DELETE: + if( pSelf->value.asList.pExprList ) + { + HB_EXPR_PTR pTmp, pExpr = pSelf->value.asList.pExprList; + while( pExpr ) + { + pTmp = pExpr->pNext; /* store next expression */ + hb_compExprDelete( pExpr ); + pExpr =pTmp; + } + pSelf->value.asList.pExprList = NULL; + } + break; + } + return pSelf; /* return self */ +} + +/* NOTE: In PUSH operation it leaves on the eval stack the last expression only + */ +static HB_EXPR_FUNC( hb_compExprUseList ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + ULONG ulCount; + + ulCount = hb_compExprListReduce( pSelf ); + if( ulCount == 1 && pSelf->value.asList.pExprList->ExprType <= HB_ET_VARIABLE ) + { + /* replace the list with a simple expression + */ + HB_EXPR_PTR pExpr = pSelf; + + pSelf = pSelf->value.asList.pExprList; + pExpr->value.asList.pExprList = NULL; + hb_compExprDelete( pExpr ); + } + } + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + if( hb_compExprListLen( pSelf ) == 1 ) + hb_compErrorLValue( pSelf->value.asList.pExprList ); + else + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList; + + while( pExpr ) + { + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + pExpr = pExpr->pNext; + if( pExpr ) + hb_compGenPCode1( HB_P_POP ); + } + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + { + HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList; + + while( pExpr ) + { + HB_EXPR_USE( pExpr, HB_EA_PUSH_POP ); + pExpr = pExpr->pNext; + } + } + break; + + case HB_EA_DELETE: + if( pSelf->value.asList.pExprList ) + { + HB_EXPR_PTR pTmp, pExpr = pSelf->value.asList.pExprList; + while( pExpr ) + { + pTmp = pExpr->pNext; /* store next expression */ + hb_compExprDelete( pExpr ); + pExpr =pTmp; + } + pSelf->value.asList.pExprList = NULL; + } + break; + } + return pSelf; +} + +/* NOTE: In PUSH operation it leaves all expressions on the eval stack + */ +static HB_EXPR_FUNC( hb_compExprUseArgList ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + hb_compExprListReduce( pSelf ); + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + break; + + case HB_EA_PUSH_PCODE: + { + HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList; + + while( pExpr ) + { + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + pExpr = pExpr->pNext; + } + } + break; + + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + break; + + case HB_EA_DELETE: + if( pSelf->value.asList.pExprList ) + { + HB_EXPR_PTR pTmp, pExpr = pSelf->value.asList.pExprList; + while( pExpr ) + { + pTmp = pExpr->pNext; /* store next expression */ + hb_compExprDelete( pExpr ); + pExpr =pTmp; + } + pSelf->value.asList.pExprList = NULL; + } + break; + } + return pSelf; +} + +/* handler for ( ( array[ idx ] )[ idx ] )[ idx ] + */ +static HB_EXPR_FUNC( hb_compExprUseArrayAt ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pIdx; + + pSelf->value.asList.pExprList = HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_REDUCE ); + pSelf->value.asList.pIndex = HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_REDUCE ); + pIdx = pSelf->value.asList.pIndex; + if( pIdx->ExprType == HB_ET_NUMERIC ) + { + HB_EXPR_PTR pExpr = pSelf->value.asList.pExprList; /* the expression that holds an array */ + + if( pExpr->ExprType == HB_ET_ARRAY ) /* is it a literal array */ + { + LONG lIndex; + + pExpr = pExpr->value.asList.pExprList; /* the first element in the array */ + if( pIdx->value.asNum.NumType == HB_ET_LONG ) + lIndex = pIdx->value.asNum.lVal; + else + lIndex = pIdx->value.asNum.dVal; + + if( lIndex > 0 ) + { + while( --lIndex && pExpr ) + pExpr = pExpr->pNext; + } + else + pExpr = NULL; /* index is <= 0 - generate bound error */ + + if( pExpr ) /* found ? */ + { + /* extract a single expression from the array + */ + HB_EXPR_PTR pNew = hb_compExprNew( HB_ET_NONE ); + memcpy( pNew, pExpr, sizeof( HB_EXPR ) ); + /* This will suppres releasing of memory occupied by components of + * the expression - we have just copied them into the new expression. + * This method is simpler then traversing the list and releasing all + * but this choosen one. + */ + pExpr->ExprType = HB_ET_NONE; + /* Here comes the magic */ + hb_compExprDelete( pSelf ); + pSelf = pNew; + } + else + { + hb_compErrorBound( pIdx ); + } + } + else + { + LONG lIndex; + + if( pIdx->value.asNum.NumType == HB_ET_LONG ) + lIndex = pIdx->value.asNum.lVal; + else + lIndex = pIdx->value.asNum.dVal; + + if( lIndex > 0 ) + HB_EXPR_USE( pExpr, HB_EA_ARRAY_AT ); + else + hb_compErrorBound( pIdx ); /* index <= 0 - bound error */ + } + } + } + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_ARRAYPUSH ); + } + break; + + case HB_EA_POP_PCODE: + { + HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_ARRAYPOP ); + } + break; + + case HB_EA_PUSH_POP: + { + /* NOTE: This is highly optimized code - this will work even + * if accessed value isn't an array. It will work also if + * the index is invalid + */ + HB_EXPR_USE( pSelf->value.asList.pExprList, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asList.pIndex, HB_EA_PUSH_POP ); + } + /* no break */ + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + break; + case HB_EA_DELETE: + hb_compExprDelete( pSelf->value.asList.pExprList ); + hb_compExprDelete( pSelf->value.asList.pIndex ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseMacro ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + case HB_EA_PUSH_PCODE: + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseFunCall ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + /* Reduce the expressions on the list of arguments + */ + pSelf->value.asFunCall.pParms = HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_REDUCE ); + } + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + USHORT usCount; + + hb_compGenPushFunCall( pSelf->value.asFunCall.szFunName ); + hb_compGenPCode1( HB_P_PUSHNIL ); + + usCount = hb_compExprListLen( pSelf->value.asFunCall.pParms ); + if( usCount == 1 && pSelf->value.asFunCall.pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) + --usCount; + if( usCount ) + HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_PUSH_PCODE ); + hb_compGenPCode3( HB_P_FUNCTION, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + { + USHORT usCount; + + hb_compGenPushFunCall( pSelf->value.asFunCall.szFunName ); + hb_compGenPCode1( HB_P_PUSHNIL ); + + usCount = hb_compExprListLen( pSelf->value.asFunCall.pParms ); + if( usCount == 1 && pSelf->value.asFunCall.pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) + --usCount; + if( usCount ) + HB_EXPR_USE( pSelf->value.asFunCall.pParms, HB_EA_PUSH_PCODE ); + hb_compGenPCode3( HB_P_DO, HB_LOBYTE( usCount ), HB_HIBYTE( usCount ) ); + } + break; + + case HB_EA_DELETE: + if( pSelf->value.asFunCall.pParms ) + hb_compExprDelete( pSelf->value.asFunCall.pParms ); + /* NOTE: function name will be released after pcode generation */ + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseAliasVar ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + case HB_EA_PUSH_PCODE: + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseAliasExpr ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + case HB_EA_PUSH_PCODE: + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compWarnMeaningless( pSelf ); + case HB_EA_DELETE: + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseSymbol ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + case HB_EA_PUSH_PCODE: + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + case HB_EA_DELETE: + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseVariable ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + break; + case HB_EA_PUSH_PCODE: + hb_compGenPushVar( pSelf->value.asSymbol ); + break; + case HB_EA_POP_PCODE: + hb_compGenPopVar( pSelf->value.asSymbol ); + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compGenPushVar( pSelf->value.asSymbol ); + hb_compGenPCode1( HB_P_POP ); + break; + + case HB_EA_DELETE: + /* NOTE: variable name will be released after pcode generation */ + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseSend ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + pSelf->value.asMessage.pObject = HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_REDUCE ); + if( pSelf->value.asMessage.pParms ) /* Is it a method call ? */ + pSelf->value.asMessage.pParms = HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_REDUCE ); + } + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + break; + + case HB_EA_PUSH_PCODE: + { + if( pSelf->value.asMessage.pParms ) /* Is it a method call ? */ + { + int iParms = hb_compExprListLen( pSelf->value.asMessage.pParms ); + HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + hb_compGenMessage( pSelf->value.asMessage.szMessage ); + /* 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 + */ + if( iParms == 1 && pSelf->value.asMessage.pParms->value.asList.pExprList->ExprType == HB_ET_NONE ) + --iParms; + if( iParms ) + HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE ); + hb_compGenPCode3( HB_P_FUNCTION, HB_LOBYTE( iParms ), HB_HIBYTE( iParms ) ); + } + else + { + /* acces to instance variable */ + HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + hb_compGenMessage( pSelf->value.asMessage.szMessage ); + hb_compGenPCode3( HB_P_FUNCTION, 0, 0 ); + } + } + break; + + case HB_EA_POP_PCODE: + { + /* NOTE: This is an exception from the rule - this leaves + * the return value on the stack + */ + HB_EXPR_USE( pSelf->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + hb_compGenMessageData( pSelf->value.asMessage.szMessage ); + HB_EXPR_USE( pSelf->value.asMessage.pParms, HB_EA_PUSH_PCODE ); + hb_compGenPCode3( HB_P_FUNCTION, 1, 0 ); + } + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); + if( ! pSelf->value.asMessage.pParms ) /* Is it a method call ? */ + { + /* instance variable */ + /* QUESTION: This warning can be misleading if nested messages + * are used, e.g. a:b():c - should we generate it ? + */ + hb_compWarnMeaningless( pSelf ); + } + + case HB_EA_DELETE: + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePostInc ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + hb_compExprPushPostOp( pSelf, HB_P_INC ); + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + /* a++ used standalone as a statement is the same as ++a + */ + hb_compExprUsePreOp( pSelf, HB_P_INC ); + break; + + case HB_EA_DELETE: + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePostDec ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + hb_compExprPushPostOp( pSelf, HB_P_DEC ); + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compExprUsePreOp( pSelf, HB_P_DEC ); + break; + + case HB_EA_DELETE: + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseAssign ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + case HB_EA_LVALUE: + break; + + case HB_EA_PUSH_PCODE: + { + /* NOTE: assigment to an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; + pObj->value.asMessage.pParms = pSelf->value.asOperator.pRight; + HB_EXPR_USE( pObj, HB_EA_POP_PCODE ); + pObj->value.asMessage.pParms = NULL; /* to suppress duplicated releasing */ + } + else + { + /* it assigns a value and leaves it on the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* QUESTION: Can we replace DUPLICATE+POP with a single PUT opcode + */ + hb_compGenPCode1( HB_P_DUPLICATE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + { + /* NOTE: assigment to an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; + pObj->value.asMessage.pParms = pSelf->value.asOperator.pRight; + HB_EXPR_USE( pObj, HB_EA_POP_PCODE ); + pObj->value.asMessage.pParms = NULL; /* to suppress duplicated releasing */ + /* Remove the return value */ + hb_compGenPCode1( HB_P_POP ); + } + else + { + /* it assigns a value and removes it from the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } + } + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePlusEq ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + hb_compExprPushOperEq( pSelf, HB_P_PLUS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compExprUseOperEq( pSelf, HB_P_PLUS ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseMinusEq ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + hb_compExprPushOperEq( pSelf, HB_P_MINUS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compExprUseOperEq( pSelf, HB_P_MINUS ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseMultEq ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + hb_compExprPushOperEq( pSelf, HB_P_MULT ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compExprUseOperEq( pSelf, HB_P_MULT ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseDivEq ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + hb_compExprPushOperEq( pSelf, HB_P_DIVIDE ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compExprUseOperEq( pSelf, HB_P_DIVIDE ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseModEq ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + hb_compExprPushOperEq( pSelf, HB_P_MODULUS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compExprUseOperEq( pSelf, HB_P_MODULUS ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseExpEq ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + hb_compExprPushOperEq( pSelf, HB_P_POWER ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compExprUseOperEq( pSelf, HB_P_POWER ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseOr ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_LOGICAL && pRight->ExprType == HB_ET_LOGICAL ) + { + BOOL bResult; + + bResult = pLeft->value.asLogical || pRight->value.asLogical; + hb_compExprDelete( pLeft ); + hb_compExprDelete( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + else if( pLeft->ExprType == HB_ET_LOGICAL ) + { + if( pLeft->value.asLogical ) + { + /* .T. .OR. expr => .T. + */ + hb_compExprDelete( pLeft ); + hb_compExprDelete( pRight ); /* discard expression */ + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = TRUE; + } + else + { + /* .F. .OR. expr => expr + */ + hb_compExprDelete( pLeft ); + pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ + hb_compExprDelete( pSelf ); + pSelf = pRight; + } + } + else if( pRight->ExprType == HB_ET_LOGICAL ) + { + if( pLeft->value.asLogical ) + { + /* expr .OR. .T. => .T. + */ + hb_compExprDelete( pLeft ); /* discard expression */ + hb_compExprDelete( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = TRUE; + } + else + { + /* expr .OR. .F. => expr + */ + hb_compExprDelete( pRight ); + pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ + hb_compExprDelete( pSelf ); + pSelf = pLeft; + } + } + + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + if( hb_comp_bShortCuts ) + { + LONG lEndPos; + + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_DUPLICATE ); + lEndPos = hb_compGenJumpTrue( 0 ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_OR ); + hb_compGenJumpHere( lEndPos ); + } + else + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_OR ); + } + break; + + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseAnd ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_LOGICAL && pRight->ExprType == HB_ET_LOGICAL ) + { + BOOL bResult; + + bResult = pLeft->value.asLogical && pRight->value.asLogical; + hb_compExprDelete( pLeft ); + hb_compExprDelete( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + else if( pLeft->ExprType == HB_ET_LOGICAL ) + { + if( pLeft->value.asLogical ) + { + /* .T. .AND. expr => expr + */ + hb_compExprDelete( pLeft ); + pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ + hb_compExprDelete( pSelf ); + pSelf = pRight; + } + else + { + /* .F. .AND. expr => .F. + */ + hb_compExprDelete( pLeft ); + hb_compExprDelete( pRight ); /* discard expression */ + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = FALSE; + } + } + else if( pRight->ExprType == HB_ET_LOGICAL ) + { + if( pLeft->value.asLogical ) + { + /* expr .AND. .T. => expr + */ + hb_compExprDelete( pRight ); + pSelf->ExprType = HB_ET_NONE; /* don't delete expression components */ + hb_compExprDelete( pSelf ); + pSelf = pLeft; + } + else + { + /* expr .AND. .F. => .F. + */ + hb_compExprDelete( pLeft ); /* discard expression */ + hb_compExprDelete( pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = FALSE; + } + } + + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + if( hb_comp_bShortCuts ) + { + LONG lEndPos; + + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_DUPLICATE ); + lEndPos = hb_compGenJumpFalse( 0 ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_AND ); + hb_compGenJumpHere( lEndPos ); + } + else + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_AND ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseNot ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pExpr; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pExpr = pSelf->value.asOperator.pLeft; + + if( pExpr->ExprType == HB_ET_LOGICAL ) + { + pExpr->value.asLogical = ! pExpr->value.asLogical; + pSelf->ExprType = HB_ET_NONE; /* do not delete operator parameter - we are still using it */ + hb_compExprDelete( pSelf ); + pSelf = pExpr; + } + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + hb_compErrorIndex( pSelf ); + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_NOT ); + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseEqual ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + } + break; + + case HB_EA_ARRAY_AT: + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + /* '=' used in an expression - compare values + */ + /* Try to optimize expression - we cannot optimize in HB_EA_REDUCE + * because it is not decided yet if it is assigment or comparision + */ + HB_EXPR_PTR pLeft, pRight; + + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + hb_compGenPushLogical( pLeft->value.asLogical == pRight->value.asLogical ); + break; + + case HB_ET_STRING: + /* NOTE: the result depends on SET EXACT setting then it + * cannot be optimized except the case when NULL string are + * compared - the result is always TRUE regardless of EXACT + * setting + */ + if( (pLeft->ulLength | pRight->ulLength) == 0 ) + hb_compGenPushLogical( TRUE ); /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ + else + { + HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_EQUAL ); + } + break; + + case HB_ET_NIL: + /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ + hb_compGenPushLogical( TRUE ); /* NIL = NIL is always TRUE */ + break; + + case HB_ET_NUMERIC: + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + hb_compGenPushLogical( pLeft->value.asNum.lVal == pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + hb_compGenPushLogical( pLeft->value.asNum.dVal == pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + hb_compGenPushLogical( pLeft->value.asNum.lVal == pRight->value.asNum.dVal ); + else + hb_compGenPushLogical( pLeft->value.asNum.dVal == pRight->value.asNum.lVal ); + } + break; + } + break; + + default: + { + HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_EQUAL ); + } + } + else + { + /* TODO: check for incompatible types + */ + HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_EQUAL ); + } + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + { + /* '=' used standalone in a statement - assign a value + * it assigns a value and removes it from the stack + * */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + /* Send messages are implemented as function calls + */ + HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; + pObj->value.asMessage.pParms = pSelf->value.asOperator.pRight; + HB_EXPR_USE( pObj, HB_EA_POP_PCODE ); + pObj->value.asMessage.pParms = NULL; /* to suppress duplicated releasing */ + /* Remove the return value */ + hb_compGenPCode1( HB_P_POP ); + } + else + { + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } + } + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +/* handler for == operator + */ +static HB_EXPR_FUNC( hb_compExprUseEQ ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + { + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + BOOL bResult = ( pLeft->value.asLogical == pRight->value.asLogical ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_STRING: + { + BOOL bResult = FALSE; + + if( pLeft->ulLength == pRight->ulLength ) + bResult = ( strcmp( pLeft->value.asString, pRight->value.asString ) == 0 ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal == pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal == pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal == pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal == pRight->value.asNum.lVal ); + } + break; + } + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + } + } + /* TODO: add checking of incompatible types + else + { + } + */ + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_EXACTLYEQUAL ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseLT ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .F. < .T. = .T. + * .T. < .T. = .F. + * .F. < .F. = .F. + * .T. < .F. = .F. + */ + BOOL bResult = ( ! pLeft->value.asLogical && pRight->value.asLogical ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal < pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal < pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal < pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal < pRight->value.asNum.lVal ); + } + break; + } + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + default: + break; + } + /* TODO: add checking of incompatible types + else + { + } + */ + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_LESS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseGT ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .T. > .F. = .T. + * .T. > .T. = .F. + * .F. > .F. = .F. + * .F. > .T. = .F. + */ + BOOL bResult = ( pLeft->value.asLogical && ! pRight->value.asLogical ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal > pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal > pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal > pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal > pRight->value.asNum.lVal ); + } + break; + } + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + } + /* TODO: add checking of incompatible types + else + { + } + */ + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_GREATER ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseLE ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .T. <= .F. = .F. + * .T. <= .T. = .T. + * .F. <= .F. = .T. + * .F. <= .T. = .T. + */ + BOOL bResult = ! ( pLeft->value.asLogical && ! pRight->value.asLogical ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal <= pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal <= pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal <= pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal <= pRight->value.asNum.lVal ); + } + break; + } + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + } + /* TODO: add checking of incompatible types + else + { + } + */ + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_LESSEQUAL ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseGE ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .T. >= .F. = .T. + * .T. >= .T. = .T. + * .F. >= .F. = .T. + * .F. >= .T. = .f. + */ + BOOL bResult = ! ( ! pLeft->value.asLogical && pRight->value.asLogical ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal >= pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal >= pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal >= pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal >= pRight->value.asNum.lVal ); + } + break; + } + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + } + /* TODO: add checking of incompatible types + else + { + } + */ + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_GREATEREQUAL ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseNE ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == pRight->ExprType ) + switch( pLeft->ExprType ) + { + case HB_ET_LOGICAL: + { + /* .F. != .T. = .T. + * .T. != .T. = .F. + * .F. != .F. = .F. + * .T. != .F. = .T. + */ + BOOL bResult = ( pLeft->value.asLogical != pRight->value.asLogical ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + case HB_ET_STRING: + /* NOTE: the result depends on SET EXACT setting then it + * cannot be optimized except the case when NULL string are + * compared - "" != "" is always FALSE regardless of EXACT + * setting + */ + if( (pLeft->ulLength | pRight->ulLength) == 0 ) + hb_compGenPushLogical( FALSE ); /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ + break; + + case HB_ET_NUMERIC: + { + BOOL bResult; + + switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) + { + case HB_ET_LONG: + bResult = ( pLeft->value.asNum.lVal != pRight->value.asNum.lVal ); + break; + case HB_ET_DOUBLE: + bResult = ( pLeft->value.asNum.dVal != pRight->value.asNum.dVal ); + break; + default: + { + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.lVal != pRight->value.asNum.dVal ); + else + bResult = ( pLeft->value.asNum.dVal != pRight->value.asNum.lVal ); + } + break; + } + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + break; + + } + /* TODO: add checking of incompatible types + else + { + } + */ + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_NOTEQUAL ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseIN ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + + if( ( pSelf->value.asOperator.pLeft->ExprType == pSelf->value.asOperator.pRight->ExprType ) && pSelf->value.asOperator.pLeft->ExprType == HB_ET_STRING ) + { + /* Both arguments are literal strings + */ + BOOL bResult; + + bResult = ( strstr( pSelf->value.asOperator.pRight->value.asString, pSelf->value.asOperator.pLeft->value.asString ) != NULL ); + /* NOTE: + * "" $ "XXX" = .T. + * "" $ "" = .T. + */ + hb_compExprDelete( pSelf->value.asOperator.pLeft ); + hb_compExprDelete( pSelf->value.asOperator.pRight ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = bResult; + } + /* TODO: add checking for incompatible types + */ + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_INSTRING ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePlus ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + unsigned char bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + { + double dVal = pLeft->value.asNum.lVal + pRight->value.asNum.lVal; + + if( ( double )LONG_MIN <= dVal && dVal <= ( double )LONG_MAX ) + { + pSelf->value.asNum.lVal = pLeft->value.asNum.lVal + pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + break; + + case HB_ET_DOUBLE: + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal + pRight->value.asNum.dVal; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + if( pLeft->value.asNum.bDec < pRight->value.asNum.bDec ) + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + else + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + } + break; + + default: + { + if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal + ( double ) pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + } + else + { + pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal + pRight->value.asNum.dVal; + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + } + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + pSelf->ExprType = HB_ET_NUMERIC; + pSelf->ValType = HB_EV_NUMERIC; + HB_EXPR_USE( pLeft, HB_EA_DELETE ); + HB_EXPR_USE( pRight, HB_EA_DELETE ); + } + else if( pLeft->ExprType == HB_ET_STRING && pRight->ExprType == HB_ET_STRING ) + { + pSelf->ExprType = HB_ET_NONE; /* suppress deletion of operator components */ + hb_compExprDelete( pSelf ); + if( pRight->ulLength == 0 ) + { + pSelf = pLeft; + hb_compExprDelete( pRight ); + } + else if( pLeft->ulLength == 0 ) + { + pSelf = pRight; + hb_compExprDelete( pLeft ); + } + else + { + pLeft->value.asString = (char *) hb_xrealloc( pLeft->value.asString, pLeft->ulLength + pRight->ulLength + 1 ); + memcpy( pLeft->value.asString + pLeft->ulLength, + pRight->value.asString, pRight->ulLength ); + pLeft->ulLength += pRight->ulLength; + pLeft->value.asString[ pLeft->ulLength ] = '\0'; + pSelf = pLeft; + hb_compExprDelete( pRight ); + } + } + else + { + /* TODO: Check for incompatible types e.g. "txt" + 3 + */ + } + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_PLUS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseMinus ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + unsigned char bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + { + double dVal = pLeft->value.asNum.lVal - pRight->value.asNum.lVal; + + if( ( double )LONG_MIN <= dVal && dVal <= ( double )LONG_MAX ) + { + pSelf->value.asNum.lVal = pLeft->value.asNum.lVal - pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + break; + + case HB_ET_DOUBLE: + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal - pRight->value.asNum.dVal; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + if( pLeft->value.asNum.bDec < pRight->value.asNum.bDec ) + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + else + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + } + break; + + default: + { + if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal - ( double ) pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + } + else + { + pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal - pRight->value.asNum.dVal; + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + } + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + pSelf->ExprType = HB_ET_NUMERIC; + pSelf->ValType = HB_EV_NUMERIC; + HB_EXPR_USE( pLeft, HB_EA_DELETE ); + HB_EXPR_USE( pRight, HB_EA_DELETE ); + } + else if( pLeft->ExprType == HB_ET_STRING && pRight->ExprType == HB_ET_STRING ) + { + /* TODO: + */ + } + else + { + /* TODO: Check for incompatible types e.g. "txt" - 3 + */ + } + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_MINUS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseMult ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + unsigned char bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + { + double dVal = pLeft->value.asNum.lVal * pRight->value.asNum.lVal; + + if( ( double )LONG_MIN <= dVal && dVal <= ( double )LONG_MAX ) + { + pSelf->value.asNum.lVal = pLeft->value.asNum.lVal * pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + break; + + case HB_ET_DOUBLE: + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal * pRight->value.asNum.dVal; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec + pRight->value.asNum.bDec; + } + break; + + default: + { + if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal * ( double ) pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + } + else + { + pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal * pRight->value.asNum.dVal; + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + } + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + pSelf->ExprType = HB_ET_NUMERIC; + pSelf->ValType = HB_EV_NUMERIC; + HB_EXPR_USE( pLeft, HB_EA_DELETE ); + HB_EXPR_USE( pRight, HB_EA_DELETE ); + } + else + { + /* TODO: Check for incompatible types e.g. 3 * "txt" + */ + } + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_MULT ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseDiv ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + unsigned char bType = ( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ); + + switch( bType ) + { + case HB_ET_LONG: + { + double dVal = pLeft->value.asNum.lVal / pRight->value.asNum.lVal; + + if( ( double )LONG_MIN <= dVal && dVal <= ( double )LONG_MAX ) + { + pSelf->value.asNum.lVal = pLeft->value.asNum.lVal / pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + break; + + case HB_ET_DOUBLE: + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal / pRight->value.asNum.dVal; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec + pRight->value.asNum.bDec; + } + break; + + default: + { + if( pLeft->value.asNum.NumType == HB_ET_DOUBLE ) + { + pSelf->value.asNum.dVal = pLeft->value.asNum.dVal / ( double ) pRight->value.asNum.lVal; + pSelf->value.asNum.bDec = pLeft->value.asNum.bDec; + } + else + { + pSelf->value.asNum.dVal = ( double ) pLeft->value.asNum.lVal / pRight->value.asNum.dVal; + pSelf->value.asNum.bDec = pRight->value.asNum.bDec; + } + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + } + pSelf->ExprType = HB_ET_NUMERIC; + pSelf->ValType = HB_EV_NUMERIC; + HB_EXPR_USE( pLeft, HB_EA_DELETE ); + HB_EXPR_USE( pRight, HB_EA_DELETE ); + } + else + { + /* TODO: Check for incompatible types e.g. 3 / "txt" + */ + } + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_DIVIDE ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseMod ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pLeft, pRight; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pSelf->value.asOperator.pRight = HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ); + pLeft = pSelf->value.asOperator.pLeft; + pRight = pSelf->value.asOperator.pRight; + + if( pLeft->ExprType == HB_ET_NUMERIC && pRight->ExprType == HB_ET_NUMERIC ) + { + if( pLeft->value.asNum.NumType == HB_ET_LONG && pRight->value.asNum.NumType == HB_ET_LONG ) + { + double dVal; + if( pRight->value.asNum.lVal ) + dVal = pLeft->value.asNum.lVal % pRight->value.asNum.lVal; + else + break; /* QUESTION: should we generate a warning or error here */ + + if( ( double )LONG_MIN <= dVal && dVal <= ( double )LONG_MAX ) + { + pSelf->value.asNum.lVal = ( long ) dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_LONG; + } + else + { + pSelf->value.asNum.dVal = dVal; + pSelf->value.asNum.bDec = 0; + pSelf->value.asNum.NumType = HB_ET_DOUBLE; + } + + pSelf->ExprType = HB_ET_NUMERIC; + pSelf->ValType = HB_EV_NUMERIC; + HB_EXPR_USE( pLeft, HB_EA_DELETE ); + HB_EXPR_USE( pRight, HB_EA_DELETE ); + } + } + else + { + /* TODO: Check for incompatible types e.g. 3 % "txt" + */ + } + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_MODULUS ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePower ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: /* Clipper doesn't optimize it */ + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POWER ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + case HB_EA_DELETE: + hb_compExprDelOperator( pSelf ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUseNegate ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + { + HB_EXPR_PTR pExpr; + + pSelf->value.asOperator.pLeft = HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ); + pExpr = pSelf->value.asOperator.pLeft; + + if( pExpr->ExprType == HB_ET_NUMERIC ) + { + if( pExpr->value.asNum.NumType == HB_ET_DOUBLE ) + pExpr->value.asNum.dVal = - pExpr->value.asNum.dVal; + else + pExpr->value.asNum.lVal = - pExpr->value.asNum.lVal; + pSelf->ExprType = HB_ET_NONE; /* do not delete operator parameter - we are still using it */ + hb_compExprDelete( pSelf ); + pSelf = pExpr; + } + } + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + case HB_EA_PUSH_PCODE: + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_NEGATE ); + } + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); +#else + /* NOTE: This will not generate a runtime error if incompatible + * data type is used + */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_POP ); +#endif + break; + + case HB_EA_STATEMENT: + hb_compErrorSyntax( pSelf ); + break; + + case HB_EA_DELETE: + if( pSelf->value.asOperator.pLeft ) + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_DELETE ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePreInc ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + hb_compExprPushPreOp( pSelf, HB_P_INC ); + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compExprUsePreOp( pSelf, HB_P_INC ); + break; + + case HB_EA_DELETE: + if( pSelf->value.asOperator.pLeft ) + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_DELETE ); + break; + } + return pSelf; +} + +static HB_EXPR_FUNC( hb_compExprUsePreDec ) +{ + switch( iMessage ) + { + case HB_EA_REDUCE: + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_LVALUE ); + break; + + case HB_EA_ARRAY_AT: + hb_compErrorType( pSelf ); + break; + + case HB_EA_ARRAY_INDEX: + break; + + case HB_EA_LVALUE: + hb_compErrorLValue( pSelf ); + break; + + case HB_EA_PUSH_PCODE: + hb_compExprPushPreOp( pSelf, HB_P_DEC ); + break; + + case HB_EA_POP_PCODE: + break; + + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + hb_compExprUsePreOp( pSelf, HB_P_DEC ); + break; + + case HB_EA_DELETE: + if( pSelf->value.asOperator.pLeft ) + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_DELETE ); + break; + } + return pSelf; +} + +/* ************************************************************************* */ + +static void hb_compExprDelOperator( HB_EXPR_PTR pExpr ) +{ + if( pExpr->value.asOperator.pLeft ) + HB_EXPR_USE( pExpr->value.asOperator.pLeft, HB_EA_DELETE ); + if( pExpr->value.asOperator.pRight ) + HB_EXPR_USE( pExpr->value.asOperator.pRight, HB_EA_DELETE ); +} + +/* Reduces the list of expressions + * + * pExpr is the first expression on the list + */ +static ULONG hb_compExprListReduce( HB_EXPR_PTR pExpr ) +{ + HB_EXPR_PTR pNext; + HB_EXPR_PTR * pPrev; + ULONG ulCnt = 0; + + /* NOTE: During optimalization an expression on the list can be + * replaced by the new one + */ + + pPrev = &pExpr->value.asList.pExprList; + pExpr = pExpr->value.asList.pExprList; + while( pExpr ) + { + pNext = pExpr->pNext; /* store next expression in case the current will be reduced */ + pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); + *pPrev = pExpr; /* store a new expression into the previous one */ + pExpr->pNext = pNext; /* restore the link to next expression */ + pPrev = &pExpr->pNext; + pExpr = pNext; + ++ulCnt; + } + return ulCnt; +} + +/* Generates pcodes for compound operators += -= *= /= %= ^= + * + * pExpr is an expression created by hb_compExprNewEq functions + */ +static void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) +{ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; + + /* Push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + /* Push _message for later use */ + hb_compGenMessageData( pObj->value.asMessage.szMessage ); + + /* Now push current value of variable */ +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + /* push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); +#else + /* NOTE: this duplicate optimization requires that HB_P_MESSAGE + * reverts items on the stack ! + * duplicate object on the stack + */ + hb_compGenPCode1( HB_P_DUPLICATE ); +#endif + /* now send the message */ + hb_compGenMessage( pObj->value.asMessage.szMessage ); + hb_compGenPCode3( HB_P_FUNCTION, 0, 0 ); + +/* NOTE: COMPATIBILITY ISSUE: + * The above HARBOUR_STRICT_CLIPPER_COMPATIBILITY setting determines + * the way the chained send messages are handled. + * For example, the following code: + * + * a:b( COUNT() ):c += 1 + * + * will be handled as: + * + * a:b( COUNT() ):c := a:b( COUNT() ):c + 1 + * + * in strict Clipper compatibility mode and + * + * temp := a:b( COUNT() ), temp:c += 1 + * + * in non-strict mode. + * In practice in Clipper it will call COUNT() function two times: the + * first time before addition and the second one after addition - in Harbour, + * COUNT() function will be called only once, before addition. + * The Harbour (non-strict) method is: + * 1) faster + * 2) it guarantees that the same instance variable of the same object will + * be changed + */ + + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* increase operation */ + hb_compGenPCode1( bOpEq ); + + /* call pop message with one argument */ + hb_compGenPCode3( HB_P_FUNCTION, 1, 0 ); + } + /* TODO: add a special code for arrays to correctly handle a[ i++ ]++ + */ + else + { + /* push old value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* perform operation and duplicate the new value */ + hb_compGenPCode1( bOpEq ); + hb_compGenPCode1( HB_P_DUPLICATE ); + /* pop the new value into variable and leave the copy on the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); } } -void ValTypeReset( void ) +/* Generates pcodes for = syntax + * used standalone as a statement (it cannot leave the value on the stack) + */ +static void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) { - /* Clear the compile time stack values (should be empty at this point) */ - if( lStackTop > 1 ) - debug_msg2( "\n* *Compile time stack overflow: %i\n", lStackTop ); - lStackTop = 1; /* first position to store a value */ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; + + /* Push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + /* Push _message for later use */ + hb_compGenMessageData( pObj->value.asMessage.szMessage ); + + /* Now push current value of variable */ +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + /* push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); +#else + /* duplicate object on the stack */ + hb_compGenPCode1( HB_P_DUPLICATE ); +#endif + /* now send the message */ + hb_compGenMessage( pObj->value.asMessage.szMessage ); + hb_compGenPCode3( HB_P_FUNCTION, 0, 0 ); + + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* increase operation */ + hb_compGenPCode1( bOpEq ); + + /* call pop message with one argument */ + hb_compGenPCode3( HB_P_FUNCTION, 1, 0 ); + /* pop the value from the stack */ + hb_compGenPCode1( HB_P_POP ); + } + else + { + /* push old value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* add */ + hb_compGenPCode1( bOpEq ); + /* pop the new value into variable and remove it from the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } +} + +/* Generates the pcodes for pre- increment/decrement expressions + */ +static void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper ) +{ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; + + /* Push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); + /* Push _message for later use */ + hb_compGenMessageData( pObj->value.asMessage.szMessage ); + + /* Now push current value of variable */ +#ifdef HARBOUR_STRICT_CLIPPER_COMPATIBILITY + /* push object */ + HB_EXPR_USE( pObj->value.asMessage.pObject, HB_EA_PUSH_PCODE ); +#else + /* duplicate object on the stack */ + hb_compGenPCode1( HB_P_DUPLICATE ); +#endif + /* now send the message */ + hb_compGenMessage( pObj->value.asMessage.szMessage ); + hb_compGenPCode3( HB_P_FUNCTION, 0, 0 ); + + /* increase/decrease operation */ + hb_compGenPCode1( bOper ); + + /* call pop message with one argument - it leaves the value on the stack */ + hb_compGenPCode3( HB_P_FUNCTION, 1, 0 ); + } + else + { + /* Push current value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* Increment */ + hb_compGenPCode1( bOper ); + /* duplicate a value */ + hb_compGenPCode1( HB_P_DUPLICATE ); + /* pop new value and leave the duplicated copy of it on the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } +} + +/* Generates the pcodes for post- increment/decrement expressions + */ +static void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper ) +{ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + /* push current value - it will be a result of whole expression */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* now increment the value */ + hb_compExprPushPreOp( pSelf, bOper ); + /* pop the value from the stack */ + hb_compGenPCode1( HB_P_POP ); + } + else + { + /* Push current value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* Duplicate value */ + hb_compGenPCode1( HB_P_DUPLICATE ); + /* Increment */ + hb_compGenPCode1( bOper ); + /* pop new value from the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } +} + +/* Generates the pcodes for increment/decrement operations + * used standalone as a statement + */ +static void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper ) +{ + /* NOTE: an object instance variable needs special handling + */ + if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) + { + hb_compExprPushPreOp( pSelf, bOper ); + /* pop the value from the stack */ + hb_compGenPCode1( HB_P_POP ); + } + else + { + /* Push current value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* Increment */ + hb_compGenPCode1( bOper ); + /* pop new value from the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + } +} + +/* ************************************************************************* */ + +/* Create a new declaration for codeblock local variable + */ +static HB_CBVAR_PTR hb_compExprCBVarNew( char * szVarName, BYTE bType ) +{ + HB_CBVAR_PTR pVar = ( HB_CBVAR_PTR ) HB_XGRAB( sizeof( HB_CBVAR ) ); + + pVar->szName = szVarName; + pVar->bType = bType; + pVar->pNext = NULL; + + return pVar; +} + +/* NOTE: This deletes all linked variable + */ +static void hb_compExprCBVarDel( HB_CBVAR_PTR pVars ) +{ + HB_CBVAR_PTR pDel; + + if( pVars ) + { + while( pVars->pNext ) + { + pDel = pVars; + pVars = pVars->pNext; + /* HB_XFREE( pDel->szName ); */ /*TODO: memory releasing */ + HB_XFREE( pDel ); + } + HB_XFREE( pVars ); + } } diff --git a/harbour/source/compiler/genc.c b/harbour/source/compiler/genc.c index 3665ef9461..51212f3058 100644 --- a/harbour/source/compiler/genc.c +++ b/harbour/source/compiler/genc.c @@ -33,17 +33,13 @@ * */ -#include "extend.h" #include "compiler.h" -#include "pcode.h" -#include "hberrors.h" -#include "hbver.h" void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ { char szFileName[ _POSIX_PATH_MAX ]; - PFUNCTION pFunc = functions.pFirst, pFTemp; - PCOMSYMBOL pSym = symbols.pFirst; + PFUNCTION pFunc = hb_comp_functions.pFirst, pFTemp; + PCOMSYMBOL pSym = hb_comp_symbols.pFirst; USHORT w, wLen, wSym, wVar; USHORT iNestedCodeblock = 0; ULONG lPCodePos; @@ -59,11 +55,11 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ yyc = fopen( szFileName, "wb" ); if( ! yyc ) { - GenError( _szCErrors, 'E', ERR_CREATE_OUTPUT, szFileName, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_CREATE_OUTPUT, szFileName, NULL ); return; } - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) { printf( "\nGenerating C source output to \'%s\'... ", szFileName ); fflush( stdout ); @@ -81,7 +77,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "#include \"hb_vmpub.h\"\n" ); fprintf( yyc, "#include \"init.h\"\n\n\n" ); - if( ! _bStartProc ) + if( ! hb_comp_bStartProc ) pFunc = pFunc->pNext; /* No implicit starting procedure */ /* write functions prototypes for PRG defined functions */ @@ -90,18 +86,18 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ if( pFunc->cScope & FS_STATIC || pFunc->cScope & FS_INIT || pFunc->cScope & FS_EXIT ) fprintf( yyc, "static " ); - if( pFunc == _pInitFunc ) + if( pFunc == hb_comp_pInitFunc ) fprintf( yyc, "HARBOUR hb_INITSTATICS( void );\n" ); /* NOTE: hb_ intentionally in lower case */ else fprintf( yyc, "HARBOUR HB_%s( void );\n", pFunc->szName ); pFunc = pFunc->pNext; } /* write functions prototypes for called functions outside this PRG */ - pFunc = funcalls.pFirst; + pFunc = hb_comp_funcalls.pFirst; while( pFunc ) { pFTemp = GetFunction( pFunc->szName ); - if( ! pFTemp || pFTemp == functions.pFirst ) + if( ! pFTemp || pFTemp == hb_comp_functions.pFirst ) fprintf( yyc, "extern HARBOUR HB_%s( void );\n", pFunc->szName ); pFunc = pFunc->pNext; } @@ -110,9 +106,9 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ /* Generate the wrapper that will initialize local symbol table */ yy_strupr( pFileName->szName ); - fprintf( yyc, "\n\nHB_INIT_SYMBOLS_BEGIN( hb_vm_SymbolInit_%s%s )\n", _szPrefix, pFileName->szName ); + fprintf( yyc, "\n\nHB_INIT_SYMBOLS_BEGIN( hb_vm_SymbolInit_%s%s )\n", hb_comp_szPrefix, pFileName->szName ); - if( ! _bStartProc ) + if( ! hb_comp_bStartProc ) pSym = pSym->pNext; /* starting procedure is always the first symbol */ wSym = 0; /* symbols counter */ @@ -159,25 +155,25 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ } ++wSym; - if( pSym != symbols.pLast ) + if( pSym != hb_comp_symbols.pLast ) fprintf( yyc, ",\n" ); pSym = pSym->pNext; } - fprintf( yyc, "\nHB_INIT_SYMBOLS_END( hb_vm_SymbolInit_%s%s )\n", _szPrefix, pFileName->szName ); - fprintf( yyc, "#if ! defined(__GNUC__) && ! defined(_MSC_VER)\n #pragma startup hb_vm_SymbolInit_%s%s\n#endif\n\n\n", _szPrefix, pFileName->szName ); + fprintf( yyc, "\nHB_INIT_SYMBOLS_END( hb_vm_SymbolInit_%s%s )\n", hb_comp_szPrefix, pFileName->szName ); + fprintf( yyc, "#if ! defined(__GNUC__) && ! defined(_MSC_VER)\n #pragma startup hb_vm_SymbolInit_%s%s\n#endif\n\n\n", hb_comp_szPrefix, pFileName->szName ); /* Generate functions data */ - pFunc = functions.pFirst; - if( ! _bStartProc ) + pFunc = hb_comp_functions.pFirst; + if( ! hb_comp_bStartProc ) pFunc = pFunc->pNext; /* No implicit starting procedure */ while( pFunc ) { if( pFunc->cScope != FS_PUBLIC ) fprintf( yyc, "static " ); - if( pFunc == _pInitFunc ) /* Is it (_INITSTATICS) */ + if( pFunc == hb_comp_pInitFunc ) /* Is it (_INITSTATICS) */ fprintf( yyc, "HARBOUR hb_INITSTATICS( void )" ); /* NOTE: hb_ intentionally in lower case */ else fprintf( yyc, "HARBOUR HB_%s( void )", pFunc->szName ); @@ -195,13 +191,13 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ lPCodePos++; break; - case HB_P_ARRAYAT: - fprintf( yyc, "\tHB_P_ARRAYAT,\n" ); + case HB_P_ARRAYPUSH: + fprintf( yyc, "\tHB_P_ARRAYPUSH,\n" ); lPCodePos++; break; - case HB_P_ARRAYPUT: - fprintf( yyc, "\tHB_P_ARRAYPUT,\n" ); + case HB_P_ARRAYPOP: + fprintf( yyc, "\tHB_P_ARRAYPOP,\n" ); lPCodePos++; break; @@ -215,7 +211,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_ARRAYDIM, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i */", w ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i */", w ); fprintf( yyc, "\n" ); lPCodePos += 3; break; @@ -296,7 +292,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_FRAME, %i, %i,", bLocals - pFunc->wParamCount, pFunc->wParamCount ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* locals, params */" ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* locals, params */" ); fprintf( yyc, "\n" ); } lPCodePos += 3; @@ -320,7 +316,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_ARRAYGEN, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i */", w ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i */", w ); fprintf( yyc, "\n" ); lPCodePos += 3; break; @@ -348,11 +344,12 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ case HB_P_JUMP: /* if( 1 ) ( lPCodePos + 3 ) < pFunc->lPCodePos ) */ { - w = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; + SHORT sPos; + sPos = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; fprintf( yyc, "\tHB_P_JUMP, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", sPos, lPCodePos + ( sPos ? sPos : 3 ) ); fprintf( yyc, "\n" ); } lPCodePos += 3; @@ -363,7 +360,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_JUMPFALSE, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); fprintf( yyc, "\n" ); lPCodePos += 3; break; @@ -373,7 +370,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_JUMPTRUE, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); fprintf( yyc, "\n" ); lPCodePos += 3; break; @@ -389,13 +386,13 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ break; case HB_P_LINE: - if( _bGenCVerbose ) fprintf( yyc, "/* %05li */ ", lPCodePos ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "/* %05li */ ", lPCodePos ); else fprintf( yyc, "\t" ); w = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; fprintf( yyc, "HB_P_LINE, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i */", w ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i */", w ); fprintf( yyc, "\n" ); lPCodePos += 3; break; @@ -404,7 +401,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_LOCALNAME, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", ( char * ) pFunc->pCode + lPCodePos + 3 ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", ( char * ) pFunc->pCode + lPCodePos + 3 ); fprintf( yyc, "\n" ); lPCodePos += 3; while( pFunc->pCode[ lPCodePos ] ) @@ -428,7 +425,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_MESSAGE, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wSym )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wSym )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -441,9 +438,9 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ case HB_P_MODULENAME: fprintf( yyc, "\tHB_P_MODULENAME," ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", ( char * ) pFunc->pCode + lPCodePos + 1 ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", ( char * ) pFunc->pCode + lPCodePos++ + 1 ); fprintf( yyc, "\n" ); - lPCodePos++; + lPCodePos++; while( pFunc->pCode[ lPCodePos ] ) { chr = pFunc->pCode[ lPCodePos++ ]; @@ -496,7 +493,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ), pFunc->pCode[ lPCodePos + 3 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 4; } @@ -526,7 +523,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_POPALIASEDFIELD, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -541,7 +538,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_POPFIELD, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -562,7 +559,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_POPLOCAL, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* localvar%i */", -wVar ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* localvar%i */", -wVar ); fprintf( yyc, "\n" ); } else @@ -570,7 +567,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_POPLOCAL, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* codeblockvar%i */", wVar ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* codeblockvar%i */", wVar ); fprintf( yyc, "\n" ); } } @@ -579,7 +576,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_POPLOCAL, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetVar( pFunc->pLocals, wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetVar( pFunc->pLocals, wVar )->szName ); fprintf( yyc, "\n" ); } lPCodePos += 3; @@ -595,7 +592,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_POPMEMVAR, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -604,7 +601,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ case HB_P_POPSTATIC: { PVAR pVar; - PFUNCTION pTmp = functions.pFirst; + PFUNCTION pTmp = hb_comp_functions.pFirst; wVar = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; while( pTmp->pNext && pTmp->pNext->iStaticsBase < wVar ) @@ -613,7 +610,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_POPSTATIC, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", pVar->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", pVar->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -628,7 +625,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_POPVARIABLE, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -654,7 +651,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHALIASEDFIELD, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -666,7 +663,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHBLOCK, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i */", + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i */", pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 ); fprintf( yyc, "\n" ); @@ -675,14 +672,14 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\t%i, %i,", pFunc->pCode[ lPCodePos + 3 ], pFunc->pCode[ lPCodePos + 4 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* number of local parameters (%i) */", w ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* number of local parameters (%i) */", w ); fprintf( yyc, "\n" ); wVar = * ( ( USHORT * ) &( pFunc->pCode [ lPCodePos + 5 ] ) ); fprintf( yyc, "\t%i, %i,", pFunc->pCode[ lPCodePos + 5 ], pFunc->pCode[ lPCodePos + 6 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* number of local variables (%i) */", wVar ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* number of local variables (%i) */", wVar ); fprintf( yyc, "\n" ); lPCodePos += 7; /* codeblock size + number of parameters + number of local variables */ @@ -693,7 +690,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\t%i, %i,", pFunc->pCode[ lPCodePos ], pFunc->pCode[ lPCodePos + 1 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetVar( pFunc->pLocals, w )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetVar( pFunc->pLocals, w )->szName ); fprintf( yyc, "\n" ); lPCodePos +=2; } @@ -706,7 +703,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHDOUBLE, " ); for( i = 0; i < sizeof( double ) + sizeof( BYTE ); ++i ) fprintf( yyc, "%i,", ( ( BYTE * ) pFunc->pCode )[ lPCodePos + i ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %.*f, %d */", + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %.*f, %d */", *( ( BYTE * ) &( pFunc->pCode[ lPCodePos + sizeof( double ) ] ) ), *( ( double * ) &( pFunc->pCode[ lPCodePos ] ) ), *( ( BYTE * ) &( pFunc->pCode[ lPCodePos + sizeof( double ) ] ) ) ); @@ -725,7 +722,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHFIELD, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -735,7 +732,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHINT, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i */", + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i */", pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256 ); fprintf( yyc, "\n" ); @@ -757,7 +754,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHLOCAL, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* localvar%i */", -wVar ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* localvar%i */", -wVar ); fprintf( yyc, "\n" ); } else @@ -765,7 +762,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHLOCAL, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* codeblockvar%i */", wVar ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* codeblockvar%i */", wVar ); fprintf( yyc, "\n" ); } } @@ -774,7 +771,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHLOCAL, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetVar( pFunc->pLocals, wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetVar( pFunc->pLocals, wVar )->szName ); fprintf( yyc, "\n" ); } lPCodePos += 3; @@ -796,7 +793,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHLOCALREF, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* localvar%i */", -wVar ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* localvar%i */", -wVar ); fprintf( yyc, "\n" ); } else @@ -804,7 +801,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHLOCALREF, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* codeblockvar%i */", wVar ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* codeblockvar%i */", wVar ); fprintf( yyc, "\n" ); } } @@ -813,7 +810,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHLOCALREF, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetVar( pFunc->pLocals, wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetVar( pFunc->pLocals, wVar )->szName ); fprintf( yyc, "\n" ); } lPCodePos += 3; @@ -826,7 +823,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ pFunc->pCode[ lPCodePos + 2 ], pFunc->pCode[ lPCodePos + 3 ], pFunc->pCode[ lPCodePos + 4 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %li */", *( ( long * ) &( pFunc->pCode[ lPCodePos + 1 ] ) ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %li */", *( ( long * ) &( pFunc->pCode[ lPCodePos + 1 ] ) ) ); fprintf( yyc, "\n" ); lPCodePos += ( 1 + sizeof( long ) ); break; @@ -841,7 +838,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHMEMVAR, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -857,7 +854,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHMEMVARREF, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -876,7 +873,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ case HB_P_PUSHSTATIC: { PVAR pVar; - PFUNCTION pTmp = functions.pFirst; + PFUNCTION pTmp = hb_comp_functions.pFirst; wVar = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; while( pTmp->pNext && pTmp->pNext->iStaticsBase < wVar ) @@ -885,7 +882,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHSTATIC, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", pVar->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", pVar->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -894,7 +891,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ case HB_P_PUSHSTATICREF: { PVAR pVar; - PFUNCTION pTmp = functions.pFirst; + PFUNCTION pTmp = hb_comp_functions.pFirst; wVar = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; while( pTmp->pNext && pTmp->pNext->iStaticsBase < wVar ) @@ -903,7 +900,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHSTATICREF, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", pVar->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", pVar->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -915,18 +912,28 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHSTR, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i */", wLen ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i */", wLen ); lPCodePos +=3; if( wLen > 0 ) { + unsigned char uchr; + fprintf( yyc, "\n\t" ); while( wLen-- ) { - chr = pFunc->pCode[ lPCodePos++ ]; - if( chr == '\'' || chr == '\\') - fprintf( yyc, "\'\\%c\', ", chr ); + uchr = ( unsigned char ) ( pFunc->pCode[ lPCodePos++ ] ); + /* + * NOTE: After optimization some CHR(n) can be converted + * into a string containing nonprintable characters. + * + * TODO: add switch to use hexadecimal format "%#04x" + */ + if( ( uchr < (unsigned char) ' ' ) || ( uchr >= 127 ) ) + fprintf( yyc, "%i, ", uchr ); + else if( strchr( "\'\\\"", uchr ) ) + fprintf( yyc, "%i, ", uchr ); else - fprintf( yyc, "\'%c\', ", chr ); + fprintf( yyc, "\'%c\', ", uchr ); } } fprintf( yyc, "\n" ); @@ -942,7 +949,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHSYM, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wSym )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wSym )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -958,7 +965,7 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_PUSHVARIABLE, %i, %i,", HB_LOBYTE( wFixPos ), HB_HIBYTE( wFixPos ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %s */", GetSymbolOrd( wVar )->szName ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %s */", hb_compGetSymbolOrd( wVar )->szName ); fprintf( yyc, "\n" ); lPCodePos += 3; } @@ -974,19 +981,19 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fprintf( yyc, "\tHB_P_SEQBEGIN, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); fprintf( yyc, "\n" ); lPCodePos += 3; break; case HB_P_SEQEND: - if( _bGenCVerbose ) fprintf( yyc, "/* %05li */ ", lPCodePos ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "/* %05li */ ", lPCodePos ); else fprintf( yyc, "\t" ); w = pFunc->pCode[ lPCodePos + 1 ] + pFunc->pCode[ lPCodePos + 2 ] * 256; fprintf( yyc, "HB_P_SEQEND, %i, %i,", pFunc->pCode[ lPCodePos + 1 ], pFunc->pCode[ lPCodePos + 2 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* %i (abs: %05li) */", w, lPCodePos + ( w ? w : 3 ) ); fprintf( yyc, "\n" ); lPCodePos += 3; break; @@ -1000,11 +1007,11 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ /* we only generate it if there are statics used in this function */ if( pFunc->bFlags & FUN_USES_STATICS ) { - GetSymbol( _pInitFunc->szName, &w ); + hb_compGetSymbol( hb_comp_pInitFunc->szName, &w ); w = FixSymbolPos( w ); fprintf( yyc, "\tHB_P_SFRAME, %i, %i,", HB_LOBYTE( w ), HB_HIBYTE( w ) ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* symbol (_INITSTATICS) */" ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* symbol (_INITSTATICS) */" ); fprintf( yyc, "\n" ); } lPCodePos += 3; @@ -1012,14 +1019,14 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ case HB_P_STATICS: - GetSymbol( _pInitFunc->szName, &w ); + hb_compGetSymbol( hb_comp_pInitFunc->szName, &w ); w = FixSymbolPos( w ); fprintf( yyc, "\tHB_P_STATICS, %i, %i, %i, %i,", HB_LOBYTE( w ), HB_HIBYTE( w ), pFunc->pCode[ lPCodePos + 3 ], pFunc->pCode[ lPCodePos + 4 ] ); - if( _bGenCVerbose ) fprintf( yyc, "\t/* symbol (_INITSTATICS), %i statics */", pFunc->pCode[ lPCodePos + 3 ] + pFunc->pCode[ lPCodePos + 4 ] * 256 ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "\t/* symbol (_INITSTATICS), %i statics */", pFunc->pCode[ lPCodePos + 3 ] + pFunc->pCode[ lPCodePos + 4 ] * 256 ); fprintf( yyc, "\n" ); lPCodePos += 5; break; @@ -1049,13 +1056,13 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ if( bEndProcRequired ) { - if( _bGenCVerbose ) fprintf( yyc, "/* %05li */ ", lPCodePos ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "/* %05li */ ", lPCodePos ); else fprintf( yyc, "\t" ); fprintf( yyc, "HB_P_ENDPROC\n" ); } else { - if( _bGenCVerbose ) fprintf( yyc, "/* %05li */\n", lPCodePos ); + if( hb_comp_bGenCVerbose ) fprintf( yyc, "/* %05li */\n", lPCodePos ); } fprintf( yyc, " };\n\n" ); @@ -1065,22 +1072,22 @@ void GenCCode( PHB_FNAME pFileName ) /* generates the C language output */ fclose( yyc ); - pFunc = functions.pFirst; + pFunc = hb_comp_functions.pFirst; while( pFunc ) pFunc = KillFunction( pFunc ); - pFunc = funcalls.pFirst; + pFunc = hb_comp_funcalls.pFirst; while( pFunc ) { - funcalls.pFirst = pFunc->pNext; + hb_comp_funcalls.pFirst = pFunc->pNext; hb_xfree( ( void * ) pFunc ); /* NOTE: szName will be released by KillSymbol() */ - pFunc = funcalls.pFirst; + pFunc = hb_comp_funcalls.pFirst; } - pSym = symbols.pFirst; + pSym = hb_comp_symbols.pFirst; while( pSym ) pSym = KillSymbol( pSym ); - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) printf( "Done.\n" ); } diff --git a/harbour/source/compiler/genhrb.c b/harbour/source/compiler/genhrb.c index 9b12963888..a3d957e8b9 100644 --- a/harbour/source/compiler/genhrb.c +++ b/harbour/source/compiler/genhrb.c @@ -33,10 +33,7 @@ * */ -#include "extend.h" #include "compiler.h" -#include "pcode.h" -#include "hberrors.h" #define SYM_NOLINK 0 /* Symbol does not have to be linked */ #define SYM_FUNC 1 /* Defined function */ @@ -45,8 +42,8 @@ void GenPortObj( PHB_FNAME pFileName ) { char szFileName[ _POSIX_PATH_MAX ]; - PFUNCTION pFunc /*= functions.pFirst */; - PCOMSYMBOL pSym = symbols.pFirst; + PFUNCTION pFunc /*= hb_comp_functions.pFirst */; + PCOMSYMBOL pSym = hb_comp_symbols.pFirst; USHORT w, wLen, wVar; LONG lPCodePos; LONG lPad; @@ -62,11 +59,11 @@ void GenPortObj( PHB_FNAME pFileName ) yyc = fopen( szFileName, "wb" ); if( ! yyc ) { - GenError( _szCErrors, 'E', ERR_CREATE_OUTPUT, szFileName, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_CREATE_OUTPUT, szFileName, NULL ); return; } - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) { printf( "\nGenerating Harbour Portable Object output to \'%s\'... ", szFileName ); fflush( stdout ); @@ -74,7 +71,7 @@ void GenPortObj( PHB_FNAME pFileName ) /* writes the symbol table */ - if( ! _bStartProc ) + if( ! hb_comp_bStartProc ) pSym = pSym->pNext; /* starting procedure is always the first symbol */ lSymbols = 0; /* Count number of symbols */ @@ -88,8 +85,8 @@ void GenPortObj( PHB_FNAME pFileName ) fputc( ( BYTE ) ( ( lSymbols >> 16 ) & 255 ), yyc ); fputc( ( BYTE ) ( ( lSymbols >> 24 ) & 255 ), yyc ); - pSym = symbols.pFirst; - if( ! _bStartProc ) + pSym = hb_comp_symbols.pFirst; + if( ! hb_comp_bStartProc ) pSym = pSym->pNext; /* starting procedure is always the first symbol */ while( pSym ) @@ -121,8 +118,8 @@ void GenPortObj( PHB_FNAME pFileName ) pSym = pSym->pNext; } - pFunc = functions.pFirst; - if( ! _bStartProc ) + pFunc = hb_comp_functions.pFirst; + if( ! hb_comp_bStartProc ) pFunc = pFunc->pNext; lSymbols = 0; /* Count number of symbols */ @@ -138,8 +135,8 @@ void GenPortObj( PHB_FNAME pFileName ) /* Generate functions data */ - pFunc = functions.pFirst; - if( ! _bStartProc ) + pFunc = hb_comp_functions.pFirst; + if( ! hb_comp_bStartProc ) pFunc = pFunc->pNext; /* No implicit starting procedure */ while( pFunc ) @@ -166,8 +163,8 @@ void GenPortObj( PHB_FNAME pFileName ) switch( pFunc->pCode[ lPCodePos ] ) { case HB_P_AND: - case HB_P_ARRAYAT: - case HB_P_ARRAYPUT: + case HB_P_ARRAYPUSH: + case HB_P_ARRAYPOP: case HB_P_DEC: case HB_P_DIVIDE: case HB_P_DUPLICATE: @@ -339,7 +336,7 @@ void GenPortObj( PHB_FNAME pFileName ) /* we only generate it if there are statics used in this function */ if( pFunc->bFlags & FUN_USES_STATICS ) { - GetSymbol( _pInitFunc->szName, &w ); + hb_compGetSymbol( hb_comp_pInitFunc->szName, &w ); w = FixSymbolPos( w ); fputc( pFunc->pCode[ lPCodePos ], yyc ); fputc( HB_LOBYTE( w ), yyc ); @@ -351,7 +348,7 @@ void GenPortObj( PHB_FNAME pFileName ) break; case HB_P_STATICS: - GetSymbol( _pInitFunc->szName, &w ); + hb_compGetSymbol( hb_comp_pInitFunc->szName, &w ); w = FixSymbolPos( w ); fputc( pFunc->pCode[ lPCodePos ], yyc ); fputc( HB_LOBYTE( w ), yyc ); @@ -389,6 +386,7 @@ void GenPortObj( PHB_FNAME pFileName ) fclose( yyc ); - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) printf( "Done.\n" ); } + diff --git a/harbour/source/compiler/genjava.c b/harbour/source/compiler/genjava.c index 80ecb834c5..d11a4c5d36 100644 --- a/harbour/source/compiler/genjava.c +++ b/harbour/source/compiler/genjava.c @@ -52,8 +52,8 @@ static int _nChar = 0; void GenJava( PHB_FNAME pFileName ) { char szFileName[ _POSIX_PATH_MAX ]; - PFUNCTION pFunc /*= functions.pFirst */; - PCOMSYMBOL pSym = symbols.pFirst; + PFUNCTION pFunc /*= hb_comp_functions.pFirst */; + PCOMSYMBOL pSym = hb_comp_symbols.pFirst; USHORT w, wLen, wVar; LONG lPCodePos; LONG lPad; @@ -69,11 +69,11 @@ void GenJava( PHB_FNAME pFileName ) yyc = fopen( szFileName, "wb" ); if( ! yyc ) { - GenError( _szCErrors, 'E', ERR_CREATE_OUTPUT, szFileName, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_CREATE_OUTPUT, szFileName, NULL ); return; } - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) { printf( "\nGenerating Java source output to \'%s\'... ", szFileName ); fflush( stdout ); @@ -93,7 +93,7 @@ void GenJava( PHB_FNAME pFileName ) /* writes the symbol table */ - if( ! _bStartProc ) + if( ! hb_comp_bStartProc ) pSym = pSym->pNext; /* starting procedure is always the first symbol */ lSymbols = 0; /* Count number of symbols */ @@ -107,8 +107,8 @@ void GenJava( PHB_FNAME pFileName ) hb_fputc( ( BYTE ) ( ( lSymbols >> 16 ) & 255 ), yyc ); hb_fputc( ( BYTE ) ( ( lSymbols >> 24 ) & 255 ), yyc ); - pSym = symbols.pFirst; - if( ! _bStartProc ) + pSym = hb_comp_symbols.pFirst; + if( ! hb_comp_bStartProc ) pSym = pSym->pNext; /* starting procedure is always the first symbol */ while( pSym ) @@ -140,8 +140,8 @@ void GenJava( PHB_FNAME pFileName ) pSym = pSym->pNext; } - pFunc = functions.pFirst; - if( ! _bStartProc ) + pFunc = hb_comp_functions.pFirst; + if( ! hb_comp_bStartProc ) pFunc = pFunc->pNext; lSymbols = 0; /* Count number of symbols */ @@ -157,8 +157,8 @@ void GenJava( PHB_FNAME pFileName ) /* Generate functions data */ - pFunc = functions.pFirst; - if( ! _bStartProc ) + pFunc = hb_comp_functions.pFirst; + if( ! hb_comp_bStartProc ) pFunc = pFunc->pNext; /* No implicit starting procedure */ while( pFunc ) @@ -185,8 +185,8 @@ void GenJava( PHB_FNAME pFileName ) switch( pFunc->pCode[ lPCodePos ] ) { case HB_P_AND: - case HB_P_ARRAYAT: - case HB_P_ARRAYPUT: + case HB_P_ARRAYPUSH: + case HB_P_ARRAYPOP: case HB_P_DEC: case HB_P_DIVIDE: case HB_P_DUPLICATE: @@ -358,7 +358,7 @@ void GenJava( PHB_FNAME pFileName ) /* we only generate it if there are statics used in this function */ if( pFunc->bFlags & FUN_USES_STATICS ) { - GetSymbol( _pInitFunc->szName, &w ); + hb_compGetSymbol( hb_comp_pInitFunc->szName, &w ); w = FixSymbolPos( w ); hb_fputc( pFunc->pCode[ lPCodePos ], yyc ); hb_fputc( HB_LOBYTE( w ), yyc ); @@ -370,7 +370,7 @@ void GenJava( PHB_FNAME pFileName ) break; case HB_P_STATICS: - GetSymbol( _pInitFunc->szName, &w ); + hb_compGetSymbol( hb_comp_pInitFunc->szName, &w ); w = FixSymbolPos( w ); hb_fputc( pFunc->pCode[ lPCodePos ], yyc ); hb_fputc( HB_LOBYTE( w ), yyc ); @@ -415,7 +415,7 @@ void GenJava( PHB_FNAME pFileName ) fclose( yyc ); - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) printf( "Done.\n" ); } diff --git a/harbour/source/compiler/genobj32.c b/harbour/source/compiler/genobj32.c index 0abb93838f..e7b5c68abd 100644 --- a/harbour/source/compiler/genobj32.c +++ b/harbour/source/compiler/genobj32.c @@ -82,11 +82,11 @@ void GenObj32( PHB_FNAME pFileName ) if( ! ( hObjFile = fopen( szFileName, "wb" ) ) ) { - GenError( _szCErrors, 'E', ERR_CREATE_OUTPUT, szFileName, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_CREATE_OUTPUT, szFileName, NULL ); return; } - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) { printf( "\nGenerating Windows/DOS OBJ32 output to \'%s\'... ", szFileName ); fflush( stdout ); @@ -103,20 +103,20 @@ void GenObj32( PHB_FNAME pFileName ) fclose( hObjFile ); - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) printf( "Done.\n" ); } static ULONG GetSymbolsSize( void ) { - return ( symbols.iCount - ( _bStartProc ? 0: 1 ) ) * sizeof( HB_SYMB ); + return ( hb_comp_symbols.iCount - ( hb_comp_bStartProc ? 0: 1 ) ) * sizeof( HB_SYMB ); } static PCOMSYMBOL GetFirstSymbol( void ) { - PCOMSYMBOL pSymbol = symbols.pFirst; + PCOMSYMBOL pSymbol = hb_comp_symbols.pFirst; - if( ! _bStartProc ) + if( ! hb_comp_bStartProc ) pSymbol = pSymbol->pNext; return pSymbol; @@ -136,9 +136,9 @@ static char * GetSymbolName( ULONG ulPos ) static ULONG GetPCodesSize( void ) { ULONG ulTotal = 0; - PFUNCTION pFunction = functions.pFirst; + PFUNCTION pFunction = hb_comp_functions.pFirst; - if( ! _bStartProc ) + if( ! hb_comp_bStartProc ) pFunction = pFunction->pNext; while( pFunction ) @@ -260,9 +260,9 @@ static void GenerateDataSegment( FILE * hObjFile ) static void GenerateCodeSegment( FILE * hObjFile ) { - USHORT wFunctions = functions.iCount - ( _bStartProc ? 0: 1 ); + USHORT wFunctions = hb_comp_functions.iCount - ( hb_comp_bStartProc ? 0: 1 ); ULONG ulSize = wFunctions * sizeof( prgFunction ); - PFUNCTION pFunc = ( _bStartProc ? functions.pFirst: functions.pFirst->pNext ); + PFUNCTION pFunc = ( hb_comp_bStartProc ? hb_comp_functions.pFirst: hb_comp_functions.pFirst->pNext ); USHORT w = 0; DefineSegment( hObjFile, 2, /* "_TEXT" position + 1 into localNames */ @@ -299,10 +299,10 @@ static void GenerateExternals( FILE * hObjFile ) PFUNCTION pFunc, pFTemp; /* calculate amount of externals */ - pFunc = funcalls.pFirst; + pFunc = hb_comp_funcalls.pFirst; while( pFunc ) { - if( ! ( pFTemp = GetFunction( pFunc->szName ) ) || pFTemp == functions.pFirst ) + if( ! ( pFTemp = GetFunction( pFunc->szName ) ) || pFTemp == hb_comp_functions.pFirst ) wExternals++; pFunc = pFunc->pNext; } @@ -312,10 +312,10 @@ static void GenerateExternals( FILE * hObjFile ) w = 1; externNames[ 0 ] = "_hb_vmExecute"; - pFunc = funcalls.pFirst; + pFunc = hb_comp_funcalls.pFirst; while( pFunc ) { - if( ! ( pFTemp = GetFunction( pFunc->szName ) ) || pFTemp == functions.pFirst ) + if( ! ( pFTemp = GetFunction( pFunc->szName ) ) || pFTemp == hb_comp_functions.pFirst ) externNames[ w++ ] = pFunc->szName; pFunc = pFunc->pNext; } @@ -463,10 +463,10 @@ static void CodeSegment( FILE * hObjFile, BYTE * prgCode, ULONG ulPrgLen, USHORT USHORT y; USHORT wTotalLen = ( ulPrgLen * wFunctions ) + 4; ULONG ul; - PFUNCTION pFunction = functions.pFirst; - ULONG ulPCodeOffset = ( symbols.iCount - ( _bStartProc ? 0: 1 ) ) * sizeof( HB_SYMB ); + PFUNCTION pFunction = hb_comp_functions.pFirst; + ULONG ulPCodeOffset = ( hb_comp_symbols.iCount - ( hb_comp_bStartProc ? 0: 1 ) ) * sizeof( HB_SYMB ); - if( ! _bStartProc ) + if( ! hb_comp_bStartProc ) pFunction = pFunction->pNext; putbyte( 0xA0, hObjFile ); @@ -503,11 +503,11 @@ static void DataSegment( FILE * hObjFile, BYTE * symbol, USHORT wSymLen, USHORT USHORT w, y; USHORT wTotalLen = 4 + ulSize; PCOMSYMBOL pSymbol = GetFirstSymbol(); - PFUNCTION pFunction = functions.pFirst; + PFUNCTION pFunction = hb_comp_functions.pFirst; ULONG ulSymbolNameOffset = GetSymbolsSize() + GetPCodesSize(); ULONG ulFunctionOffset; - if( ! _bStartProc ) + if( ! hb_comp_bStartProc ) pFunction = pFunction->pNext; putbyte( 0xA0, hObjFile ); diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index ef942250fe..2bb7d794cb 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -33,23 +33,3351 @@ * */ -#include "hbsetup.h" +#include "compiler.h" #if defined(DOS) && defined(__BORLANDC__) #include extern unsigned _stklen = UINT_MAX; #endif -extern int harbour_main( int argc, char * argv[] ); +/* /ES command line setting types */ +#define HB_EXITLEVEL_DEFAULT 0 +#define HB_EXITLEVEL_SETEXIT 1 +#define HB_EXITLEVEL_DELTARGET 2 + +typedef enum +{ + LANG_C, /* C language (by default) */ + LANG_OBJ32, /* DOS/Windows 32 bits */ + LANG_JAVA, /* Java */ + LANG_PASCAL, /* Pascal */ + LANG_RESOURCES, /* Resources */ + LANG_PORT_OBJ /* Portable objects */ +} LANGUAGES; /* supported Harbour output languages */ + + + +extern int harbour_main( char *szName ); +extern int Include( char * szFileName, PATHNAMES * pSearchPath ); /* end #include support */ + + /* Following line added for preprocessor */ +extern void Hbpp_init ( void ); + +/* output related functions */ +extern void GenCCode( PHB_FNAME ); /* generates the C language output */ +extern void GenJava( PHB_FNAME ); /* generates the Java language output */ +extern void GenPascal( PHB_FNAME ); /* generates the Pascal language output */ +extern void GenRC( PHB_FNAME ); /* generates the RC language output */ +extern void GenPortObj( PHB_FNAME ); /* generates the portable objects */ +#ifdef HARBOUR_OBJ_GENERATION +extern void GenObj32( PHB_FNAME ); /* generates OBJ 32 bits */ +#endif + + /* Following two lines added for preprocessor */ +extern BOOL _bPPO; /* flag indicating, is ppo output needed */ +extern FILE *yyppo; /* output .ppo file */ + + +static void PrintUsage( char * ); +static void PrintCredits( void ); +static BOOL SwitchCmp( char * szString, char * szSwitch ); +static ULONG PackDateTime( void ); +static void AddSearchPath( char *, PATHNAMES * * ); /* add pathname to a search list */ +static char * RESERVED_FUNC( char * ); + +void EXTERNAL_LINKAGE close_on_exit( void ); + +extern int iLine; /* currently parsed file line number */ + +/* global variables */ +FILES hb_comp_files; +FUNCTIONS hb_comp_functions, hb_comp_funcalls; +SYMBOLS hb_comp_symbols; + + +PFUNCTION hb_comp_pInitFunc; +PHB_FNAME hb_comp_pFileName = NULL; +BOOL hb_comp_bStartProc = TRUE; /* holds if we need to create the starting procedure */ +BOOL hb_comp_bLineNumbers = TRUE; /* holds if we need pcodes with line numbers */ +BOOL hb_comp_bQuiet = FALSE; /* quiet mode */ +BOOL hb_comp_bRestrictSymbolLength = FALSE; /* generate 10 chars max symbols length */ +BOOL hb_comp_bShortCuts = TRUE; /* .and. & .or. expressions shortcuts */ +int hb_comp_iWarnings = 0; /* enable parse warnings */ +BOOL hb_comp_bAnyWarning = FALSE; /* holds if there was any warning during the compilation process */ +BOOL hb_comp_bAutoMemvarAssume = FALSE; /* holds if undeclared variables are automatically assumed MEMVAR (-a)*/ +BOOL hb_comp_bForceMemvars = FALSE; /* holds if memvars are assumed when accesing undeclared variable (-v)*/ +BOOL hb_comp_bDebugInfo = FALSE; /* holds if generate debugger required info */ +char hb_comp_szPrefix[ 20 ] = { '\0' }; /* holds the prefix added to the generated symbol init function name (in C output currently) */ +BOOL hb_comp_bGenCVerbose = TRUE; /* C code generation should be verbose (use comments) or not */ +int hb_comp_iExitLevel = HB_EXITLEVEL_DEFAULT; /* holds if there was any warning during the compilation process */ +PATHNAMES *hb_comp_pIncludePath = NULL; +int hb_comp_iFunctionCnt = 0; +int hb_comp_iErrorCount = 0; +char hb_comp_cVarType = ' '; /* current declared variable type */ +BOOL hb_comp_bDontGenLineNum = FALSE; /* suppress line number generation */ +LONG hb_comp_lLastPushPos = -1; /* position of last push pcode */ +ULONG hb_comp_ulLastLinePos = 0; /* position of last opcode with line number */ +ULONG hb_comp_ulMessageFix = 0; /* Position of the message which needs to be changed */ +ALIASID_PTR hb_comp_pAliasId = NULL; +int hb_comp_iStaticCnt = 0; /* number of defined statics variables on the PRG */ +BOOL hb_comp_bExternal = FALSE; +PTR_LOOPEXIT hb_comp_pLoops = NULL; +PEXTERN hb_comp_pExterns = NULL; +EXPLIST_PTR hb_comp_pExprList = NULL; /* stack used for parenthesized expressions */ +int hb_comp_iVarScope = VS_LOCAL; /* holds the scope for next variables to be defined */ + /* different values for hb_comp_iVarScope */ + +/* local variables */ +static PHB_FNAME s_pOutPath = NULL; +static BOOL s_bCredits = FALSE; /* print credits */ +static BOOL s_bLogo = TRUE; /* print logo */ +static BOOL s_bSyntaxCheckOnly = FALSE; /* syntax check only */ +static int s_iLanguage = LANG_C; /* default Harbour generated output language */ + + +/* Table with parse errors */ +char * hb_comp_szCErrors[] = +{ + "Statement not allowed outside of procedure or function", + "Redefinition of procedure or function: \'%s\'", + "Duplicate variable declaration: \'%s\'", + "%s declaration follows executable statement", + "Outer codeblock variable is out of reach: \'%s\'", + "Invalid numeric format '.'", + "Unterminated string: \'%s\'", + "Redefinition of predefined function %s: \'%s\'", + "Illegal variable \'%s\' initializer: \'%s\'", + "ENDIF does not match IF", + "ENDDO does not match WHILE", + "ENDCASE does not match DO CASE", + "NEXT does not match FOR", + "ELSE does not match IF", + "ELSEIF does not match IF", + "Syntax error: \'%s\'", + "Unclosed control structures", + "%s statement with no loop in sight", + "Syntax error: \'%s\' in: \'%s\'", + "Incomplete statement: %s", + "Incorrect number of arguments: %s %s", + "Invalid lvalue: \'%s\'", + "Invalid use of \'@\' (pass by reference): \'%s\'", + "Formal parameters already declared", + "Invalid %s from within of SEQUENCE code", + "Unterminated array index", + "Memory allocation error", + "Memory reallocation error", + "Freeing a NULL memory pointer", + "Syntax error: \"%s at \'%s\'\"", + "Jump offset too long", + "Can't create output file: \'%s\'", + "Can't create preprocessed output file: \'%s\'", + "Bad command line option: \'%s\'", + "Bad command line parameter: \'%s\'", + "Invalid filename: \'%s\'", + "Mayhem in CASE handler", + "Operation not supported for this data type: \'%s\'", + "Invalid alias expression: \'%s\'", + "Invalid array index expression: \'%s\'", + "Bound error: \'%s\'" +}; + +/* Table with parse warnings */ +/* NOTE: The first character stores the warning's level that triggers this + * warning. The warning's level is set by -w command line option. + */ +char * hb_comp_szCWarnings[] = +{ + "1Ambiguous reference: \'%s\'", + "1Ambiguous reference, assuming memvar: \'%s\'", + "2Variable: \'%s\' declared but not used in function: \'%s\'", + "2CodeBlock Parameter: \'%s\' declared but not used in function: \'%s\'", + "1RETURN statement with no return value in function", + "1Procedure returns value", + "1Function \'%s\' does not end with RETURN statement", + "3Incompatible type in assignment to: \'%s\' expected: \'%s\'", + "3Incompatible operand type: \'%s\' expected: \'Logical\'", + "3Incompatible operand type: \'%s\' expected: \'Numeric\'", + "3Incompatible operand types: \'%s\' and: \'%s\'", + "3Suspicious type in assignment to: \'%s\' expected: \'%s\'", + "3Suspicious operand type: \'UnKnown\' expected: \'%s\'", + "3Suspicious operand type: \'UnKnown\' expected: \'Logical\'", + "3Suspicious operand type: \'UnKnown\' expected: \'Numeric\'", + "0Meaningless use of expression: \'%s\'" +}; + +/* Table with reserved functions names + * NOTE: THIS TABLE MUST BE SORTED ALPHABETICALLY +*/ +static const char * _szReservedFun[] = { + "AADD" , + "ABS" , + "ASC" , + "AT" , + "BOF" , + "BREAK" , + "CDOW" , + "CHR" , + "CMONTH" , + "COL" , + "CTOD" , + "DATE" , + "DAY" , + "DELETED" , + "DEVPOS" , + "DOW" , + "DTOC" , + "DTOS" , + "EMPTY" , + "EOF" , + "EXP" , + "FCOUNT" , + "FIELDNAME" , + "FLOCK" , + "FOUND" , + "INKEY" , + "INT" , + "LASTREC" , + "LEFT" , + "LEN" , + "LOCK" , + "LOG" , + "LOWER" , + "LTRIM" , + "MAX" , + "MIN" , + "MONTH" , + "PCOL" , + "PCOUNT" , + "PROW" , + "QSELF" , + "RECCOUNT" , + "RECNO" , + "REPLICATE" , + "RLOCK" , + "ROUND" , + "ROW" , + "RTRIM" , + "SECONDS" , + "SELECT" , + "SETPOS" , + "SETPOSBS" , + "SPACE" , + "SQRT" , + "STR" , + "SUBSTR" , + "TIME" , + "TRANSFORM" , + "TRIM" , + "TYPE" , + "UPPER" , + "VAL" , + "WORD" , + "YEAR" +}; +#define RESERVED_FUNCTIONS sizeof( _szReservedFun ) / sizeof( char * ) + int main( int argc, char * argv[] ) { - return harbour_main( argc, argv ); + int iStatus = 0; + int iArg; + BOOL bSkipGen; + + /* Check for the nologo switch /q0 before everything else. */ + + for( iArg = 1; iArg < argc; iArg++ ) + { + if( SwitchCmp( argv[ iArg ], "Q0" ) ) + s_bLogo = FALSE; + + else if( SwitchCmp( argv[ iArg ], "CREDITS" ) || + SwitchCmp( argv[ iArg ], "CREDIT" ) || + SwitchCmp( argv[ iArg ], "CREDI" ) || + SwitchCmp( argv[ iArg ], "CRED" ) ) + s_bCredits = TRUE; + } + + if( s_bLogo ) + { + printf( "Harbour Compiler, Build %i%s (%04d.%02d.%02d)\n", + hb_build, hb_revision, hb_year, hb_month, hb_day ); + printf( "Copyright 1999, http://www.harbour-project.org\n" ); + } + + if( s_bCredits ) + { + PrintCredits(); + return iStatus; + } + + if( argc > 1 ) + { + char szFileName[ _POSIX_PATH_MAX ]; /* filename to parse */ + char szPpoName[ _POSIX_PATH_MAX ]; + + hb_comp_pFileName = NULL; + s_pOutPath = NULL; + + Hbpp_init(); /* Initialization of preprocessor arrays */ + /* Command line options */ + for( iArg = 1; iArg < argc; iArg++ ) + { + if( IS_OPT_SEP( argv[ iArg ][ 0 ] ) ) + { + switch( argv[ iArg ][ 1 ] ) + { + case '1': + if( argv[ iArg ][ 2 ] == '0' ) + hb_comp_bRestrictSymbolLength = TRUE; + break; + + case 'a': + case 'A': + /* variables declared by PRIVATE and PUBLIC statement are + * automatically assumed as MEMVAR + */ + hb_comp_bAutoMemvarAssume = TRUE; + break; + + case 'b': + case 'B': + hb_comp_bDebugInfo = TRUE; + hb_comp_bLineNumbers = TRUE; + break; + + case 'd': + case 'D': /* defines a Lex #define from the command line */ + { + unsigned int i = 0; + char * szDefText = yy_strdup( argv[ iArg ] + 2 ); + while( i < strlen( szDefText ) && szDefText[ i ] != '=' ) + i++; + if( szDefText[ i ] != '=' ) + AddDefine( szDefText, 0 ); + else + { + szDefText[ i ] = '\0'; + AddDefine( szDefText, szDefText + i + 1 ); + } + free( szDefText ); + } + break; + + case 'e': + case 'E': + + if( argv[ iArg ][ 2 ] == 's' || + argv[ iArg ][ 2 ] == 'S' ) + { + switch( argv[ iArg ][ 3 ] ) + { + case '\0': + case '0': + hb_comp_iExitLevel = HB_EXITLEVEL_DEFAULT; + break; + + case '1': + hb_comp_iExitLevel = HB_EXITLEVEL_SETEXIT; + break; + + case '2': + hb_comp_iExitLevel = HB_EXITLEVEL_DELTARGET; + break; + + default: + hb_compGenError( hb_comp_szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); + } + } + else + hb_compGenError( hb_comp_szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); + + break; + case 'g': + case 'G': + switch( argv[ iArg ][ 2 ] ) + { + case 'c': + case 'C': + s_iLanguage = LANG_C; + + switch( argv[ iArg ][ 3 ] ) + { + case '\0': + case '1': + hb_comp_bGenCVerbose = TRUE; + break; + + case '0': + hb_comp_bGenCVerbose = FALSE; + break; + + default: + hb_compGenError( hb_comp_szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); + } + break; + + case 'f': + case 'F': + s_iLanguage = LANG_OBJ32; + break; + + case 'j': + case 'J': + s_iLanguage = LANG_JAVA; + break; + + case 'p': + case 'P': + s_iLanguage = LANG_PASCAL; + break; + + case 'r': + case 'R': + s_iLanguage = LANG_RESOURCES; + break; + + case 'h': + case 'H': + s_iLanguage = LANG_PORT_OBJ; + break; + + default: + printf( "\nUnsupported output language option\n" ); + exit( EXIT_FAILURE ); + } + break; + + case 'i': + case 'I': + { + char * pPath; + char * pDelim; + char * szInclude; + + pPath = szInclude = yy_strdup( argv[ iArg ] + 2 ); + while( ( pDelim = strchr( pPath, OS_PATH_LIST_SEPARATOR ) ) != NULL ) + { + * pDelim = '\0'; + AddSearchPath( pPath, &hb_comp_pIncludePath ); + pPath = pDelim + 1; + } + AddSearchPath( pPath, &hb_comp_pIncludePath ); + } + break; + + case 'l': + case 'L': + hb_comp_bLineNumbers = FALSE; + break; + + case 'm': + case 'M': + /* TODO: Implement this switch */ + printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); + break; + + case 'n': + case 'N': + hb_comp_bStartProc = FALSE; + break; + + case 'o': + case 'O': + s_pOutPath = hb_fsFNameSplit( argv[ iArg ] + 2 ); + break; + + /* Added for preprocessor needs */ + case 'p': + case 'P': + _bPPO = TRUE; + break; + + case 'q': + case 'Q': + hb_comp_bQuiet = TRUE; + break; + + case 'r': + case 'R': + /* TODO: Implement this switch */ + printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); + break; + + case 's': + case 'S': + s_bSyntaxCheckOnly = TRUE; + break; + + case 't': + case 'T': + /* TODO: Implement this switch */ + printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); + break; + + case 'u': + case 'U': + /* TODO: Implement this switch */ + printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); + break; + + case 'v': + case 'V': + /* All undeclared variables are assumed MEMVAR variables + */ + hb_comp_bForceMemvars = TRUE; + break; + + case 'w': + case 'W': + hb_comp_iWarnings = 1; + if( argv[ iArg ][ 2 ] ) + { /*there is -w<0,1,2,3> probably */ + hb_comp_iWarnings = argv[ iArg ][ 2 ] - '0'; + if( hb_comp_iWarnings < 0 || hb_comp_iWarnings > 3 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); + } + break; + + case 'x': + case 'X': + { + if( strlen( argv[ iArg ] + 2 ) == 0 ) + sprintf( hb_comp_szPrefix, "%08lX_", PackDateTime() ); + else + { + strncpy( hb_comp_szPrefix, argv[ iArg ] + 2, 16 ); + hb_comp_szPrefix[ 16 ] = '\0'; + strcat( hb_comp_szPrefix, "_" ); + } + } + break; + +#ifdef YYDEBUG + case 'y': + case 'Y': + yydebug = TRUE; + break; +#endif + + case 'z': + case 'Z': + hb_comp_bShortCuts = FALSE; + break; + + default: + hb_compGenError( hb_comp_szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); + break; + } + } + else if( argv[ iArg ][ 0 ] == '@' ) + /* TODO: Implement this switch */ + printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); + else + { + if( hb_comp_pFileName ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_BADPARAM, argv[ iArg ], NULL ); + else + { + hb_comp_pFileName = hb_fsFNameSplit( argv[ iArg ] ); + + if( ! hb_comp_pFileName->szName ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_BADFILENAME, argv[ iArg ], NULL ); + } + } + } + + if( hb_comp_pFileName ) + { + if( !hb_comp_pFileName->szExtension ) + hb_comp_pFileName->szExtension = ".prg"; + hb_fsFNameMerge( szFileName, hb_comp_pFileName ); + if( _bPPO ) + { + hb_comp_pFileName->szExtension = ".ppo"; + hb_fsFNameMerge( szPpoName, hb_comp_pFileName ); + yyppo = fopen( szPpoName, "w" ); + if( ! yyppo ) + { + hb_compGenError( hb_comp_szCErrors, 'E', ERR_CREATE_PPO, szPpoName, NULL ); + return iStatus; + } + } + } + else + { + PrintUsage( argv[ 0 ] ); + return iStatus; + } + + atexit( close_on_exit ); + + hb_comp_files.iFiles = 0; /* initialize support variables */ + hb_comp_files.pLast = NULL; + hb_comp_functions.iCount = 0; + hb_comp_functions.pFirst = NULL; + hb_comp_functions.pLast = NULL; + hb_comp_funcalls.iCount = 0; + hb_comp_funcalls.pFirst = NULL; + hb_comp_funcalls.pLast = NULL; + hb_comp_symbols.iCount = 0; + hb_comp_symbols.pFirst = NULL; + hb_comp_symbols.pLast = NULL; + + hb_comp_pInitFunc = NULL; + hb_comp_bAnyWarning = FALSE; + + if( Include( szFileName, NULL ) ) + { + char * szInclude = getenv( "INCLUDE" ); + + if( szInclude ) + { + char * pPath; + char * pDelim; + + pPath = szInclude = yy_strdup( szInclude ); + while( ( pDelim = strchr( pPath, OS_PATH_LIST_SEPARATOR ) ) != NULL ) + { + *pDelim = '\0'; + AddSearchPath( pPath, &hb_comp_pIncludePath ); + pPath = pDelim + 1; + } + AddSearchPath( pPath, &hb_comp_pIncludePath ); + } + + /* + * Start processing + */ + harbour_main( hb_comp_pFileName->szName ); + + bSkipGen = FALSE; + + if( hb_comp_bAnyWarning ) + { + if( hb_comp_iExitLevel == HB_EXITLEVEL_SETEXIT ) + iStatus = 1; + if( hb_comp_iExitLevel == HB_EXITLEVEL_DELTARGET ) + { + iStatus = 1; + bSkipGen = TRUE; + printf( "\nNo code generated\n" ); + } + } + + if( ! s_bSyntaxCheckOnly && ! bSkipGen && ( hb_comp_iErrorCount == 0 ) ) + { + hb_comp_pFileName->szPath = NULL; + hb_comp_pFileName->szExtension = NULL; + + /* we create a the output file */ + if( s_pOutPath ) + { + if( s_pOutPath->szPath ) + hb_comp_pFileName->szPath = s_pOutPath->szPath; + if( s_pOutPath->szName ) + { + hb_comp_pFileName->szName = s_pOutPath->szName; + if( s_pOutPath->szExtension ) + hb_comp_pFileName->szExtension = s_pOutPath->szExtension; + } + } + + switch( s_iLanguage ) + { + case LANG_C: + GenCCode( hb_comp_pFileName ); + break; + + case LANG_OBJ32: +#ifdef HARBOUR_OBJ_GENERATION + GenObj32( hb_comp_pFileName ); +#endif + break; + + case LANG_JAVA: + GenJava( hb_comp_pFileName ); + break; + + case LANG_PASCAL: + GenPascal( hb_comp_pFileName ); + break; + + case LANG_RESOURCES: + GenRC( hb_comp_pFileName ); + break; + + case LANG_PORT_OBJ: + GenPortObj( hb_comp_pFileName ); + break; + } + } + + if( _bPPO ) + fclose( yyppo ); + } + else + { + printf( "Cannot open input file: %s\n", szFileName ); + iStatus = 1; + } + hb_xfree( ( void * ) hb_comp_pFileName ); + if( s_pOutPath ) + hb_xfree( s_pOutPath ); + + if( hb_comp_iErrorCount > 0 ) + iStatus = EXIT_FAILURE; + } + else + PrintUsage( argv[ 0 ] ); + + return iStatus; } +/* + * Prints available options +*/ +static void PrintUsage( char * szSelf ) +{ + printf( "\nSyntax: %s [options]" + "\n" + "\nOptions: /a automatic memvar declaration" + "\n /b debug info" + "\n /d[=] #define " + "\n /es[] set exit severity" + "\n /g output type generated is (see below)" + "\n /gc[] output type: C source (.c) (default)" + "\n : 0=without comments, 1=normal (default)" +#ifdef HARBOUR_OBJ_GENERATION + "\n /gf output type: Windows/DOS OBJ32 (.obj)" +#endif + "\n /gh output type: Harbour Portable Object (.hrb)" + "\n /gj output type: Java source (.java)" + "\n /gp output type: Pascal source (.pas)" + "\n /gr output type: Windows resource (.rc)" + "\n /i add #include file search path" + "\n /l suppress line number information" +/* TODO: "\n /m compile module only" */ + "\n /n no implicit starting procedure" + "\n /o object file drive and/or path" + "\n /p generate pre-processed output (.ppo) file" + "\n /q quiet" + "\n /q0 quiet and don't display program header" +/* TODO: "\n /r[] request linker to search (or none)" */ + "\n /s syntax check only" +/* TODO: "\n /t path for temp file creation" */ +/* TODO: "\n /u[] use command def set in (or none)" */ + "\n /v variables are assumed M->" + "\n /w[] set warning level number (0..3, default 1)" + "\n /x[] set symbol init function name prefix (for .c only)" +#ifdef YYDEBUG + "\n /y trace lex & yacc activity" +#endif + "\n /z suppress shortcutting (.and. & .or.)" + "\n /10 restrict symbol length to 10 characters" +/* TODO: "\n @ compile list of modules in " */ + "\n" + , szSelf ); +} + +/* + * Prints credits +*/ +static void PrintCredits( void ) +{ + printf( "\nCredits: The Harbour Team at www.harbour-project.com" + ); +} + + #if defined(__IBMCPP__) || defined(_MSC_VER) int isatty( int handle ) { return ( handle < 4 ) ? 1 : 0; } #endif + +static BOOL SwitchCmp( char * szString, char * szSwitch ) +{ + if( IS_OPT_SEP( *szString ) ) + { + szString++; + + if( strlen( szString ) == strlen( szSwitch ) ) + { + while( *szString != '\0' ) + { + if( toupper( *szString ) != *szSwitch ) + return FALSE; + + szString++; + szSwitch++; + } + + return TRUE; + } + } + + return FALSE; +} + +/* NOTE: Making the date and time info to fit into 32 bits can only be done + in a "lossy" way, in practice that means it's not possible to unpack + the exact date/time info from the resulting ULONG. Since the year + is only stored in 6 bits, 1980 will result in the same bit pattern + as 2044. The purpose of this value is only used to *differenciate* + between the dates ( the exact dates are not significant ), so this can + be used here without problems. */ + +/* 76543210765432107654321076543210 + |.......|.......|.......|....... + |____| Year 6 bits + |__| Month 4 bits + |___| Day 5 bits + |___| Hour 5 bits + |____| Minute 6 bits + |____| Second 6 bits */ + +static ULONG PackDateTime( void ) +{ + BYTE szString[ 4 ]; + BYTE nValue; + + time_t t; + struct tm * oTime; + + time( &t ); + oTime = localtime( &t ); + + nValue = ( BYTE ) ( ( ( oTime->tm_year + 1900 ) - 1980 ) & ( 2 ^ 6 ) ) ; /* 6 bits */ + szString[ 0 ] = nValue << 2; + nValue = ( BYTE ) ( oTime->tm_mon + 1 ); /* 4 bits */ + szString[ 0 ] |= nValue >> 2; + szString[ 1 ] = nValue << 6; + nValue = ( BYTE ) ( oTime->tm_mday ); /* 5 bits */ + szString[ 1 ] |= nValue << 1; + + nValue = ( BYTE ) oTime->tm_hour; /* 5 bits */ + szString[ 1 ] = nValue >> 4; + szString[ 2 ] = nValue << 4; + nValue = ( BYTE ) oTime->tm_min; /* 6 bits */ + szString[ 2 ] |= nValue >> 2; + szString[ 3 ] = nValue << 6; + nValue = ( BYTE ) oTime->tm_sec; /* 6 bits */ + szString[ 3 ] |= nValue; + + return HB_MKLONG( szString[ 3 ], szString[ 2 ], szString[ 1 ], szString[ 0 ] ); +} + +/* + * Function that adds specified path to the list of pathnames to search + */ +void AddSearchPath( char * szPath, PATHNAMES * * pSearchList ) +{ + PATHNAMES * pPath = *pSearchList; + + if( pPath ) + { + while( pPath->pNext ) + pPath = pPath->pNext; + pPath->pNext = ( PATHNAMES * ) hb_xgrab( sizeof( PATHNAMES ) ); + pPath = pPath->pNext; + } + else + { + *pSearchList = pPath = ( PATHNAMES * ) hb_xgrab( sizeof( PATHNAMES ) ); + } + pPath->pNext = NULL; + pPath->szPath = szPath; +} + +void EXTERNAL_LINKAGE close_on_exit( void ) +{ + PFILE pFile = hb_comp_files.pLast; + + while( pFile ) + { + fclose( pFile->handle ); + pFile = ( PFILE ) pFile->pPrev; + } +} + + + +/* ------------------------------------------------------------------------- */ + +#define IS_PATH_SEP( c ) ( strchr( OS_PATH_DELIMITER_LIST, ( c ) ) != NULL ) + +/* Split given filename into path, name and extension */ +PHB_FNAME hb_fsFNameSplit( char * szFileName ) +{ + PHB_FNAME pFileName = ( PHB_FNAME ) hb_xgrab( sizeof( HB_FNAME ) ); + + int iLen = strlen( szFileName ); + int iSlashPos; + int iDotPos; + int iPos; + + pFileName->szPath = + pFileName->szName = + pFileName->szExtension = NULL; + + iSlashPos = iLen - 1; + iPos = 0; + + while( iSlashPos >= 0 && !IS_PATH_SEP( szFileName[ iSlashPos ] ) ) + --iSlashPos; + + if( iSlashPos == 0 ) + { + /* root path -> \filename */ + pFileName->szBuffer[ 0 ] = OS_PATH_DELIMITER; + pFileName->szBuffer[ 1 ] = '\0'; + pFileName->szPath = pFileName->szBuffer; + iPos = 2; /* first free position after the slash */ + } + else if( iSlashPos > 0 ) + { + /* If we are after a drive letter let's keep the following backslash */ + if( IS_PATH_SEP( ':' ) && + ( szFileName[ iSlashPos ] == ':' || szFileName[ iSlashPos - 1 ] == ':' ) ) + { + /* path with separator -> d:\path\filename or d:path\filename */ + memcpy( pFileName->szBuffer, szFileName, iSlashPos + 1 ); + pFileName->szBuffer[ iSlashPos + 1 ] = '\0'; + iPos = iSlashPos + 2; /* first free position after the slash */ + } + else + { + /* path with separator -> path\filename */ + memcpy( pFileName->szBuffer, szFileName, iSlashPos ); + pFileName->szBuffer[ iSlashPos ] = '\0'; + iPos = iSlashPos + 1; /* first free position after the slash */ + } + + pFileName->szPath = pFileName->szBuffer; + } + + iDotPos = iLen - 1; + while( iDotPos > iSlashPos && szFileName[ iDotPos ] != '.' ) + --iDotPos; + + if( ( iDotPos - iSlashPos ) > 1 ) + { + /* the dot was found + * and there is at least one character between a slash and a dot + */ + if( iDotPos == iLen - 1 ) + { + /* the dot is the last character - use it as extension name */ + pFileName->szExtension = pFileName->szBuffer + iPos; + pFileName->szBuffer[ iPos++ ] = '.'; + pFileName->szBuffer[ iPos++ ] = '\0'; + } + else + { + pFileName->szExtension = pFileName->szBuffer + iPos; + /* copy rest of the string with terminating ZERO character */ + memcpy( pFileName->szExtension, szFileName + iDotPos + 1, iLen - iDotPos ); + iPos += iLen - iDotPos; + } + } + else + /* there is no dot in the filename or it is '.filename' */ + iDotPos = iLen; + + if( ( iDotPos - iSlashPos - 1 ) > 0 ) + { + pFileName->szName = pFileName->szBuffer + iPos; + memcpy( pFileName->szName, szFileName + iSlashPos + 1, iDotPos - iSlashPos - 1 ); + pFileName->szName[ iDotPos - iSlashPos - 1 ] = '\0'; + } + +/* DEBUG + printf( "\nFilename: %s\n", szFileName ); + printf( "\n szPath: %s\n", pFileName->szPath ); + printf( "\n szName: %s\n", pFileName->szName ); + printf( "\n szExt: %s\n", pFileName->szExtension ); +*/ + + return pFileName; +} + +/* This function joins path, name and extension into a string with a filename */ +char * hb_fsFNameMerge( char * szFileName, PHB_FNAME pFileName ) +{ + if( pFileName->szPath && pFileName->szPath[ 0 ] ) + { + /* we have not empty path specified */ + int iLen = strlen( pFileName->szPath ); + + strcpy( szFileName, pFileName->szPath ); + + /* if the path is a root directory then we don't need to add path separator */ + if( !( IS_PATH_SEP( pFileName->szPath[ 0 ] ) && pFileName->szPath[ 0 ] == '\0' ) ) + { + /* add the path separator only in cases: + * when a name doesn't start with it + * when the path doesn't end with it + */ + if( !( IS_PATH_SEP( pFileName->szName[ 0 ] ) || IS_PATH_SEP( pFileName->szPath[ iLen-1 ] ) ) ) + { + szFileName[ iLen++ ] = OS_PATH_DELIMITER; + szFileName[ iLen ] = '\0'; + } + } + if( pFileName->szName ) + strcpy( szFileName + iLen, pFileName->szName ); + } + else + { + if( pFileName->szName ) + strcpy( szFileName, pFileName->szName ); + } + + if( pFileName->szExtension ) + { + int iLen = strlen( szFileName ); + + if( !( pFileName->szExtension[ 0 ] == '.' || szFileName[ iLen - 1 ] == '.') ) + { + /* add extension separator only when extansion doesn't contain it */ + szFileName[ iLen++ ] = '.'; + szFileName[ iLen ] = '\0'; + } + strcpy( szFileName + iLen, pFileName->szExtension ); + } + +/* DEBUG + printf( "\nMERGE:\n" ); + printf( "\n szPath: %s\n", pFileName->szPath ); + printf( "\n szName: %s\n", pFileName->szName ); + printf( "\n szExt: %s\n", pFileName->szExtension ); + printf( "\nFilename result: %s\n", szFileName ); +*/ + + return szFileName; +} + +/* ------------------------------------------------------------------------- */ + +void * hb_xgrab( ULONG ulSize ) /* allocates fixed memory, exits on failure */ +{ + void * pMem = malloc( ulSize ); + + if( ! pMem ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_MEMALLOC, NULL, NULL ); + + return pMem; +} + +void * hb_xrealloc( void * pMem, ULONG ulSize ) /* reallocates memory */ +{ + void * pResult = realloc( pMem, ulSize ); + + if( ! pResult ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_MEMREALLOC, NULL, NULL ); + + return pResult; +} + +void hb_xfree( void * pMem ) /* frees fixed memory */ +{ + if( pMem ) + free( pMem ); + else + hb_compGenError( hb_comp_szCErrors, 'E', ERR_MEMFREE, NULL, NULL ); +} + +char * yy_strupr( char * p ) +{ + char * p1; + + for( p1 = p; * p1; p1++ ) + * p1 = toupper( * p1 ); + + return p; +} + +char * yy_strdup( char * p ) +{ + char * pDup; + int iLen; + + iLen = strlen( p ) + 1; + pDup = ( char * ) hb_xgrab( iLen ); + memcpy( pDup, p, iLen ); + + return pDup; +} + +/* ------------------------------------------------------------------------- */ + +void hb_compGenError( char* _szErrors[], char cPrefix, int iError, char * szError1, char * szError2 ) +{ + if( hb_comp_files.pLast != NULL && hb_comp_files.pLast->szFileName != NULL ) + printf( "\r%s(%i) ", hb_comp_files.pLast->szFileName, iLine ); + + printf( "Error %c%04i ", cPrefix, iError ); + printf( _szErrors[ iError - 1 ], szError1, szError2 ); + printf( "\n" ); + + hb_comp_iErrorCount++; +/* exit( EXIT_FAILURE ); */ +} + +void hb_compGenWarning( char* _szWarnings[], char cPrefix, int iWarning, char * szWarning1, char * szWarning2) +{ + char *szText = _szWarnings[ iWarning - 1 ]; + + if( (szText[ 0 ] - '0') <= hb_comp_iWarnings ) + { + printf( "\r%s(%i) ", hb_comp_files.pLast->szFileName, iLine ); + printf( "Warning %c%04i ", cPrefix, iWarning ); + printf( szText + 1, szWarning1, szWarning2 ); + printf( "\n" ); + + hb_comp_bAnyWarning = TRUE; /* report warnings at exit */ + } +} + +/* ------------------------------------------------------------------------- */ + +/* checks if passed string is a reserved function name + */ +static char * RESERVED_FUNC( char * szName ) +{ + USHORT wNum = 0; + int iFound = 1; + + while( wNum < RESERVED_FUNCTIONS && iFound ) + { + /* Compare first 4 characters + * If they are the same then compare the whole name + * SECO() is not allowed because of Clipper function SECONDS() + * however SECO32() is a valid name. + */ + iFound = strncmp( szName, _szReservedFun[ wNum ], 4 ); + if( iFound == 0 ) + iFound = strncmp( szName, _szReservedFun[ wNum ], strlen( szName ) ); + ++wNum; + } + if( iFound ) + return NULL; + else + return (char *) _szReservedFun[ wNum - 1 ]; +} + +/* NOTE: iMinParam = -1, means no checking */ +/* iMaxParam = -1, means no upper limit */ + +typedef struct +{ + char * cFuncName; /* function name */ + int iMinParam; /* min no of parms it needs */ + int iMaxParam; /* max no of parms need */ +} FUNCINFO, * PFUNCINFO; + +static FUNCINFO _StdFun[] = +{ + { "AADD" , 2, 2 }, + { "ABS" , 1, 1 }, + { "ASC" , 1, 1 }, + { "AT" , 2, 2 }, + { "BOF" , 0, 0 }, + { "BREAK" , 0, 1 }, + { "CDOW" , 1, 1 }, + { "CHR" , 1, 1 }, + { "CMONTH" , 1, 1 }, + { "COL" , 0, 0 }, + { "CTOD" , 1, 1 }, + { "DATE" , 0, 0 }, + { "DAY" , 1, 1 }, + { "DELETED" , 0, 0 }, + { "DEVPOS" , 2, 2 }, + { "DOW" , 1, 1 }, + { "DTOC" , 1, 1 }, + { "DTOS" , 1, 1 }, + { "EMPTY" , 1, 1 }, + { "EOF" , 0, 0 }, + { "EVAL" , 1, -1 }, + { "EXP" , 1, 1 }, + { "FCOUNT" , 0, 0 }, + { "FIELDNAME" , 1, 1 }, + { "FILE" , 1, 1 }, + { "FLOCK" , 0, 0 }, + { "FOUND" , 0, 0 }, + { "INKEY" , 0, 2 }, + { "INT" , 1, 1 }, + { "LASTREC" , 0, 0 }, + { "LEFT" , 2, 2 }, + { "LEN" , 1, 1 }, + { "LOCK" , 0, 0 }, + { "LOG" , 1, 1 }, + { "LOWER" , 1, 1 }, + { "LTRIM" , 1, 1 }, + { "MAX" , 2, 2 }, + { "MIN" , 2, 2 }, + { "MONTH" , 1, 1 }, + { "PCOL" , 0, 0 }, + { "PCOUNT" , 0, 0 }, + { "PROW" , 0, 0 }, + { "RECCOUNT" , 0, 0 }, + { "RECNO" , 0, 0 }, + { "REPLICATE" , 2, 2 }, + { "RLOCK" , 0, 0 }, + { "ROUND" , 2, 2 }, + { "ROW" , 0, 0 }, + { "RTRIM" , 1, 2 }, /* Second parameter is a Harbour extension */ + { "SECONDS" , 0, 0 }, + { "SELECT" , 0, 1 }, + { "SETPOS" , 2, 2 }, + { "SETPOSBS" , 0, 0 }, + { "SPACE" , 1, 1 }, + { "SQRT" , 1, 1 }, + { "STR" , 1, 3 }, + { "SUBSTR" , 2, 3 }, + { "TIME" , 0, 0 }, + { "TRANSFORM" , 2, 2 }, + { "TRIM" , 1, 2 }, /* Second parameter is a Harbour extension */ + { "TYPE" , 1, 1 }, + { "UPPER" , 1, 1 }, + { "VAL" , 1, 1 }, + { "VALTYPE" , 1, 1 }, + { "WORD" , 1, 1 }, + { "YEAR" , 1, 1 }, + { 0 , 0, 0 } +}; + +void hb_compCheckArgs( char * szFuncCall, int iArgs ) +{ + FUNCINFO * f = _StdFun; + int i = 0; + int iPos = -1; + int iCmp; + + while( f[ i ].cFuncName ) + { + iCmp = strncmp( szFuncCall, f[ i ].cFuncName, 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szFuncCall, f[ i ].cFuncName, strlen( szFuncCall ) ); + if( iCmp == 0 ) + { + iPos = i; + break; + } + else + ++i; + } + + if( iPos >= 0 && ( f[ iPos ].iMinParam != -1 ) ) + { + if( iArgs < f[ iPos ].iMinParam || ( f[ iPos ].iMaxParam != -1 && iArgs > f[ iPos ].iMaxParam ) ) + { + char szMsg[ 40 ]; + + if( f[ iPos ].iMaxParam == -1 ) + sprintf( szMsg, "\nPassed: %i, expected: at least %i", iArgs, f[ iPos ].iMinParam ); + else if( f[ iPos ].iMinParam == f[ iPos ].iMaxParam ) + sprintf( szMsg, "\nPassed: %i, expected: %i", iArgs, f[ iPos ].iMinParam ); + else + sprintf( szMsg, "\nPassed: %i, expected: %i - %i", iArgs, f[ iPos ].iMinParam, f[ iPos ].iMaxParam ); + + hb_compGenError( hb_comp_szCErrors, 'E', ERR_CHECKING_ARGS, szFuncCall, szMsg ); + + /* Clipper way */ + /* hb_compGenError( hb_comp_szCErrors, 'E', ERR_CHECKING_ARGS, szFuncCall, NULL ); */ + } + } +} + +/* ------------------------------------------------------------------------- */ +/** ACTIONS **/ +/* ------------------------------------------------------------------------- */ + +/* + * This function adds the name of called function into the list + * as they have to be placed on the symbol table later than the first + * public symbol + */ +PFUNCTION hb_compAddFunCall( char * szFunctionName ) +{ + PFUNCTION pFunc = FunctionNew( szFunctionName, 0 ); + + if( ! hb_comp_funcalls.iCount ) + { + hb_comp_funcalls.pFirst = pFunc; + hb_comp_funcalls.pLast = pFunc; + } + else + { + ( ( PFUNCTION ) hb_comp_funcalls.pLast )->pNext = pFunc; + hb_comp_funcalls.pLast = pFunc; + } + hb_comp_funcalls.iCount++; + + return pFunc; +} + +/* + * This function adds the name of external symbol into the list of externals + * as they have to be placed on the symbol table later than the first + * public symbol + */ +void hb_compAddExtern( char * szExternName ) /* defines a new extern name */ +{ + PEXTERN pExtern = ( PEXTERN ) hb_xgrab( sizeof( _EXTERN ) ), pLast; + + pExtern->szName = szExternName; + pExtern->pNext = NULL; + + if( hb_comp_pExterns == NULL ) + hb_comp_pExterns = pExtern; + else + { + pLast = hb_comp_pExterns; + while( pLast->pNext ) + pLast = pLast->pNext; + pLast->pNext = pExtern; + } +} + +void hb_compAddVar( char * szVarName, char cValueType ) +{ + PVAR pVar, pLastVar; + PFUNCTION pFunc = hb_comp_functions.pLast; + + if( ! hb_comp_bStartProc && hb_comp_functions.iCount <= 1 && hb_comp_iVarScope == VS_LOCAL ) + { + /* Variable declaration is outside of function/procedure body. + In this case only STATIC and PARAMETERS variables are allowed. */ + --iLine; + hb_compGenError( hb_comp_szCErrors, 'E', ERR_OUTSIDE, NULL, NULL ); + } + + /* check if we are declaring local/static variable after some + * executable statements + * Note: FIELD and MEMVAR are executable statements + */ + if( ( hb_comp_functions.pLast->bFlags & FUN_STATEMENTS ) && !( hb_comp_iVarScope == VS_FIELD || ( hb_comp_iVarScope & VS_MEMVAR ) ) ) + { + --iLine; + hb_compGenError( hb_comp_szCErrors, 'E', ERR_FOLLOWS_EXEC, ( hb_comp_iVarScope == VS_LOCAL ? "LOCAL" : "STATIC" ), NULL ); + } + + /* When static variable is added then hb_comp_functions.pLast points to function + * that will initialise variables. The function where variable is being + * defined is stored in pOwner member. + */ + if( hb_comp_iVarScope == VS_STATIC ) + pFunc = pFunc->pOwner; + + /* Check if a declaration of duplicated variable name is requested */ + if( pFunc->szName ) + { + /* variable defined in a function/procedure */ + CheckDuplVars( pFunc->pFields, szVarName, hb_comp_iVarScope ); + CheckDuplVars( pFunc->pStatics, szVarName, hb_comp_iVarScope ); + if( !( hb_comp_iVarScope == VS_PRIVATE || hb_comp_iVarScope == VS_PUBLIC ) ) + CheckDuplVars( pFunc->pMemvars, szVarName, hb_comp_iVarScope ); + } + else + /* variable defined in a codeblock */ + hb_comp_iVarScope = VS_PARAMETER; + CheckDuplVars( pFunc->pLocals, szVarName, hb_comp_iVarScope ); + + pVar = ( PVAR ) hb_xgrab( sizeof( VAR ) ); + pVar->szName = szVarName; + pVar->szAlias = NULL; + pVar->cType = hb_comp_cVarType; + pVar->iUsed = 0; + pVar->pNext = NULL; + + if( hb_comp_iVarScope & VS_MEMVAR ) + { + PCOMSYMBOL pSym; + USHORT wPos; + + if( hb_comp_bAutoMemvarAssume || hb_comp_iVarScope == VS_MEMVAR ) + { + /* add this variable to the list of MEMVAR variables + */ + if( ! pFunc->pMemvars ) + pFunc->pMemvars = pVar; + else + { + pLastVar = pFunc->pMemvars; + while( pLastVar->pNext ) + pLastVar = pLastVar->pNext; + pLastVar->pNext = pVar; + } + } + + switch( hb_comp_iVarScope ) + { + case VS_MEMVAR: + /* variable declared in MEMVAR statement */ + break; + case ( VS_PARAMETER | VS_PRIVATE ): + { + BOOL bNewParameter = FALSE; + + if( ++hb_comp_functions.pLast->wParamNum > hb_comp_functions.pLast->wParamCount ) + { + hb_comp_functions.pLast->wParamCount = hb_comp_functions.pLast->wParamNum; + bNewParameter = TRUE; + } + + pSym = hb_compGetSymbol( szVarName, &wPos ); /* check if symbol exists already */ + if( ! pSym ) + pSym = hb_compAddSymbol( yy_strdup( szVarName ), &wPos ); + pSym->cScope |= VS_MEMVAR; + hb_compGenPCode3( HB_P_PARAMETER, HB_LOBYTE( wPos ), HB_HIBYTE( wPos ) ); + hb_compGenPCode1( HB_LOBYTE( hb_comp_functions.pLast->wParamNum ) ); + + /* Add this variable to the local variables list - this will + * allow to use the correct positions for real local variables. + * The name of variable have to be hidden because we should + * not find this name on the local variables list. + * We have to use the new structure because it is used in + * memvars list already. + */ + if( bNewParameter ) + { + pVar = ( PVAR ) hb_xgrab( sizeof( VAR ) ); + pVar->szName = yy_strdup( szVarName ); + pVar->szAlias = NULL; + pVar->cType = cValueType; + pVar->iUsed = 0; + pVar->pNext = NULL; + pVar->szName[ 0 ] ='!'; + if( ! pFunc->pLocals ) + pFunc->pLocals = pVar; + else + { + pLastVar = pFunc->pLocals; + while( pLastVar->pNext ) + pLastVar = pLastVar->pNext; + pLastVar->pNext = pVar; + } + } + } + break; + case VS_PRIVATE: + { + hb_compPushSymbol( yy_strdup( "__MVPRIVATE" ), 1); + hb_compGenPushNil(); + hb_compPushSymbol( yy_strdup( szVarName ), 0 ); + hb_compGenDoProc( 1 ); + pSym = hb_compGetSymbol( szVarName, NULL ); + pSym->cScope |= VS_MEMVAR; + } + break; + case VS_PUBLIC: + { + hb_compPushSymbol( yy_strdup( "__MVPUBLIC" ), 1); + hb_compGenPushNil(); + hb_compPushSymbol( yy_strdup( szVarName ), 0 ); + hb_compGenDoProc( 1 ); + pSym = hb_compGetSymbol( szVarName, NULL ); + pSym->cScope |= VS_MEMVAR; + } + break; + } + } + else + { + switch( hb_comp_iVarScope ) + { + case VS_LOCAL: + case VS_PARAMETER: + { + USHORT wLocal = 1; + + if( ! pFunc->pLocals ) + pFunc->pLocals = pVar; + else + { + pLastVar = pFunc->pLocals; + while( pLastVar->pNext ) + { + pLastVar = pLastVar->pNext; + wLocal++; + } + pLastVar->pNext = pVar; + } + if( hb_comp_iVarScope == VS_PARAMETER ) + { + ++hb_comp_functions.pLast->wParamCount; + hb_comp_functions.pLast->bFlags |= FUN_USES_LOCAL_PARAMS; + } + if( hb_comp_bDebugInfo ) + { + hb_compGenPCode3( HB_P_LOCALNAME, HB_LOBYTE( wLocal ), HB_HIBYTE( wLocal ) ); + hb_compGenPCodeN( ( BYTE * )szVarName, strlen( szVarName ) ); + hb_compGenPCode1( 0 ); + } + } + break; + + case VS_STATIC: + if( ! pFunc->pStatics ) + pFunc->pStatics = pVar; + else + { + pLastVar = pFunc->pStatics; + while( pLastVar->pNext ) + pLastVar = pLastVar->pNext; + pLastVar->pNext = pVar; + } + break; + + case VS_FIELD: + if( ! pFunc->pFields ) + pFunc->pFields = pVar; + else + { + pLastVar = pFunc->pFields; + while( pLastVar->pNext ) + pLastVar = pLastVar->pNext; + pLastVar->pNext = pVar; + } + break; + } + + } +} + +PCOMSYMBOL hb_compAddSymbol( char * szSymbolName, USHORT * pwPos ) +{ + PCOMSYMBOL pSym = ( PCOMSYMBOL ) hb_xgrab( sizeof( COMSYMBOL ) ); + + pSym->szName = szSymbolName; + pSym->cScope = 0; + pSym->cType = hb_comp_cVarType; + pSym->pNext = NULL; + + if( ! hb_comp_symbols.iCount ) + { + hb_comp_symbols.pFirst = pSym; + hb_comp_symbols.pLast = pSym; + } + else + { + ( ( PCOMSYMBOL ) hb_comp_symbols.pLast )->pNext = pSym; + hb_comp_symbols.pLast = pSym; + } + hb_comp_symbols.iCount++; + + if( pwPos ) + *pwPos = hb_comp_symbols.iCount; + + /*if( hb_comp_cVarType != ' ') printf("\nDeclared %s as type %c at symbol %i\n", szSymbolName, hb_comp_cVarType, hb_comp_symbols.iCount );*/ + return pSym; +} + +/* Adds new alias to the alias stack + */ +void AliasAdd( ALIASID_PTR pAlias ) +{ + pAlias->pPrev = hb_comp_pAliasId; + hb_comp_pAliasId = pAlias; +} + +/* Restores previously selected alias + */ +void AliasRemove( void ) +{ + ALIASID_PTR pAlias = hb_comp_pAliasId; + + hb_comp_pAliasId = hb_comp_pAliasId->pPrev; + hb_xfree( pAlias ); +} + +/* Adds an integer workarea number into alias stack + */ +void AliasAddInt( int iWorkarea ) +{ + ALIASID_PTR pAlias = ( ALIASID_PTR ) hb_xgrab( sizeof( ALIASID ) ); + + pAlias->type = ALIAS_NUMBER; + pAlias->alias.iAlias = iWorkarea; + AliasAdd( pAlias ); +} + +/* Adds an expression into alias stack + */ +void AliasAddExp( void ) +{ + ALIASID_PTR pAlias = ( ALIASID_PTR ) hb_xgrab( sizeof( ALIASID ) ); + + pAlias->type = ALIAS_EVAL; + AliasAdd( pAlias ); +} + +/* Adds an alias name into alias stack + */ +void AliasAddStr( char * szAlias ) +{ + ALIASID_PTR pAlias = ( ALIASID_PTR ) hb_xgrab( sizeof( ALIASID ) ); + + pAlias->type = ALIAS_NAME; + pAlias->alias.szAlias = szAlias; + AliasAdd( pAlias ); +} + +/* Generates pcodes to store the current workarea number + */ +void AliasPush( void ) +{ + hb_compGenPCode1( HB_P_PUSHALIAS ); +} + +/* Generates pcodes to select the workarea number using current value + * from the eval stack + */ +void AliasPop( void ) +{ + hb_compGenPCode1( HB_P_POPALIAS ); +} + +/* Generates pcodes to swap two last items from the eval stack. + * Last item (after swaping) is next popped as current workarea + */ +void AliasSwap( void ) +{ + hb_compGenPCode1( HB_P_SWAPALIAS ); +} + +void Duplicate( void ) +{ + hb_compGenPCode1( HB_P_DUPLICATE ); +} + +void DupPCode( ULONG ulStart ) /* duplicates the current generated pcode from an offset */ +{ + ULONG w, wEnd = hb_comp_functions.pLast->lPCodePos - ulStart; + + for( w = 0; w < wEnd; w++ ) + hb_compGenPCode1( hb_comp_functions.pLast->pCode[ ulStart + w ] ); +} + +/* + * Starts a new expression in the parenthesized epressions list + */ +void ExpListPush( void ) +{ + EXPLIST_PTR pExp = ( EXPLIST_PTR ) hb_xgrab( sizeof( EXPLIST ) ); + + pExp->pNext = pExp->pPrev = NULL; + + /* Store the previous state on the stack */ + if( hb_comp_pExprList ) + { + hb_comp_pExprList->pNext = pExp; + pExp->pPrev = hb_comp_pExprList; + /* save currently used pcode buffer */ + hb_comp_pExprList->exprSize = hb_comp_functions.pLast->lPCodePos; + hb_comp_pExprList->exprPCode = hb_comp_functions.pLast->pCode; + } + hb_comp_pExprList = pExp; + + /* store current pcode buffer */ + pExp->prevPCode = hb_comp_functions.pLast->pCode; + pExp->prevSize = hb_comp_functions.pLast->lPCodeSize; + pExp->prevPos = hb_comp_functions.pLast->lPCodePos; + + /* and create the new one */ + hb_comp_functions.pLast->pCode = ( BYTE * ) hb_xgrab( PCODE_CHUNK ); + hb_comp_functions.pLast->lPCodeSize = PCODE_CHUNK; + hb_comp_functions.pLast->lPCodePos = 0; + + pExp->exprPCode = hb_comp_functions.pLast->pCode; +} + +/* + * Pops specified number of expressions from the stack + */ +void ExpListPop( int iExpCount ) +{ + EXPLIST_PTR pExp, pDel; + + /* save currently used pcode buffer */ + hb_comp_pExprList->exprSize = hb_comp_functions.pLast->lPCodePos; + hb_comp_pExprList->exprPCode = hb_comp_functions.pLast->pCode; + + /* find the first expression in the list */ + while( --iExpCount ) + hb_comp_pExprList = hb_comp_pExprList->pPrev; + + /* return to the original pcode buffer */ + hb_comp_functions.pLast->pCode = hb_comp_pExprList->prevPCode; + hb_comp_functions.pLast->lPCodeSize = hb_comp_pExprList->prevSize; + hb_comp_functions.pLast->lPCodePos = hb_comp_pExprList->prevPos; + + pExp = hb_comp_pExprList; + if( hb_comp_pExprList->pPrev ) + { + hb_comp_pExprList = hb_comp_pExprList->pPrev; + hb_comp_pExprList->pNext = NULL; + } + else + hb_comp_pExprList = NULL; + + while( pExp ) + { + if( pExp->exprSize ) + { + hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); + if( pExp->pNext ) + hb_compGenPCode1( HB_P_POP ); + } + else + { + /* exprN, , exprN1 + * in this context empty expression is not allowed + * + * NOTE: + * We don't have to generate this error - it is safe to continue + * pcode generation - in this case an empty expression will not + * generate any opcode + */ + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, ")", NULL ); + } + + hb_xfree( pExp->exprPCode ); + + pDel = pExp; + pExp = pExp->pNext; + hb_xfree( pDel ); + } +} + + +/* + * Function generates passed pcode for passed database field + */ +void FieldPCode( BYTE bPCode, char * szVarName ) +{ + USHORT wVar; + PCOMSYMBOL pVar; + + pVar = hb_compGetSymbol( szVarName, &wVar ); + if( ! pVar ) + pVar = hb_compAddSymbol( szVarName, &wVar ); + pVar->cScope |= VS_MEMVAR; + hb_compGenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ) ); +} + +/* + * This function creates and initialises the _FUNC structure + */ +PFUNCTION FunctionNew( char * szName, HB_SYMBOLSCOPE cScope ) +{ + PFUNCTION pFunc; + + pFunc = ( PFUNCTION ) hb_xgrab( sizeof( _FUNC ) ); + pFunc->szName = szName; + pFunc->cScope = cScope; + pFunc->pLocals = NULL; + pFunc->pStatics = NULL; + pFunc->pFields = NULL; + pFunc->pMemvars = NULL; + pFunc->pCode = NULL; + pFunc->lPCodeSize = 0; + pFunc->lPCodePos = 0; + pFunc->pNext = NULL; + pFunc->wParamCount = 0; + pFunc->wParamNum = 0; + pFunc->iStaticsBase = hb_comp_iStaticCnt; + pFunc->pOwner = NULL; + pFunc->bFlags = 0; + + hb_comp_lLastPushPos = -1; + + return pFunc; +} + +/* + * Stores a Clipper defined function/procedure + * szFunName - name of a function + * cScope - scope of a function + * iType - FUN_PROCEDURE if a procedure or 0 + */ +void hb_compFunDef( char * szFunName, HB_SYMBOLSCOPE cScope, int iType ) +{ + PCOMSYMBOL pSym; + PFUNCTION pFunc; + char * szFunction; + + FixReturns(); /* fix all previous function returns offsets */ + + pFunc = GetFunction( szFunName ); + if( pFunc ) + { + /* The name of a function/procedure is already defined */ + if( ( pFunc != hb_comp_functions.pFirst ) || hb_comp_bStartProc ) + /* it is not a starting procedure that was automatically created */ + hb_compGenError( hb_comp_szCErrors, 'E', ERR_FUNC_DUPL, szFunName, NULL ); + } + + szFunction = RESERVED_FUNC( szFunName ); + if( szFunction && !( hb_comp_functions.iCount==0 && !hb_comp_bStartProc ) ) + { + /* We are ignoring it when it is the name of PRG file and we are + * not creating implicit starting procedure + */ + hb_compGenError( hb_comp_szCErrors, 'E', ERR_FUNC_RESERVED, szFunction, szFunName ); + } + + hb_comp_iFunctionCnt++; + + pSym = hb_compGetSymbol( szFunName, NULL ); + if( ! pSym ) + /* there is not a symbol on the symbol table for this function name */ + pSym = hb_compAddSymbol( szFunName, NULL ); + + if( cScope != FS_PUBLIC ) +/* pSym->cScope = FS_PUBLIC; */ +/* else */ + pSym->cScope |= cScope; /* we may have a non public function and a object message */ + + pFunc = FunctionNew( szFunName, cScope ); + pFunc->bFlags |= iType; + + if( hb_comp_functions.iCount == 0 ) + { + hb_comp_functions.pFirst = pFunc; + hb_comp_functions.pLast = pFunc; + } + else + { + hb_comp_functions.pLast->pNext = pFunc; + hb_comp_functions.pLast = pFunc; + } + hb_comp_functions.iCount++; + + hb_comp_ulLastLinePos = 0; /* optimization of line numbers opcode generation */ + + hb_compGenPCode3( HB_P_FRAME, 0, 0 ); /* frame for locals and parameters */ + hb_compGenPCode3( HB_P_SFRAME, 0, 0 ); /* frame for statics variables */ + + if( hb_comp_bDebugInfo ) + { + hb_compGenPCode1( HB_P_MODULENAME ); + hb_compGenPCodeN( ( BYTE * )hb_comp_files.pLast->szFileName, strlen( hb_comp_files.pLast->szFileName ) ); + hb_compGenPCode1( ':' ); + hb_compGenPCodeN( ( BYTE * )szFunName, strlen( szFunName ) ); + hb_compGenPCode1( 0 ); + } +} + +void hb_compGenPushFunRef( char * szName ) +{ + HB_SYMBOL_UNUSED( szName ); /* TODO: */ +} + +void * GenElseIf( void * pFirst, ULONG ulOffset ) +{ + PELSEIF pElseIf = ( PELSEIF ) hb_xgrab( sizeof( _ELSEIF ) ), pLast; + + pElseIf->ulOffset = ulOffset; + pElseIf->pNext = 0; + + if( ! pFirst ) + pFirst = pElseIf; + else + { + pLast = ( PELSEIF ) pFirst; + while( pLast->pNext ) + pLast = pLast->pNext; + pLast->pNext = pElseIf; + } + return pFirst; +} + + +PFUNCTION KillFunction( PFUNCTION pFunc ) +{ + PFUNCTION pNext = pFunc->pNext; + PVAR pVar; + + while( pFunc->pLocals ) + { + pVar = pFunc->pLocals; + pFunc->pLocals = pVar->pNext; + + hb_xfree( ( void * ) pVar->szName ); + hb_xfree( ( void * ) pVar ); + } + + while( pFunc->pStatics ) + { + pVar = pFunc->pStatics; + pFunc->pStatics = pVar->pNext; + + hb_xfree( ( void * ) pVar->szName ); + hb_xfree( ( void * ) pVar ); + } + + while( pFunc->pFields ) + { + pVar = pFunc->pFields; + pFunc->pFields = pVar->pNext; + + hb_xfree( ( void * ) pVar->szName ); + if( pVar->szAlias ) + { + hb_xfree( ( void * ) pVar->szAlias ); + } + hb_xfree( ( void * ) pVar ); + } + + while( pFunc->pMemvars ) + { + pVar = pFunc->pMemvars; + pFunc->pMemvars = pVar->pNext; + + hb_xfree( ( void * ) pVar->szName ); + if( pVar->szAlias ) + { + hb_xfree( ( void * ) pVar->szAlias ); + } + hb_xfree( ( void * ) pVar ); + } + + hb_xfree( ( void * ) pFunc->pCode ); +/* hb_xfree( ( void * ) pFunc->szName ); The name will be released in KillSymbol() */ + hb_xfree( ( void * ) pFunc ); + + return pNext; +} + + +PCOMSYMBOL KillSymbol( PCOMSYMBOL pSym ) +{ + PCOMSYMBOL pNext = pSym->pNext; + + hb_xfree( ( void * ) pSym->szName ); + hb_xfree( ( void * ) pSym ); + + return pNext; +} + +void hb_compGenBreak( void ) +{ + hb_compPushSymbol( yy_strdup("BREAK"), 1 ); + hb_compGenPushNil(); +} + +void hb_compGenExterns( void ) /* generates the symbols for the EXTERN names */ +{ + PEXTERN pDelete; + + if( hb_comp_bDebugInfo ) + hb_compAddExtern( yy_strdup( "__DBGENTRY" ) ); + + while( hb_comp_pExterns ) + { + if( hb_compGetSymbol( hb_comp_pExterns->szName, NULL ) ) + { + if( ! GetFuncall( hb_comp_pExterns->szName ) ) + hb_compAddFunCall( hb_comp_pExterns->szName ); + } + else + { + hb_compAddSymbol( hb_comp_pExterns->szName, NULL ); + hb_compAddFunCall( hb_comp_pExterns->szName ); + } + pDelete = hb_comp_pExterns; + hb_comp_pExterns = hb_comp_pExterns->pNext; + hb_xfree( ( void * ) pDelete ); + } +} + +/* This function generates pcodes for IIF( expr1, expr2, expr3 ) + * or IF( expr1, expr2, expr3 ) + * + * NOTE: + * 'IF' followed by parenthesized expression containing 3 expressions + * is always interpreted as IF inlined - it is not possible to distinguish + * it from IF( expr1, expr2, expr3 ); ENDIF syntax + * (This behaviour is Clipper compatible) + */ +void GenIfInline( void ) +{ + EXPLIST_PTR pExp, pDel; + int iExpCount = 3; /* We are expecting 3 expressions here */ + BOOL bhb_compGenPCode; + + /* save currently used pcode buffer */ + hb_comp_pExprList->exprSize = hb_comp_functions.pLast->lPCodePos; + hb_comp_pExprList->exprPCode = hb_comp_functions.pLast->pCode; + + /* find the first expression in the list */ + while( --iExpCount ) + hb_comp_pExprList = hb_comp_pExprList->pPrev; + + /* return to the original pcode buffer */ + hb_comp_functions.pLast->pCode = hb_comp_pExprList->prevPCode; + hb_comp_functions.pLast->lPCodeSize = hb_comp_pExprList->prevSize; + hb_comp_functions.pLast->lPCodePos = hb_comp_pExprList->prevPos; + + /* Update the pointer for nested or next expressions */ + pExp = hb_comp_pExprList; + if( hb_comp_pExprList->pPrev ) + { + hb_comp_pExprList = hb_comp_pExprList->pPrev; + hb_comp_pExprList->pNext = NULL; + } + else + hb_comp_pExprList = NULL; + + bhb_compGenPCode = TRUE; + pDel = pExp; /* save it for later use */ + + /* pExp points now to pcode buffer for logical condition + */ + if( pExp->exprSize == 0 ) + { + /* The logical condition have to be specified. + * If it is empty then generate the syntax error + */ + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, ",", NULL ); + } + else if( pExp->exprSize == 1 ) + { + /* one byte opcode for logical condition - check if it is TRUE or FALSE + */ + if( pExp->exprPCode[ 0 ] == HB_P_TRUE ) + { + /* move to the second expression */ + pExp = pExp->pNext; + if( pExp->exprSize ) + hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); + else + hb_compGenPushNil(); /* IIF have to return some value */ + bhb_compGenPCode = FALSE; + } + else if( pExp->exprPCode[ 0 ] == HB_P_FALSE ) + { + /* move to the third expression */ + pExp = pExp->pNext; + pExp = pExp->pNext; + if( pExp->exprSize ) + hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); + else + hb_compGenPushNil(); /* IIF have to return some value */ + bhb_compGenPCode = FALSE; + } + } + + if( bhb_compGenPCode ) + { + /* generate pcodes for all expressions + */ + LONG lPosFalse, lPosEnd; + + hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); + lPosFalse = hb_compGenJumpFalse( 0 ); + + pExp = pExp->pNext; + if( pExp->exprSize ) + hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); + else + hb_compGenPushNil(); /* IIF have to return some value */ + lPosEnd = hb_compGenJump( 0 ); + hb_compGenJumpHere( lPosFalse ); + + pExp = pExp->pNext; + if( pExp->exprSize ) + hb_compGenPCodeN( pExp->exprPCode, pExp->exprSize ); + else + hb_compGenPushNil(); /* IIF have to return some value */ + hb_compGenJumpHere( lPosEnd ); + } + + while( pDel ) + { + pExp = pDel; + pDel = pDel->pNext; + hb_xfree( pExp->exprPCode ); + hb_xfree( pExp ); + } +} + + +PFUNCTION GetFuncall( char * szFunctionName ) /* returns a previously called defined function */ +{ + PFUNCTION pFunc = hb_comp_funcalls.pFirst; + + while( pFunc ) + { + if( ! strcmp( pFunc->szName, szFunctionName ) ) + return pFunc; + else + { + if( pFunc->pNext ) + pFunc = pFunc->pNext; + else + return NULL; + } + } + return NULL; +} + +PFUNCTION GetFunction( char * szFunctionName ) /* returns a previously defined function */ +{ + PFUNCTION pFunc = hb_comp_functions.pFirst; + + while( pFunc ) + { + if( ! strcmp( pFunc->szName, szFunctionName ) ) + return pFunc; + else + { + if( pFunc->pNext ) + pFunc = pFunc->pNext; + else + return NULL; + } + } + return NULL; +} + +PVAR GetVar( PVAR pVars, USHORT wOrder ) /* returns variable if defined or zero */ +{ + USHORT w = 1; + + while( pVars->pNext && w++ < wOrder ) + pVars = pVars->pNext; + + return pVars; +} + +USHORT GetVarPos( PVAR pVars, char * szVarName ) /* returns the order + 1 of a variable if defined or zero */ +{ + USHORT wVar = 1; + + while( pVars ) + { + if( pVars->szName && ! strcmp( pVars->szName, szVarName ) ) + { + /* TODO: This is not the best place to push the variable type + * in some cases it will be called two times for the same variable + */ + pVars->iUsed = 1; + return wVar; + } + else + { + if( pVars->pNext ) + { + pVars = pVars->pNext; + wVar++; + } + else + return 0; + } + } + return 0; +} + +int GetLocalVarPos( char * szVarName ) /* returns the order + 1 of a variable if defined or zero */ +{ + int iVar = 0; + PFUNCTION pFunc = hb_comp_functions.pLast; + + if( pFunc->szName ) + /* we are in a function/procedure -we don't need any tricks */ + return GetVarPos( pFunc->pLocals, szVarName ); + else + { + /* we are in a codeblock */ + iVar = GetVarPos( pFunc->pLocals, szVarName ); + if( iVar == 0 ) + { + /* this is not a current codeblock parameter + * we have to check the list of nested codeblocks up to a function + * where the codeblock is defined + */ + PFUNCTION pOutBlock = pFunc; /* the outermost codeblock */ + + pFunc = pFunc->pOwner; + while( pFunc ) + { + iVar = GetVarPos( pFunc->pLocals, szVarName ); + if( iVar ) + { + if( pFunc->pOwner ) + { + /* this variable is defined in a parent codeblock + * It is not possible to access a parameter of a codeblock in which + * the current codeblock is defined + */ + hb_compGenError( hb_comp_szCErrors, 'E', ERR_OUTER_VAR, szVarName, NULL ); + } + else + { + /* We want to access a local variable defined in a function + * that owns this codeblock. We cannot access this variable in + * a normal way because at runtime the stack base will point + * to local variables of EVAL function. + * The codeblock cannot have static variables then we can + * use this structure to store temporarily all referenced + * local variables + */ + /* NOTE: The list of local variables defined in a function + * and referenced in a codeblock will be stored in a outer + * codeblock only. This makes sure that all variables will be + * detached properly - the inner codeblock can be created + * outside of a function where it was defined when the local + * variables are not accessible. + */ + iVar = -GetVarPos( pOutBlock->pStatics, szVarName ); + if( iVar == 0 ) + { + /* this variable was not referenced yet - add it to the list */ + PVAR pVar; + + pVar = ( PVAR ) hb_xgrab( sizeof( VAR ) ); + pVar->szName = szVarName; + pVar->cType = ' '; + pVar->iUsed = 0; + pVar->pNext = NULL; + + /* Use negative order to signal that we are accessing a local + * variable from a codeblock + */ + iVar = -1; /* first variable */ + if( ! pOutBlock->pStatics ) + pOutBlock->pStatics = pVar; + else + { + PVAR pLastVar = pOutBlock->pStatics; + + --iVar; /* this will be at least second variable */ + while( pLastVar->pNext ) + { + pLastVar = pLastVar->pNext; + --iVar; + } + pLastVar->pNext = pVar; + } + } + return iVar; + } + } + pOutBlock = pFunc; + pFunc = pFunc->pOwner; + } + } + } + return iVar; +} + +/* + * Gets position of passed static variables. + * All static variables are hold in a single array at runtime then positions + * are numbered for whole PRG module. + */ +int GetStaticVarPos( char * szVarName ) +{ + int iPos; + PFUNCTION pFunc = hb_comp_functions.pLast; + + /* First we have to check if this name belongs to a static variable + * defined in current function + */ + if( pFunc->pOwner ) + pFunc = pFunc->pOwner; /* we are in the static variable definition state */ + iPos = GetVarPos( pFunc->pStatics, szVarName ); + if( iPos ) + return iPos + pFunc->iStaticsBase; + + /* Next we have to check the list of global static variables + * Note: It is not possible to have global static variables when + * implicit starting procedure is defined + */ + if( !hb_comp_bStartProc ) + { + iPos = GetVarPos( hb_comp_functions.pFirst->pStatics, szVarName ); + if( iPos ) + return iPos; + } + return 0; +} + +/* Checks if passed variable name is declared as FIELD + * Returns 0 if not found in FIELD list or its position in this list if found + */ +int GetFieldVarPos( char * szVarName, PFUNCTION pFunc ) +{ + int iVar; + + if( pFunc->szName ) + /* we are in a function/procedure -we don't need any tricks */ + iVar = GetVarPos( pFunc->pFields, szVarName ); + else + { + /* we have to check the list of nested codeblock up to a function + * where the codeblock is defined + */ + while( pFunc->pOwner ) + pFunc = pFunc->pOwner; + iVar = GetVarPos( pFunc->pFields, szVarName ); + } + return iVar; +} + +/* Checks if passed variable name is declared as MEMVAR + * Returns 0 if not found in MEMVAR list or its position in this list if found + */ +int GetMemvarPos( char * szVarName, PFUNCTION pFunc ) +{ + int iVar; + + if( pFunc->szName ) + /* we are in a function/procedure -we don't need any tricks */ + iVar = GetVarPos( pFunc->pMemvars, szVarName ); + else + { + /* we have to check the list of nested codeblock up to a function + * where the codeblock is defined + */ + while( pFunc->pOwner ) + pFunc = pFunc->pOwner; + iVar = GetVarPos( pFunc->pMemvars, szVarName ); + } + return iVar; +} + +USHORT FixSymbolPos( USHORT wCompilePos ) +{ + return ( hb_comp_bStartProc ? wCompilePos - 1 : wCompilePos - 2 ); +} + + +/* returns a symbol pointer from the symbol table + * and sets its position in the symbol table + */ +PCOMSYMBOL hb_compGetSymbol( char * szSymbolName, USHORT * pwPos ) +{ + PCOMSYMBOL pSym = hb_comp_symbols.pFirst; + USHORT wCnt = 1; + + if( pwPos ) + *pwPos = 0; + while( pSym ) + { + if( ! strcmp( pSym->szName, szSymbolName ) ) + { + if( pwPos ) + *pwPos = wCnt; + return pSym; + } + else + { + if( pSym->pNext ) + { + pSym = pSym->pNext; + ++wCnt; + } + else + return NULL; + } + } + return NULL; +} + +PCOMSYMBOL hb_compGetSymbolOrd( USHORT wSymbol ) /* returns a symbol based on its index on the symbol table */ +{ + PCOMSYMBOL pSym = hb_comp_symbols.pFirst; + USHORT w = 1; + + while( w++ < wSymbol && pSym->pNext ) + pSym = pSym->pNext; + + return pSym; +} + +USHORT GetFunctionPos( char * szFunctionName ) /* return 0 if not found or order + 1 */ +{ + PFUNCTION pFunc = hb_comp_functions.pFirst; + USHORT wFunction = hb_comp_bStartProc; + + while( pFunc ) + { + if( ! strcmp( pFunc->szName, szFunctionName ) && pFunc != hb_comp_functions.pFirst ) + return wFunction; + else + { + if( pFunc->pNext ) + { + pFunc = pFunc->pNext; + wFunction++; + } + else + return 0; + } + } + return 0; +} + +void Inc( void ) +{ + hb_compGenPCode1( HB_P_INC ); +} + +ULONG hb_compGenJump( LONG lOffset ) +{ + /* TODO: We need a longer offset (longer then two bytes) + */ + if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_JUMP_TOO_LONG, NULL, NULL ); + + hb_compGenPCode3( HB_P_JUMP, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ) ); + + return hb_comp_functions.pLast->lPCodePos - 2; +} + +ULONG hb_compGenJumpFalse( LONG lOffset ) +{ + /* TODO: We need a longer offset (longer then two bytes) + */ + if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_JUMP_TOO_LONG, NULL, NULL ); + + hb_compGenPCode3( HB_P_JUMPFALSE, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ) ); + + return hb_comp_functions.pLast->lPCodePos - 2; +} + +void hb_compGenJumpThere( ULONG ulFrom, ULONG ulTo ) +{ + BYTE * pCode = hb_comp_functions.pLast->pCode; + LONG lOffset = ulTo - ulFrom + 1; + + /* TODO: We need a longer offset (longer then two bytes) + */ + if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_JUMP_TOO_LONG, NULL, NULL ); + + pCode[ ( ULONG ) ulFrom ] = HB_LOBYTE( lOffset ); + pCode[ ( ULONG ) ulFrom + 1 ] = HB_HIBYTE( lOffset ); +} + +void hb_compGenJumpHere( ULONG ulOffset ) +{ + hb_compGenJumpThere( ulOffset, hb_comp_functions.pLast->lPCodePos ); +} + +ULONG hb_compGenJumpTrue( LONG lOffset ) +{ + /* TODO: We need a longer offset (longer then two bytes) + */ + if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_JUMP_TOO_LONG, NULL, NULL ); + hb_compGenPCode3( HB_P_JUMPTRUE, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ) ); + + return hb_comp_functions.pLast->lPCodePos - 2; +} + +void Line( void ) /* generates the pcode with the currently compiled source code line */ +{ + if( hb_comp_bLineNumbers && ! hb_comp_bDontGenLineNum ) + { + if( ( ( hb_comp_functions.pLast->lPCodePos - hb_comp_ulLastLinePos ) > 3 ) || hb_comp_bDebugInfo ) + { + hb_comp_ulLastLinePos = hb_comp_functions.pLast->lPCodePos; + hb_compGenPCode3( HB_P_LINE, HB_LOBYTE( iLine ), HB_HIBYTE( iLine ) ); + } + else + { + hb_comp_functions.pLast->pCode[ hb_comp_ulLastLinePos +1 ] = HB_LOBYTE( iLine ); + hb_comp_functions.pLast->pCode[ hb_comp_ulLastLinePos +2 ] = HB_HIBYTE( iLine ); + } + } + hb_comp_bDontGenLineNum = FALSE; + hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; /* clear RETURN flag */ + hb_comp_lLastPushPos = -1; +} + +/* Generates the pcode with the currently compiled source code line + * if debug code was requested only + */ +void LineDebug( void ) +{ + if( hb_comp_bDebugInfo ) + Line(); + else + hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; /* clear RETURN flag */ +} + +void LineBody( void ) /* generates the pcode with the currently compiled source code line */ +{ + /* This line can be placed inside a procedure or function only */ + /* except EXTERNAL */ + if( ! hb_comp_bExternal ) + { + hb_comp_bExternal = FALSE; + if( ! hb_comp_bStartProc && hb_comp_functions.iCount <= 1 ) + { + hb_compGenError( hb_comp_szCErrors, 'E', ERR_OUTSIDE, NULL, NULL ); + } + } + + hb_comp_functions.pLast->bFlags |= FUN_STATEMENTS; + Line(); +} + +/* + * Function generates passed pcode for passed variable name + */ +void VariablePCode( BYTE bPCode, char * szVarName ) +{ + USHORT wVar; + PCOMSYMBOL pSym; + PFUNCTION pOwnerFunc = NULL; + int iType = VS_LOCAL; /* not really */ + + /* Check if it is a FIELD declared in current function + */ + wVar = GetFieldVarPos( szVarName, hb_comp_functions.pLast ); + if( wVar == 0 ) + { + /* Check if it is a MEMVAR declared in current function + */ + wVar = GetMemvarPos( szVarName, hb_comp_functions.pLast ); + if( wVar ) + iType = VS_MEMVAR; + } + else + { + iType = VS_FIELD; + pOwnerFunc = hb_comp_functions.pLast; + } + + /* if it is not declared in current function then check if it is + * a symbol with file wide scope + */ + if( wVar == 0 && ! hb_comp_bStartProc ) + { + wVar = GetFieldVarPos( szVarName, hb_comp_functions.pFirst ); + if( wVar == 0 ) + { + wVar = GetMemvarPos( szVarName, hb_comp_functions.pFirst ); + if( wVar ) + iType = VS_MEMVAR; + } + else + { + iType = VS_FIELD; + pOwnerFunc = hb_comp_functions.pFirst; + } + } + + if( wVar == 0 ) + { + /* This is undeclared variable */ + /* + * NOTE: + * Clipper always assumes a memvar variable if undeclared variable + * is popped (a value is asssigned to a variable). + * + */ +#if defined( HARBOUR_STRICT_CLIPPER_COMPATIBILITY ) + if( hb_comp_bForceMemvars || bPCode == HB_P_POPVARIABLE ) +#else + if( hb_comp_bForceMemvars ) +#endif + { + /* -v switch was used -> assume it is a memvar variable + */ + iType = VS_MEMVAR; + hb_compGenWarning( hb_comp_szCWarnings, 'W', WARN_MEMVAR_ASSUMED, szVarName, NULL ); + } + else + hb_compGenWarning( hb_comp_szCWarnings, 'W', WARN_AMBIGUOUS_VAR, szVarName, NULL ); + } + + if( iType == VS_FIELD ) + { /* variable is declared using FIELD statement */ + PVAR pField = GetVar( pOwnerFunc->pFields, wVar ); + + if( pField->szAlias ) + { /* the alias was specified in FIELD declaration */ + if( bPCode == HB_P_POPVARIABLE ) + bPCode = HB_P_POPALIASEDFIELD; + else if( bPCode == HB_P_PUSHVARIABLE ) + bPCode = HB_P_PUSHALIASEDFIELD; + else + /* pushing fields by reference is not allowed */ + hb_compGenError( hb_comp_szCErrors, 'E', ERR_INVALID_REFER, szVarName, NULL ); + /* + * Push alias symbol before the field symbol + */ + hb_compPushSymbol( yy_strdup( pField->szAlias ), 0 ); + } + else + { /* this is unaliased field */ + if( bPCode == HB_P_POPVARIABLE ) + bPCode = HB_P_POPFIELD; + else if( bPCode == HB_P_PUSHVARIABLE ) + bPCode = HB_P_PUSHFIELD; + else if( bPCode == HB_P_PUSHMEMVARREF ) + /* pushing fields by reference is not allowed */ + hb_compGenError( hb_comp_szCErrors, 'E', ERR_INVALID_REFER, szVarName, NULL ); + } + } + else if( iType == VS_MEMVAR ) + { + /* variable is declared or assumed MEMVAR */ + if( bPCode == HB_P_POPVARIABLE ) + bPCode = HB_P_POPMEMVAR; + else if( bPCode == HB_P_PUSHVARIABLE ) + bPCode = HB_P_PUSHMEMVAR; + } + + /* Check if this variable name is placed into the symbol table + */ + pSym = hb_compGetSymbol( szVarName, &wVar ); + if( ! pSym ) + pSym = hb_compAddSymbol( szVarName, &wVar ); + pSym->cScope |= VS_MEMVAR; + hb_compGenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ) ); +} + +/* + * Function generates passed pcode for passed memvar name + */ +void MemvarPCode( BYTE bPCode, char * szVarName ) +{ + USHORT wVar; + PCOMSYMBOL pSym; + + /* Check if this variable name is placed into the symbol table + */ + pSym = hb_compGetSymbol( szVarName, &wVar ); + if( ! pSym ) + pSym = hb_compAddSymbol( szVarName, &wVar ); + pSym->cScope |= VS_MEMVAR; + hb_compGenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ) ); +} + +void hb_compGenMessage( char * szMsgName ) /* sends a message to an object */ +{ + USHORT wSym; + PCOMSYMBOL pSym = hb_compGetSymbol( szMsgName, &wSym ); + + if( ! pSym ) /* the symbol was not found on the symbol table */ + pSym = hb_compAddSymbol( szMsgName, &wSym ); + pSym->cScope |= FS_MESSAGE; + hb_compGenPCode3( HB_P_MESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ) ); +} + +void hb_compGenMessageData( char * szMsg ) /* generates an underscore-symbol name for a data assignment */ +{ + char * szResult = ( char * ) hb_xgrab( strlen( szMsg ) + 2 ); + + strcpy( szResult, "_" ); + strcat( szResult, szMsg ); + + hb_compGenMessage( szResult ); +} + +void hb_compGenPopVar( char * szVarName ) /* generates the pcode to pop a value from the virtual machine stack onto a variable */ +{ + int iVar; + + if( hb_comp_pAliasId == NULL ) + { + iVar = GetLocalVarPos( szVarName ); + if( iVar ) + hb_compGenPCode3( HB_P_POPLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + else + { + iVar = GetStaticVarPos( szVarName ); + if( iVar ) + { + hb_compGenPCode3( HB_P_POPSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; + } + else + { + VariablePCode( HB_P_POPVARIABLE, szVarName ); + } + } + } + else + { + if( hb_comp_pAliasId->type == ALIAS_NAME ) + { + if( hb_comp_pAliasId->alias.szAlias[ 0 ] == 'M' && hb_comp_pAliasId->alias.szAlias[ 1 ] == '\0' ) + { /* M->variable */ + MemvarPCode( HB_P_POPMEMVAR, szVarName ); + } + else + { + int iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "MEMVAR", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "MEMVAR", strlen( hb_comp_pAliasId->alias.szAlias ) ); + if( iCmp == 0 ) + { /* MEMVAR-> or MEMVA-> or MEMV-> */ + MemvarPCode( HB_P_POPMEMVAR, szVarName ); + } + else + { /* field variable */ + iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "FIELD", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "FIELD", strlen( hb_comp_pAliasId->alias.szAlias ) ); + if( iCmp == 0 ) + { /* FIELD-> */ + FieldPCode( HB_P_POPFIELD, szVarName ); + } + else + { /* database alias */ + hb_compPushSymbol( yy_strdup( hb_comp_pAliasId->alias.szAlias ), 0 ); + FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); + } + } + } + } + else if( hb_comp_pAliasId->type == ALIAS_NUMBER ) + { + hb_compGenPushInteger( hb_comp_pAliasId->alias.iAlias ); + FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); + } + else + /* Alias is already placed on stack */ + FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); + } +} + +void hb_compGenPushVar( char * szVarName ) /* generates the pcode to push a variable value to the virtual machine stack */ +{ + int iVar; + + if( hb_comp_pAliasId == NULL ) + { + iVar = GetLocalVarPos( szVarName ); + if( iVar ) + hb_compGenPCode3( HB_P_PUSHLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + else + { + iVar = GetStaticVarPos( szVarName ); + if( iVar ) + { + hb_compGenPCode3( HB_P_PUSHSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; + } + else + { + VariablePCode( HB_P_PUSHVARIABLE, szVarName ); + } + } + } + else + { + if( hb_comp_pAliasId->type == ALIAS_NAME ) + { + if( hb_comp_pAliasId->alias.szAlias[ 0 ] == 'M' && hb_comp_pAliasId->alias.szAlias[ 1 ] == '\0' ) + { /* M->variable */ + MemvarPCode( HB_P_PUSHMEMVAR, szVarName ); + } + else + { + int iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "MEMVAR", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "MEMVAR", strlen( hb_comp_pAliasId->alias.szAlias ) ); + if( iCmp == 0 ) + { /* MEMVAR-> or MEMVA-> or MEMV-> */ + MemvarPCode( HB_P_PUSHMEMVAR, szVarName ); + } + else + { /* field variable */ + iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "FIELD", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( hb_comp_pAliasId->alias.szAlias, "FIELD", strlen( hb_comp_pAliasId->alias.szAlias ) ); + if( iCmp == 0 ) + { /* FIELD-> */ + FieldPCode( HB_P_PUSHFIELD, szVarName ); + } + else + { /* database alias */ + hb_compPushSymbol( yy_strdup( hb_comp_pAliasId->alias.szAlias ), 0 ); + FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + } + } + } + } + else if( hb_comp_pAliasId->type == ALIAS_NUMBER ) + { + hb_compGenPushInteger( hb_comp_pAliasId->alias.iAlias ); + FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + } + else + /* Alias is already placed on stack */ + FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + } +} + +void hb_compGenPushVarRef( char * szVarName ) /* generates the pcode to push a variable by reference to the virtual machine stack */ +{ + USHORT iVar; + + iVar = GetLocalVarPos( szVarName ); + if( iVar ) + hb_compGenPCode3( HB_P_PUSHLOCALREF, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + else + { + iVar = GetStaticVarPos( szVarName ); + if( iVar ) + { + hb_compGenPCode3( HB_P_PUSHSTATICREF, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; + } + else + { + /* if undeclared variable is passed by reference then a memvar + * variable is assumed because fields cannot be passed by + * a reference + */ + VariablePCode( HB_P_PUSHMEMVARREF, szVarName ); + } + } +} + +void hb_compGenPushLogical( int iTrueFalse ) /* pushes a logical value on the virtual machine stack */ +{ + if( iTrueFalse ) + hb_compGenPCode1( HB_P_TRUE ); + else + hb_compGenPCode1( HB_P_FALSE ); +} + +void hb_compGenPushNil( void ) +{ + hb_compGenPCode1( HB_P_PUSHNIL ); +} + +/* generates the pcode to push a double number on the virtual machine stack */ +void hb_compGenPushDouble( double dNumber, BYTE bDec ) +{ + hb_compGenPCode1( HB_P_PUSHDOUBLE ); + hb_compGenPCodeN( ( BYTE * ) &dNumber, sizeof( double ) ); + hb_compGenPCode1( bDec ); +} + +void hb_compGenPushFunCall( char * szFunName ) +{ + char * szFunction; + + szFunction = RESERVED_FUNC( szFunName ); + if( szFunction ) + { + /* Abbreviated function name was used - change it for whole name + */ + hb_compPushSymbol( yy_strdup( szFunction ), 1 ); + } + else + hb_compPushSymbol( szFunName, 1 ); +} + +/* generates the pcode to push a integer number on the virtual machine stack */ +void hb_compGenPushInteger( int iNumber ) +{ + if( iNumber ) + hb_compGenPCode3( HB_P_PUSHINT, HB_LOBYTE( ( USHORT ) iNumber ), HB_HIBYTE( ( USHORT ) iNumber ) ); + else + hb_compGenPCode1( HB_P_ZERO ); +} + +/* generates the pcode to push a long number on the virtual machine stack */ +void hb_compGenPushLong( long lNumber ) +{ + if( lNumber ) + { + hb_compGenPCode1( HB_P_PUSHLONG ); + hb_compGenPCode1( ( ( char * ) &lNumber )[ 0 ] ); + hb_compGenPCode1( ( ( char * ) &lNumber )[ 1 ] ); + hb_compGenPCode1( ( ( char * ) &lNumber )[ 2 ] ); + hb_compGenPCode1( ( ( char * ) &lNumber )[ 3 ] ); + } + else + hb_compGenPCode1( HB_P_ZERO ); +} + +/* generates the pcode to push a string on the virtual machine stack */ +void hb_compGenPushString( char * szText, ULONG ulStrLen ) +{ + hb_compGenPCode3( HB_P_PUSHSTR, HB_LOBYTE( ulStrLen ), HB_HIBYTE( ulStrLen ) ); + hb_compGenPCodeN( ( BYTE * ) szText, ulStrLen ); +} + +/* generates the pcode to push a symbol on the virtual machine stack */ +void hb_compPushSymbol( char * szSymbolName, int iIsFunction ) +{ + USHORT wSym; + PCOMSYMBOL pSym; + + if( iIsFunction ) + { + char * pName = RESERVED_FUNC( szSymbolName ); + /* If it is reserved function name then we should truncate + * the requested name. + * We have to use passed szSymbolName so we can latter deallocate it + * (pName points to static data) + */ + if( pName ) + szSymbolName[ strlen( pName ) ] ='\0'; + } + + pSym = hb_compGetSymbol( szSymbolName, &wSym ); + if( ! pSym ) /* the symbol was not found on the symbol table */ + { + pSym = hb_compAddSymbol( szSymbolName, &wSym ); + if( iIsFunction ) + hb_compAddFunCall( szSymbolName ); + } + else + { + if( iIsFunction && ! GetFuncall( szSymbolName ) ) + hb_compAddFunCall( szSymbolName ); + } + hb_compGenPCode3( HB_P_PUSHSYM, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ) ); +} + + +void CheckDuplVars( PVAR pVar, char * szVarName, int iVarScope ) +{ + while( pVar ) + { + if( ! strcmp( pVar->szName, szVarName ) ) + { + if( ! ( iVarScope & VS_PARAMETER ) ) + --iLine; + hb_compErrorDuplVar( szVarName ); + } + else + pVar = pVar->pNext; + } +} + +void Dec( void ) +{ + hb_compGenPCode1( HB_P_DEC ); +} + +void hb_compGenDoProc( BYTE bParams ) +{ + hb_compGenPCode3( HB_P_DO, bParams, 0 ); +} + +void FixElseIfs( void * pFixElseIfs ) +{ + PELSEIF pFix = ( PELSEIF ) pFixElseIfs; + + while( pFix ) + { + hb_compGenJumpHere( pFix->ulOffset ); + pFix = pFix->pNext; + } +} + +void FixReturns( void ) /* fixes all last defined function returns jumps offsets */ +{ + if( hb_comp_iWarnings && hb_comp_functions.pLast ) + { + PVAR pVar; + + pVar = hb_comp_functions.pLast->pLocals; + while( pVar ) + { + if( pVar->szName && hb_comp_functions.pLast->szName && hb_comp_functions.pLast->szName[0] && ! pVar->iUsed ) + hb_compGenWarning( hb_comp_szCWarnings, 'W', WARN_VAR_NOT_USED, pVar->szName, hb_comp_functions.pLast->szName ); + + pVar = pVar->pNext; + } + + pVar = hb_comp_functions.pLast->pStatics; + while( pVar ) + { + if( pVar->szName && hb_comp_functions.pLast->szName && hb_comp_functions.pLast->szName[0] && ! pVar->iUsed ) + hb_compGenWarning( hb_comp_szCWarnings, 'W', WARN_VAR_NOT_USED, pVar->szName, hb_comp_functions.pLast->szName ); + + pVar = pVar->pNext; + } + + /* Check if the function returned some value + */ + if( (hb_comp_functions.pLast->bFlags & FUN_WITH_RETURN) == 0 && + (hb_comp_functions.pLast->bFlags & FUN_PROCEDURE) == 0 ) + hb_compGenWarning( hb_comp_szCWarnings, 'W', WARN_FUN_WITH_NO_RETURN, + hb_comp_functions.pLast->szName, NULL ); + } + +/* TODO: check why it triggers this error in keywords.prg + if( hb_comp_pLoops ) + { + PTR_LOOPEXIT pLoop = hb_comp_pLoops; + char cLine[ 64 ]; + + while( pLoop->pNext ) + pLoop = pLoop->pNext; + + itoa( pLoop->iLine, cLine, 10 ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_UNCLOSED_STRU, cLine, NULL ); + } +*/ +} + +void Function( BYTE bParams ) +{ + hb_compGenPCode3( HB_P_FUNCTION, bParams, 0 ); +} + +void hb_compGenArray( int iElements ) +{ + hb_compGenPCode3( HB_P_ARRAYGEN, HB_LOBYTE( iElements ), HB_HIBYTE( iElements ) ); +} + +void hb_compGenPCode1( BYTE byte ) +{ + PFUNCTION pFunc = hb_comp_functions.pLast; /* get the currently defined Clipper function */ + + if( ! pFunc->pCode ) /* has been created the memory block to hold the pcode ? */ + { + pFunc->pCode = ( BYTE * ) hb_xgrab( PCODE_CHUNK ); + pFunc->lPCodeSize = PCODE_CHUNK; + pFunc->lPCodePos = 0; + } + else + if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 1 ) + pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += PCODE_CHUNK ); + + pFunc->pCode[ pFunc->lPCodePos++ ] = byte; +} + +void hb_compGenPCode3( BYTE byte1, BYTE byte2, BYTE byte3 ) +{ + PFUNCTION pFunc = hb_comp_functions.pLast; /* get the currently defined Clipper function */ + + if( ! pFunc->pCode ) /* has been created the memory block to hold the pcode ? */ + { + pFunc->pCode = ( BYTE * ) hb_xgrab( PCODE_CHUNK ); + pFunc->lPCodeSize = PCODE_CHUNK; + pFunc->lPCodePos = 0; + } + else + if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 3 ) + pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += PCODE_CHUNK ); + + pFunc->pCode[ pFunc->lPCodePos++ ] = byte1; + pFunc->pCode[ pFunc->lPCodePos++ ] = byte2; + pFunc->pCode[ pFunc->lPCodePos++ ] = byte3; +} + +void hb_compGenPCodeN( BYTE * pBuffer, ULONG ulSize ) +{ + PFUNCTION pFunc = hb_comp_functions.pLast; /* get the currently defined Clipper function */ + + if( ! pFunc->pCode ) /* has been created the memory block to hold the pcode ? */ + { + pFunc->lPCodeSize = ( ( ulSize / PCODE_CHUNK ) + 1 ) * PCODE_CHUNK; + pFunc->pCode = ( BYTE * ) hb_xgrab( pFunc->lPCodeSize ); + pFunc->lPCodePos = 0; + } + else if( pFunc->lPCodePos + ulSize > pFunc->lPCodeSize ) + { + /* not enough free space in pcode buffer - increase it */ + pFunc->lPCodeSize += ( ( ( ulSize / PCODE_CHUNK ) + 1 ) * PCODE_CHUNK ); + pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize ); + } + + memcpy( pFunc->pCode + pFunc->lPCodePos, pBuffer, ulSize ); + pFunc->lPCodePos += ulSize; +} + +/* Generate the opcode to open BEGIN/END sequence + * This code is simmilar to JUMP opcode - the offset will be filled with + * - either the address of HB_P_SEQEND opcode if there is no RECOVER clause + * - or the address of RECOVER code + */ +ULONG SequenceBegin( void ) +{ + hb_compGenPCode3( HB_P_SEQBEGIN, 0, 0 ); + + return hb_comp_functions.pLast->lPCodePos - 2; +} + +/* Generate the opcode to close BEGIN/END sequence + * This code is simmilar to JUMP opcode - the offset will be filled with + * the address of first line after END SEQUENCE + * This opcode will be executed if recover code was not requested (as the + * last statement in code beetwen BEGIN ... RECOVER) or if BREAK was requested + * and there was no matching RECOVER clause. + */ +ULONG SequenceEnd( void ) +{ + hb_compGenPCode3( HB_P_SEQEND, 0, 0 ); + + return hb_comp_functions.pLast->lPCodePos - 2; +} + +/* Remove unnecessary opcodes in case there were no executable statements + * beetwen BEGIN and RECOVER sequence + */ +void SequenceFinish( ULONG ulStartPos, int bUsualStmts ) +{ + if( ! hb_comp_bDebugInfo ) /* only if no debugger info is required */ + { + if( ! bUsualStmts ) + { + hb_comp_functions.pLast->lPCodePos = ulStartPos - 1; /* remove also HB_P_SEQBEGIN */ + hb_comp_ulLastLinePos = ulStartPos - 4; + } + } +} + + +/* Set the name of an alias for the list of previously declared FIELDs + * + * szAlias -> name of the alias + * iField -> position of the first FIELD name to change + */ +void FieldsSetAlias( char * szAlias, int iField ) +{ + PVAR pVar; + + pVar = hb_comp_functions.pLast->pFields; + while( iField-- && pVar ) + pVar = pVar->pNext; + + while( pVar ) + { + pVar->szAlias = szAlias; + pVar = pVar->pNext; + } +} + +/* This functions counts the number of FIELD declaration in a function + * We will required this information in FieldsSetAlias function + */ +int FieldsCount() +{ + int iFields = 0; + PVAR pVar = hb_comp_functions.pLast->pFields; + + while( pVar ) + { + ++iFields; + pVar = pVar->pNext; + } + + return iFields; +} + +/* + * Start of definition of static variable + * We are using here the special function hb_comp_pInitFunc which will store + * pcode needed to initialize all static variables declared in PRG module. + * pOwner member will point to a function where the static variable is + * declared: + * TODO: support for static variables in codeblock + */ +void hb_compStaticDefStart( void ) +{ + hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; + if( ! hb_comp_pInitFunc ) + { + BYTE pBuffer[ 5 ]; + + hb_comp_pInitFunc = FunctionNew( yy_strdup("(_INITSTATICS)"), FS_INIT ); + hb_comp_pInitFunc->pOwner = hb_comp_functions.pLast; + hb_comp_pInitFunc->bFlags = FUN_USES_STATICS | FUN_PROCEDURE; + hb_comp_pInitFunc->cScope = FS_INIT | FS_EXIT; + hb_comp_functions.pLast = hb_comp_pInitFunc; + + pBuffer[ 0 ] = HB_P_STATICS; + pBuffer[ 1 ] = 0; + pBuffer[ 2 ] = 0; + pBuffer[ 3 ] = 1; /* the number of static variables is unknown now */ + pBuffer[ 4 ] = 0; + hb_compGenPCodeN( pBuffer, 5 ); + hb_compGenPCode3( HB_P_SFRAME, 0, 0 ); /* frame for statics variables */ + } + else + { + hb_comp_pInitFunc->pOwner = hb_comp_functions.pLast; + hb_comp_functions.pLast = hb_comp_pInitFunc; + } +} + +/* + * End of definition of static variable + * Return to previously pcoded function. + */ +void hb_compStaticDefEnd( void ) +{ + hb_comp_functions.pLast = hb_comp_pInitFunc->pOwner; + hb_comp_pInitFunc->pOwner = NULL; + ++hb_comp_iStaticCnt; +} + +/* + * Start a new fake-function that will hold pcodes for a codeblock +*/ +void hb_compCodeBlockStart() +{ + PFUNCTION pFunc = FunctionNew( NULL, FS_STATIC ); + + pFunc->pOwner = hb_comp_functions.pLast; + pFunc->iStaticsBase = hb_comp_functions.pLast->iStaticsBase; + + hb_comp_functions.pLast = pFunc; + LineDebug(); +} + +void hb_compCodeBlockEnd( void ) +{ + PFUNCTION pCodeblock; /* pointer to the current codeblock */ + PFUNCTION pFunc; /* pointer to a function that owns a codeblock */ + USHORT wSize; + USHORT wLocals = 0; /* number of referenced local variables */ + USHORT wPos; + PVAR pVar, pFree; + + pCodeblock = hb_comp_functions.pLast; + + /* return to pcode buffer of function/codeblock in which the current + * codeblock was defined + */ + hb_comp_functions.pLast = pCodeblock->pOwner; + + /* find the function that owns the codeblock */ + pFunc = pCodeblock->pOwner; + while( pFunc->pOwner ) + pFunc = pFunc->pOwner; + pFunc->bFlags |= ( pCodeblock->bFlags & FUN_USES_STATICS ); + + /* generate a proper codeblock frame with a codeblock size and with + * a number of expected parameters + */ + /*QUESTION: would be 64kB enough for a codeblock size? + * we are assuming now a USHORT for a size of codeblock + */ + + /* Count the number of referenced local variables */ + pVar = pCodeblock->pStatics; + while( pVar ) + { + pVar = pVar->pNext; + ++wLocals; + } + + /*NOTE: 8 = HB_P_PUSHBLOCK + USHORT( size ) + USHORT( wParams ) + USHORT( wLocals ) + _ENDBLOCK */ + wSize = ( USHORT ) pCodeblock->lPCodePos + 8 + wLocals * 2; + + hb_compGenPCode3( HB_P_PUSHBLOCK, HB_LOBYTE( wSize ), HB_HIBYTE( wSize ) ); + hb_compGenPCode1( HB_LOBYTE( pCodeblock->wParamCount ) ); + hb_compGenPCode1( HB_HIBYTE( pCodeblock->wParamCount ) ); + hb_compGenPCode1( HB_LOBYTE( wLocals ) ); + hb_compGenPCode1( HB_HIBYTE( wLocals ) ); + + /* generate the table of referenced local variables */ + pVar = pCodeblock->pStatics; + while( wLocals-- ) + { + wPos = GetVarPos( pFunc->pLocals, pVar->szName ); + hb_compGenPCode1( HB_LOBYTE( wPos ) ); + hb_compGenPCode1( HB_HIBYTE( wPos ) ); + + pFree = pVar; + hb_xfree( ( void * ) pFree->szName ); + pVar = pVar->pNext; + hb_xfree( ( void * ) pFree ); + } + + hb_compGenPCodeN( pCodeblock->pCode, pCodeblock->lPCodePos ); + hb_compGenPCode1( HB_P_ENDBLOCK ); /* finish the codeblock */ + + /* this fake-function is no longer needed */ + hb_xfree( ( void * ) pCodeblock->pCode ); + pVar = pCodeblock->pLocals; + while( pVar ) + { + if( hb_comp_iWarnings && pFunc->szName && pVar->szName && ! pVar->iUsed ) + hb_compGenWarning( hb_comp_szCWarnings, 'W', WARN_BLOCKVAR_NOT_USED, pVar->szName, pFunc->szName ); + + /* free used variables */ + pFree = pVar; + hb_xfree( ( void * ) pFree->szName ); + pVar = pVar->pNext; + hb_xfree( ( void * ) pFree ); + } + hb_xfree( ( void * ) pCodeblock ); +} + + +/* ************************************************************************* */ + +HB_EXPR_PTR hb_compErrorLValue( HB_EXPR_PTR pExpr ) +{ + char * szDesc = hb_compExprDescription( pExpr ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_INVALID_LVALUE, szDesc, NULL ); + return pExpr; +} + +HB_EXPR_PTR hb_compErrorType( HB_EXPR_PTR pExpr ) +{ + char * szDesc = hb_compExprDescription( pExpr ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_INVALID_TYPE, szDesc, NULL ); + return pExpr; +} + +HB_EXPR_PTR hb_compErrorIndex( HB_EXPR_PTR pExpr ) +{ + char * szDesc = hb_compExprDescription( pExpr ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_INVALID_INDEX, szDesc, NULL ); + return pExpr; +} + +HB_EXPR_PTR hb_compErrorBound( HB_EXPR_PTR pExpr ) +{ + char * szDesc = hb_compExprDescription( pExpr ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_INVALID_BOUND, szDesc, NULL ); + return pExpr; +} + +HB_EXPR_PTR hb_compErrorSyntax( HB_EXPR_PTR pExpr ) +{ + char * szDesc = hb_compExprDescription( pExpr ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, szDesc, NULL ); + return pExpr; +} + +HB_EXPR_PTR hb_compErrorAlias( HB_EXPR_PTR pExpr ) +{ + char * szDesc = hb_compExprDescription( pExpr ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_INVALID_ALIAS, szDesc, NULL ); + return pExpr; +} + +HB_EXPR_PTR hb_compErrorStatic( char * szVarName, HB_EXPR_PTR pExpr ) +{ + char * szDesc = hb_compExprDescription( pExpr ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_ILLEGAL_INIT, szVarName, szDesc ); + return pExpr; +} + +void hb_compErrorDuplVar( char * szVarName ) +{ + hb_compGenError( hb_comp_szCErrors, 'E', ERR_VAR_DUPL, szVarName, NULL ); +} + +HB_EXPR_PTR hb_compWarnMeaningless( HB_EXPR_PTR pExpr ) +{ + char * szDesc = hb_compExprDescription( pExpr ); + hb_compGenWarning( hb_comp_szCWarnings, 'W', WARN_MEANINGLESS, szDesc, NULL ); + return pExpr; +} diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index ae180b37f2..f9564ddf7d 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -40,8 +40,8 @@ #include #include #include -#include "harboury.h" #include "compiler.h" +#include "harboury.h" #include "hbsetup.h" /* main configuration file */ #include "hberrors.h" #include "hbdefs.h" @@ -74,12 +74,7 @@ int yy_lex_input( char *, int ); #define YY_INPUT( buf, result, max_size ) result = yy_lex_input( buf, max_size ); /* variables defined in harbour.y */ -extern int _bRestrictSymbolLength; -extern USHORT _wSeqCounter; -extern USHORT _wForCounter; -extern USHORT _wIfCounter; -extern USHORT _wWhileCounter; -extern USHORT _wCaseCounter; +extern int hb_comp_bRestrictSymbolLength; int iLine = 1; long lNumber = 0; @@ -87,7 +82,7 @@ long lNumber = 0; #define LOOKUP 0 /* scan from the begining of line */ #define OPERATOR -1 #define SEPARATOR -2 -int _iState = LOOKUP; +int hb_comp_iState = LOOKUP; static int _iOpenBracket = 0; /* Support for Array Index */ @@ -105,13 +100,12 @@ int i_INDEX_STATE = 0; SpaceTab [ \t]+ Number ([0-9]+)|([0-9]*\.[0-9]+) -Integer ([0-9]+)|([0-9]+) InvalidNumber [0-9]+\. HexNumber 0x[0-9A-F]+ Identifier (([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+)) -/* TODO check if String definition can be removed - Ron Pinkas added support for [] String Delimiters see STRING1, STRING2 and STRING3*/ -/*String (\"(([^\"]*)|([\!]*))\")|(\'(([^\']*)|([\!]*))\')*/ +TrueValue "."[t|y]"." +FalseValue "."[f|n]"." PseudoFunc {Identifier}"("+.*")"+ @@ -132,40 +126,40 @@ Separator {SpaceTab} %% -"&"("'"|\"|\[) { GenError( _szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); } +"&"("'"|\"|\[) { hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); } ' BEGIN STRING1; \" BEGIN STRING2; -"="[ \t]*"[" { BEGIN STRING3; _iState =OPERATOR; return '='; } -"+"[ \t]*"[" { BEGIN STRING3; _iState =OPERATOR; return '+'; } -"-"[ \t]*"[" { BEGIN STRING3; _iState =OPERATOR; return '-'; } -"*"[ \t]*"[" { BEGIN STRING3; _iState =OPERATOR; return '*'; } -"/"[ \t]*"[" { BEGIN STRING3; _iState =OPERATOR; return '/'; } -"%"[ \t]*"[" { BEGIN STRING3; _iState =OPERATOR; return '%'; } -"$"[ \t]*"[" { BEGIN STRING3; _iState =OPERATOR; return '$'; } -("<>"|"!=")[ \t]*"[" { BEGIN STRING3; _iState =NE2; return NE2; } -":="[ \t]*"[" { BEGIN STRING3; _iState =INASSIGN; return INASSIGN; } -"=="[ \t]*"[" { BEGIN STRING3; _iState =EQ; return EQ; } -"<="[ \t]*"[" { BEGIN STRING3; _iState =LE; return LE; } -">="[ \t]*"[" { BEGIN STRING3; _iState =GE; return GE; } -"+="[ \t]*"[" { BEGIN STRING3; _iState =PLUSEQ; return PLUSEQ; } -"-="[ \t]*"[" { BEGIN STRING3; _iState =MINUSEQ; return MINUSEQ; } -"*="[ \t]*"[" { BEGIN STRING3; _iState =MULTEQ; return MULTEQ; } -"/="[ \t]*"[" { BEGIN STRING3; _iState =DIVEQ; return DIVEQ; } -"^="[ \t]*"[" { BEGIN STRING3; _iState =EXPEQ; return EXPEQ; } -"%="[ \t]*"[" { BEGIN STRING3; _iState =MODEQ; return MODEQ; } -("**"|"^")[ \t]*"[" { BEGIN STRING3; _iState =POWER; return POWER; } +"="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =OPERATOR; return '='; } +"+"[ \t]*"[" { BEGIN STRING3; hb_comp_iState =OPERATOR; return '+'; } +"-"[ \t]*"[" { BEGIN STRING3; hb_comp_iState =OPERATOR; return '-'; } +"*"[ \t]*"[" { BEGIN STRING3; hb_comp_iState =OPERATOR; return '*'; } +"/"[ \t]*"[" { BEGIN STRING3; hb_comp_iState =OPERATOR; return '/'; } +"%"[ \t]*"[" { BEGIN STRING3; hb_comp_iState =OPERATOR; return '%'; } +"$"[ \t]*"[" { BEGIN STRING3; hb_comp_iState =OPERATOR; return '$'; } +("<>"|"!=")[ \t]*"[" { BEGIN STRING3; hb_comp_iState =NE2; return NE2; } +":="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =INASSIGN; return INASSIGN; } +"=="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =EQ; return EQ; } +"<="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =LE; return LE; } +">="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =GE; return GE; } +"+="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =PLUSEQ; return PLUSEQ; } +"-="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =MINUSEQ; return MINUSEQ; } +"*="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =MULTEQ; return MULTEQ; } +"/="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =DIVEQ; return DIVEQ; } +"^="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =EXPEQ; return EXPEQ; } +"%="[ \t]*"[" { BEGIN STRING3; hb_comp_iState =MODEQ; return MODEQ; } +("**"|"^")[ \t]*"[" { BEGIN STRING3; hb_comp_iState =POWER; return POWER; } ".and."[ \t]*"[" { BEGIN STRING3; return AND; } ".or."[ \t]*"[" { BEGIN STRING3; return OR; } ("!"|".not.")[ \t]*"[" { BEGIN STRING3; return NOT; } -(","|"{"|"<"|">"|"(")[ \t]*"[" { BEGIN STRING3; _iState = OPERATOR; yyleng = 1; yytext[1] = 0; return yytext[ 0 ]; } +(","|"{"|"<"|">"|"(")[ \t]*"[" { BEGIN STRING3; hb_comp_iState = OPERATOR; yyleng = 1; yytext[1] = 0; return yytext[ 0 ]; } \[ BEGIN STRING3; -[^'^\n]* { GenError( _szCErrors, 'E', ERR_STRING_TERMINATOR, yytext, NULL ); BEGIN 0; } -[^\"^\n]* { GenError( _szCErrors, 'E', ERR_STRING_TERMINATOR, yytext, NULL ); BEGIN 0; } -[^\]]*\n { GenError( _szCErrors, 'E', ERR_STRING_TERMINATOR, yytext, NULL ); BEGIN 0; } +[^'^\n]* { hb_compGenError( hb_comp_szCErrors, 'E', ERR_STRING_TERMINATOR, yytext, NULL ); BEGIN 0; } +[^\"^\n]* { hb_compGenError( hb_comp_szCErrors, 'E', ERR_STRING_TERMINATOR, yytext, NULL ); BEGIN 0; } +[^\]]*\n { hb_compGenError( hb_comp_szCErrors, 'E', ERR_STRING_TERMINATOR, yytext, NULL ); BEGIN 0; } [^']*' { if( i_INDEX_STATE ) BEGIN INDEX; @@ -203,7 +197,7 @@ Separator {SpaceTab} return LITERAL; } -\n { GenError( _szCErrors, 'E', ERR_UNTERM_ARRAY_INDEX, NULL, NULL ); } +\n { hb_compGenError( hb_comp_szCErrors, 'E', ERR_UNTERM_ARRAY_INDEX, NULL, NULL ); } \[ { iIndexSets++; return yytext[ 0 ]; } @@ -217,23 +211,23 @@ Separator {SpaceTab} i_INDEX_STATE = 0; BEGIN 0; } - _iState =OPERATOR; + hb_comp_iState =OPERATOR; return yytext[ 0 ]; } {SpaceTab} ; \n.* { - _iState = LOOKUP; + hb_comp_iState = LOOKUP; yyless( 1 ); /*++iLine;*/ #if 0 - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) { printf( "\r%i", iLine ); } #endif - if( ! _bQuiet && ( iLine % 100 ) == 0 ) + if( ! hb_comp_bQuiet && ( iLine % 100 ) == 0 ) { printf( "\r%i", iLine ); fflush( stdout ); @@ -243,7 +237,7 @@ Separator {SpaceTab} %{ /* ************************************************************************ */ %} -; _iState = LOOKUP; if( ! i_INDEX_STATE ) return ';'; +; hb_comp_iState = LOOKUP; if( ! i_INDEX_STATE ) return ';'; %{ /* ************************************************************************ */ %} @@ -251,12 +245,12 @@ Separator {SpaceTab} %{ /* ************************************************************************ */ %} -"break" { if( _iState == LOOKUP ) +"break" { if( hb_comp_iState == LOOKUP ) BEGIN BREAK_; else { yylval.string = yy_strupr( yy_strdup( yytext ) ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -272,7 +266,7 @@ Separator {SpaceTab} /* {Separator}*[\[] { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - GenError( _szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); } */ %} @@ -281,7 +275,7 @@ Separator {SpaceTab} yylval.string = yy_strdup( "BREAK" ); unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } {Separator}*("++"|"--") { /* operators */ @@ -293,14 +287,14 @@ Separator {SpaceTab} yylval.string = yy_strdup( "BREAK" ); unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); - _iState =BREAK; + hb_comp_iState =BREAK; return BREAK; } {Separator}*[\=\(] { /* operators = ( */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; yylval.string = yy_strdup( "BREAK" ); unput( yytext[ yyleng-1 ] ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } {Separator}*. { /* all other cases */ @@ -308,7 +302,7 @@ Separator {SpaceTab} */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - _iState =BREAK; + hb_comp_iState =BREAK; return BREAK; } %{ @@ -318,19 +312,19 @@ Separator {SpaceTab} {Separator}*[\:\=\|\$\%\*\,\/\]\)\}\^] { /* there is an operator after "case" */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; yylval.string = yy_strdup( "CASE" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } {Separator}*[\[] { /* array */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; /* Clipper does not like case[] at all */ - GenError( _szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); } {Separator}*("+="|"-="|"->") { /* operators */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; yylval.string = yy_strdup( "CASE" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); return IDENTIFIER; @@ -339,21 +333,21 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); - _iState =CASE; + hb_comp_iState =CASE; return CASE; } {Separator}*(\n|.) { /* not operator */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - _iState =CASE; + hb_comp_iState =CASE; return CASE; } else { /* there is another item in line already */ yylval.string = yy_strdup( "CASE" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -369,7 +363,7 @@ Separator {SpaceTab} "do" BEGIN DO_; {Separator}+"case" { /* DO CASE statement */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =DOCASE; + hb_comp_iState =DOCASE; return DOCASE; } {Separator}+"while" { /* DO WHILE found -move it to WHILE state */ @@ -377,21 +371,21 @@ Separator {SpaceTab} * or DO while [WITH ] */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =DO; + hb_comp_iState =DO; yyless( yyleng-5 ); } {Separator}+[_a-zA-Z] { /* an identifier DO id WITH */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - _iState =DO; + hb_comp_iState =DO; return DO; } else { /* there is another item in line already */ yylval.string = yy_strdup( "DO" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -399,27 +393,27 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); yylval.string = yy_strdup( "DO" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ /* ************************************************************************ */ %} "else" { /* ELSE can be used in one context only */ - if( _wIfCounter == 0 ) - GenError( _szCErrors, 'E', ERR_UNMATCHED_ELSE, NULL, NULL ); - _iState =ELSE; + if( hb_comp_wIfCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_UNMATCHED_ELSE, NULL, NULL ); + hb_comp_iState =ELSE; return ELSE; } "elseif" { /* ELSEIF can be used in one context only */ - if( _wIfCounter == 0 ) - GenError( _szCErrors, 'E', ERR_UNMATCHED_ELSEIF, NULL, NULL ); - _iState =ELSEIF; + if( hb_comp_wIfCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_UNMATCHED_ELSEIF, NULL, NULL ); + hb_comp_iState =ELSEIF; return ELSEIF; } "end"{Separator}+"sequ"("ence"|"enc"|"en"|"e")? { - if( _wSeqCounter == 0 ) - GenError( _szCErrors, 'E', ERR_ENDIF, NULL, NULL ); + if( hb_comp_wSeqCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_ENDIF, NULL, NULL ); return END; } %{ @@ -427,18 +421,18 @@ Separator {SpaceTab} %} "endif"|"endi" { /* ENDIF can be used in one context only */ - if( _wIfCounter == 0 ) - GenError( _szCErrors, 'E', ERR_ENDIF, NULL, NULL ); + if( hb_comp_wIfCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_ENDIF, NULL, NULL ); return ENDIF; } "endc"("ase"|"as"|"a")? { /* ENDCASE can be used in one context only */ - if( _wCaseCounter == 0 ) - GenError( _szCErrors, 'E', ERR_ENDCASE, NULL, NULL ); + if( hb_comp_wCaseCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_ENDCASE, NULL, NULL ); return ENDCASE; } "enddo"|"endd" { /* ENDDO can be used in one context only */ - if( _wWhileCounter == 0 ) - GenError( _szCErrors, 'E', ERR_ENDDO, NULL, NULL ); + if( hb_comp_wWhileCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_ENDDO, NULL, NULL ); return ENDDO; } %{ @@ -447,23 +441,23 @@ Separator {SpaceTab} "end" { BEGIN END_; } {Separator}*[\[\(] { /* array, function call */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* Clipper does not like end[] & end() at the begining of line */ - GenError( _szCErrors, 'E', ERR_ENDIF, NULL, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_ENDIF, NULL, NULL ); } yylval.string = yy_strdup( "END" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } {Separator}*("->"|"++"|"--") { /* operators */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* Clipper does not like end-> & end++ at the begining of line */ - GenError( _szCErrors, 'E', ERR_ENDIF, NULL, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_ENDIF, NULL, NULL ); } yylval.string = yy_strdup( "END" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); return IDENTIFIER; @@ -471,22 +465,22 @@ Separator {SpaceTab} {Separator}*[\+\-\:\=\|\$\%\*\,\/\[\]\)\}\^] { /* there is an operator after "end" */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; yylval.string = yy_strdup( "END" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } {Separator}*(.|\n) { /* not operator */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - _iState =END; + hb_comp_iState =END; return END; } else { /* there is another item in line already */ yylval.string = yy_strdup( "END" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -498,32 +492,32 @@ Separator {SpaceTab} {Separator}*[\n;] { /* EXIT last item in the line */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - if( _wForCounter == 0 && _wWhileCounter == 0 ) - GenError( _szCErrors, 'E', ERR_UNMATCHED_EXIT, "EXIT", NULL ); - _iState =EXITLOOP; + if( hb_comp_wForCounter == 0 && hb_comp_wWhileCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_UNMATCHED_EXIT, "EXIT", NULL ); + hb_comp_iState =EXITLOOP; return EXITLOOP; } else { /* there is another item in line already */ yylval.string = yy_strdup( "EXIT" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}+[fFpP] { /* FUNCTION or PROCEDURE after EXIT */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - _iState =EXIT; + hb_comp_iState =EXIT; return EXIT; } else { /* there is another item in line already */ yylval.string = yy_strdup( "EXIT" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -531,7 +525,7 @@ Separator {SpaceTab} unput( yytext[ yyleng-1 ] ); yylval.string = yy_strdup( "EXIT" ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ @@ -543,22 +537,22 @@ Separator {SpaceTab} {Separator}+[_a-zA-Z] { /* an identifier after the EXTERNAL */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { hb_xfree( (void *) yylval.string ); - _iState =EXTERN; + hb_comp_iState =EXTERN; return EXTERN; } else { - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}*[^_a-zA-Z] { unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } . { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); } @@ -571,22 +565,30 @@ Separator {SpaceTab} {Separator}+[_a-zA-Z] { /* an identifier after the FIELD */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { hb_xfree( (void *) yylval.string ); - _iState =FIELD; + hb_comp_iState =FIELD; return FIELD; } else { - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } +{Separator}*"->" { /* alias expression */ + unput( yytext[ yyleng-1 ] ); + unput( yytext[ yyleng-2 ] ); + if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; + hb_xfree( (void *) yylval.string ); + hb_comp_iState =FIELD; + return FIELD; + } {Separator}*[^_a-zA-Z] { unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } . { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); } @@ -597,26 +599,26 @@ Separator {SpaceTab} {Separator}+[_a-zA-Z] { /* an identifier after the FOR */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { - _iState =FOR; + hb_comp_iState =FOR; return FOR; } else { /* for example: DO for WITH variable */ yylval.string = yy_strdup( "FOR" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}*[\(] { /* function call */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* Clipper does not like FOR() at the begining of line */ - GenError( _szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); } yylval.string = yy_strdup( "FOR" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } @@ -624,7 +626,7 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; yylval.string = yy_strdup( "FOR" ); unput( yytext[ yyleng-1 ] ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ @@ -634,18 +636,18 @@ Separator {SpaceTab} {Separator}+[_a-zA-Z] { BEGIN 0; /* we can don't care about INDEX_STATE here */ unput( yytext[ yyleng-1 ] ); - _iState=FUNCTION; + hb_comp_iState=FUNCTION; return FUNCTION; } {Separator}*[^_a-zA-Z] { /* Clipper needs FUNCTION in one context only */ - GenError( _szCErrors, 'E', ERR_SYNTAX, ((yytext[ yyleng-1 ]=='\n')?"FUNCTION":yytext), NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, ((yytext[ yyleng-1 ]=='\n')?"FUNCTION":yytext), NULL ); } %{ /* ************************************************************************ */ %} "iif" { - if( _iState == FUNCTION || _iState == PROCEDURE ) - GenError( _szCErrors, 'E', ERR_SYNTAX, "IIF", NULL ); + if( hb_comp_iState == FUNCTION || hb_comp_iState == PROCEDURE ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, "IIF", NULL ); else BEGIN IIF_; /* Note: In Clipper: @@ -658,46 +660,46 @@ Separator {SpaceTab} {Separator}*"(" { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - _iState=IIF; + hb_comp_iState=IIF; return IIF; } {Separator}*[^\(] { - GenError( _szCErrors, 'E', ERR_SYNTAX, ((yytext[ yyleng-1 ]=='\n')?"IIF":yytext), NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, ((yytext[ yyleng-1 ]=='\n')?"IIF":yytext), NULL ); } %{ /* ************************************************************************ */ %} "if" { - if( _iState == FUNCTION || _iState == PROCEDURE ) - GenError( _szCErrors, 'E', ERR_SYNTAX, "IF", NULL ); + if( hb_comp_iState == FUNCTION || hb_comp_iState == PROCEDURE ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, "IF", NULL ); else BEGIN IF_; } {Separator}*"(" { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - if( _iState == LOOKUP ) - _iState =IF; + if( hb_comp_iState == LOOKUP ) + hb_comp_iState =IF; else - _iState =IIF; - return _iState; + hb_comp_iState =IIF; + return hb_comp_iState; } {Separator}*[\)\[\]\/\^\*\%\=\$\@] { - GenError( _szCErrors, 'E', ERR_SYNTAX2, yytext, "IF" ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX2, yytext, "IF" ); } {Separator}*"->" { - GenError( _szCErrors, 'E', ERR_SYNTAX2, yytext, "IF" ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX2, yytext, "IF" ); } {Separator}*[\n] { - GenError( _szCErrors, 'E', ERR_SYNTAX, "IF", NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, "IF", NULL ); } {Separator}*("++"|"--")/[\n] { - GenError( _szCErrors, 'E', ERR_SYNTAX2, yytext, "IF" ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX2, yytext, "IF" ); } {Separator}*. { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - _iState =IF; + hb_comp_iState =IF; return IF; } %{ @@ -707,12 +709,12 @@ Separator {SpaceTab} {Separator}+[_a-zA-Z] { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - if( _iState == IDENTIFIER ) + if( hb_comp_iState == IDENTIFIER ) return IN; else { yylval.string =yy_strdup( "IN" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -720,17 +722,17 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); yylval.string =yy_strdup( "IN" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } {Separator}*[0-9] { - GenError( _szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); } {Separator}*. { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); yylval.string =yy_strdup( "IN" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ @@ -740,15 +742,15 @@ Separator {SpaceTab} {Separator}+[fFpP] { /* FUNCTION or PROCEDURE after INIT */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - _iState =INIT; + hb_comp_iState =INIT; return INIT; } else { /* there is another item in line already */ yylval.string = yy_strdup( "INIT" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -756,7 +758,7 @@ Separator {SpaceTab} unput( yytext[ yyleng-1 ] ); yylval.string = yy_strdup( "INIT" ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ @@ -769,22 +771,22 @@ Separator {SpaceTab} {Separator}+[_a-zA-Z] { /* an identifier after LOCAL */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ hb_xfree( (void *) yylval.string ); - _iState =LOCAL; + hb_comp_iState =LOCAL; return LOCAL; } else { /* there is another item in line already */ - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}*[^a-zA-Z] { /* any character (not identifier) after LOCAL */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ @@ -794,17 +796,17 @@ Separator {SpaceTab} {Separator}*[\n;] { /* at the end of the line */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - if( _wWhileCounter == 0 && _wForCounter == 0 ) - GenError( _szCErrors, 'E', ERR_UNMATCHED_EXIT, "LOOP", NULL ); - _iState =LOOP; + if( hb_comp_wWhileCounter == 0 && hb_comp_wForCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_UNMATCHED_EXIT, "LOOP", NULL ); + hb_comp_iState =LOOP; return LOOP; } else { /* there is another item in line already */ yylval.string = yy_strdup( "LOOP" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -812,7 +814,7 @@ Separator {SpaceTab} unput( yytext[ yyleng-1 ] ); yylval.string = yy_strdup( "LOOP" ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ @@ -824,22 +826,22 @@ Separator {SpaceTab} {Separator}+[_a-zA-Z] { /* an identifier after MEMVAR */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is the first item in the line */ hb_xfree( (void *) yylval.string ); - _iState =MEMVAR; + hb_comp_iState =MEMVAR; return MEMVAR; } else { /* there is another item in line already */ - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}*[^a-zA-Z] { /* any character (not identifier) after MEMVAR */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ @@ -849,39 +851,39 @@ Separator {SpaceTab} {Separator}*[\n\;] { /* at the end of line */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ - if( _wForCounter == 0 ) - GenError( _szCErrors, 'E', ERR_NEXTFOR, NULL, NULL ); - _iState =NEXT; + if( hb_comp_wForCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_NEXTFOR, NULL, NULL ); + hb_comp_iState =NEXT; return NEXT; } else { /* there is another item in line already */ yylval.string = yy_strdup( "NEXT" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}*[\[\(] { /* array, function call */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* Clipper does not like NEXT[] & NEXT() at the begining of line */ - GenError( _szCErrors, 'E', ERR_NEXTFOR, NULL, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_NEXTFOR, NULL, NULL ); } yylval.string = yy_strdup( "NEXT" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); return IDENTIFIER; } {Separator}*("->"|"++"|"--") { /* operators */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* Clipper does not like next-> & next++ at the begining of line */ - GenError( _szCErrors, 'E', ERR_NEXTFOR, NULL, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_NEXTFOR, NULL, NULL ); } yylval.string = yy_strdup( "NEXT" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); return IDENTIFIER; @@ -895,24 +897,24 @@ Separator {SpaceTab} {Separator}*. { /* an identifier follows NEXT statement */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { - if( _wForCounter == 0 ) - GenError( _szCErrors, 'E', ERR_NEXTFOR, NULL, NULL ); - _iState =NEXT; + if( hb_comp_wForCounter == 0 ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_NEXTFOR, NULL, NULL ); + hb_comp_iState =NEXT; return NEXT; } else { yylval.string = yy_strdup( "NEXT" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } %{ /* ************************************************************************ */ %} -"nil" _iState =LITERAL; return NIL; +"nil" hb_comp_iState =LITERAL; return NIL; "otherwise" return OTHERWISE; %{ /* ************************************************************************ */ @@ -924,22 +926,22 @@ Separator {SpaceTab} {Separator}+[_a-zA-Z] { /* an identifier after PARAMETERS */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is the first item in the line */ hb_xfree( (void *) yylval.string ); - _iState =PARAMETERS; + hb_comp_iState =PARAMETERS; return PARAMETERS; } else { /* there is another item in line already */ - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } {Separator}*[^a-zA-Z] { /* any character (not identifier) after PARAMETERS */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ @@ -948,26 +950,26 @@ Separator {SpaceTab} "priv"("ate"|"at"|"a")? { BEGIN PRIVATE_; yylval.string = yy_strupr( yy_strdup( yytext ) ); } -{Separator}+["&"|_a-zA-Z] { /* an Identifier after PRIVATE */ +{Separator}+[_a-zA-Z] { /* an Identifier after PRIVATE */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ hb_xfree( (void *) yylval.string ); - _iState = PRIVATE; + hb_comp_iState =PRIVATE; return PRIVATE; } else { /* there is another item in line already */ - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } - -{Separator}*[^a-zA-Z] { /* any character (not identifier or macro operator) after PRIVATE */ +{Separator}*[^a-zA-Z] { /* any character (not identifier) after PRIVATE */ + /* TODO: add support for macro operator */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState = IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ @@ -980,34 +982,35 @@ Separator {SpaceTab} "publ"("ic"|"i")? { BEGIN PUBLIC_; yylval.string = yy_strupr( yy_strdup( yytext ) ); } -{Separator}+["&"|_a-zA-Z] { /* an identifier after PUBLIC */ +{Separator}+[_a-zA-Z] { /* an identifier after PUBLIC */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - if( _iState == LOOKUP ) + if( hb_comp_iState == LOOKUP ) { /* it is first item in the line */ hb_xfree( (void *) yylval.string ); - _iState =PUBLIC; + hb_comp_iState =PUBLIC; return PUBLIC; } else { /* there is another item in line already */ - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } -{Separator}*[^a-zA-Z] { /* any character (not identifier or macro) after PUBLIC */ +{Separator}*[^a-zA-Z] { /* any character (not identifier) after PUBLIC */ + /* TODO: add support for macro operator */ unput( yytext[ yyleng-1 ] ); if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } %{ /* ************************************************************************ */ %} "qself"{SpaceTab}*[(]{SpaceTab}*[)] return SELF; -"recover" _iState =RECOVER; return RECOVER; -"retu"|"retur"|"return" _iState =RETURN; return RETURN; -"static" _iState =STATIC; return STATIC; +"recover" hb_comp_iState =RECOVER; return RECOVER; +"retu"|"retur"|"return" hb_comp_iState =RETURN; return RETURN; +"static" hb_comp_iState =STATIC; return STATIC; "step"/[^(] return STEP; "to" return TO; "using" return USING; @@ -1018,7 +1021,7 @@ Separator {SpaceTab} {Separator}*\n { /* end of line */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( '\n' ); - if( _iState == DO ) + if( hb_comp_iState == DO ) { /* we have DO while - replace it with while() */ unput( ')' ); unput( '(' ); } @@ -1028,7 +1031,7 @@ Separator {SpaceTab} {Separator}*[\[] { /* array */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; /* Clipper does not like while[] at all */ - GenError( _szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); } {Separator}*[\:\=\|\$\%\*\,\/\]\)\}\^] { /* there is an operator after "case" */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; @@ -1047,21 +1050,21 @@ Separator {SpaceTab} if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); unput( yytext[ yyleng-2 ] ); - _iState =WHILE; + hb_comp_iState =WHILE; return WHILE; } {Separator}*. { /* identifiers and literals */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - if( _iState == LOOKUP || _iState == DO ) + if( hb_comp_iState == LOOKUP || hb_comp_iState == DO ) { /* it is first item in the line or after DO or FIELD */ - _iState =WHILE; + hb_comp_iState =WHILE; return WHILE; } else { /* there is another item in line already */ yylval.string = yy_strdup( "WHILE" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -1078,34 +1081,34 @@ Separator {SpaceTab} {Separator}*"with" { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; yyless( yyleng-4 ); - if( _iState == DO ) + if( hb_comp_iState == DO ) { /* DO with */ - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; yylval.string = yy_strdup( "WITH" ); return IDENTIFIER; } else { /* DO WITH with */ - _iState =WITH; + hb_comp_iState =WITH; return WITH; } } {Separator}*[\[] { /* array */ /* Clipper does not like with[] at all */ - GenError( _szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_SYNTAX, yytext, NULL ); } {Separator}*. { if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); - if( _iState == WHILE || _iState == DO || _iState == IDENTIFIER ) + if( hb_comp_iState == WHILE || hb_comp_iState == DO || hb_comp_iState == IDENTIFIER ) { /* DO WITH */ - _iState =WITH; + hb_comp_iState =WITH; return WITH; } else { yylval.string = yy_strdup( "WITH" ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } } @@ -1122,48 +1125,40 @@ Separator {SpaceTab} %{ /* ************************************************************************ */ %} -"#" { _iState =OPERATOR; return NE1; } -"=" { _iState =OPERATOR; return yytext[ 0 ]; } -"+" { _iState =OPERATOR; return yytext[ 0 ]; } -"-" { _iState =OPERATOR; return yytext[ 0 ]; } -"*" { _iState =OPERATOR; return yytext[ 0 ]; } -[\/] { _iState =OPERATOR; return yytext[ 0 ]; } -"%" { _iState =OPERATOR; return yytext[ 0 ]; } -"$" { _iState =OPERATOR; return yytext[ 0 ]; } -"<>"|"!=" { _iState =OPERATOR; return NE2; } -":=" { _iState =OPERATOR; return INASSIGN; } -"==" { _iState =OPERATOR; return EQ; } -"++" { _iState =OPERATOR; return INC; } -"--" { _iState =OPERATOR; return DEC; } -"->" { _iState =OPERATOR; return ALIASOP; } -"M->&" { _iState =OPERATOR; return MACROALIAS; } -"MEMV->&" { _iState =OPERATOR; return MACROALIAS; } -"MEMVA->&" { _iState =OPERATOR; return MACROALIAS; } -"MEMVAR->&" { _iState =OPERATOR; return MACROALIAS; } -"&" { _iState =OPERATOR; return MACROOP; } -"<=" { _iState =OPERATOR; return LE; } -">=" { _iState =OPERATOR; return GE; } -"+=" { _iState =OPERATOR; return PLUSEQ; } -"-=" { _iState =OPERATOR; return MINUSEQ; } -"*=" { _iState =OPERATOR; return MULTEQ; } -"/=" { _iState =OPERATOR; return DIVEQ; } -"^=" { _iState =OPERATOR; return EXPEQ; } -"%=" { _iState =OPERATOR; return MODEQ; } -"**"|"^" { _iState =OPERATOR; return POWER; } -"."[t|y]"." { _iState =SEPARATOR; return TRUEVALUE; } -"."[f|n]"." { _iState =SEPARATOR; return FALSEVALUE; } -".and." { _iState =OPERATOR; return AND; } -".or." { _iState =OPERATOR; return OR; } -"!"|".not." { _iState =OPERATOR; return NOT; } -"." { _iState =OPERATOR; return DOT; } -"::" { unput( ':' ); unput( 'f' ); unput( 'l' ); unput( 'e' ); unput( 'S' ); } -[,\{\}\|\#\&\:\<\>\[\]\@] { _iState =OPERATOR; return yytext[ 0 ]; } -[\(] { ++_iOpenBracket; _iState =SEPARATOR; return yytext[ 0 ]; } -[\)] { --_iOpenBracket; _iState =SEPARATOR; return yytext[ 0 ]; } +"#" hb_comp_iState =OPERATOR; return NE1; +"=" hb_comp_iState =OPERATOR; return yytext[ 0 ]; +"+" hb_comp_iState =OPERATOR; return yytext[ 0 ]; +"-" hb_comp_iState =OPERATOR; return yytext[ 0 ]; +"*" hb_comp_iState =OPERATOR; return yytext[ 0 ]; +[\/] hb_comp_iState =OPERATOR; return yytext[ 0 ]; +"%" hb_comp_iState =OPERATOR; return yytext[ 0 ]; +"$" hb_comp_iState =OPERATOR; return yytext[ 0 ]; +"<>"|"!=" hb_comp_iState =OPERATOR; return NE2; +":=" hb_comp_iState =OPERATOR; return INASSIGN; +"==" hb_comp_iState =OPERATOR; return EQ; +"++" hb_comp_iState =OPERATOR; return INC; +"--" hb_comp_iState =OPERATOR; return DEC; +"->" hb_comp_iState =OPERATOR; return ALIASOP; +"<=" hb_comp_iState =OPERATOR; return LE; +">=" hb_comp_iState =OPERATOR; return GE; +"+=" hb_comp_iState =OPERATOR; return PLUSEQ; +"-=" hb_comp_iState =OPERATOR; return MINUSEQ; +"*=" hb_comp_iState =OPERATOR; return MULTEQ; +"/=" hb_comp_iState =OPERATOR; return DIVEQ; +"^=" hb_comp_iState =OPERATOR; return EXPEQ; +"%=" hb_comp_iState =OPERATOR; return MODEQ; +"**"|"^" hb_comp_iState =OPERATOR; return POWER; +".and." hb_comp_iState =OPERATOR; return AND; +".or." hb_comp_iState =OPERATOR; return OR; +"!"|".not." hb_comp_iState =OPERATOR; return NOT; +"::" unput( ':' ); unput( 'f' ); unput( 'l' ); unput( 'e' ); unput( 'S' ); +[,\{\}\|\#\&\:\<\>\[\]\@] hb_comp_iState =OPERATOR; return yytext[ 0 ]; +[\(] ++_iOpenBracket; hb_comp_iState =SEPARATOR; return yytext[ 0 ]; +[\)] --_iOpenBracket; hb_comp_iState =SEPARATOR; return yytext[ 0 ]; {InvalidNumber} BEGIN INVALIDNUM_; yylval.string = yy_strupr( yy_strdup( yytext ) ); ("."|{Separator}+) { - GenError( _szCErrors, 'E', ERR_NUMERIC_FORMAT, NULL, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_NUMERIC_FORMAT, NULL, NULL ); } . { unput( yytext[ yyleng-1 ] ); @@ -1173,31 +1168,6 @@ Separator {SpaceTab} return yy_ConvertNumber( yylval.string ); } -"_FIELD->"{Integer}"->" { - unput( yytext[ yyleng-1 ] ); - unput( yytext[ yyleng-2 ] ); - yytext[ yyleng - 2 ] = 0; - - if( _bRestrictSymbolLength && strlen( yytext ) > 20 ) - { - yytext[ 18 ] = 0; - yyleng = 10; - } - yylval.string = yy_strupr( yy_strdup( yytext + 8 ) ); - _iState = IDENTIFIER; - return IDENTIFIER; - } - -"_FIELD->"{Number}"->" { GenError( _szCErrors, 'E', ERR_ALIASEXP, yytext + 8, NULL ); } - -"_FIELD->" { - unput( yytext[ yyleng-1 ] ); - unput( yytext[ yyleng-2 ] ); - yytext[ yyleng - 2 ] = 0; - yylval.string = yy_strupr( yy_strdup( yytext + 1 ) ); - _iState = IDENTIFIER; - return IDENTIFIER; - } {Number} { return yy_ConvertNumber( yytext ); } @@ -1206,23 +1176,29 @@ Separator {SpaceTab} if( ( double )SHRT_MIN <= lNumber && lNumber <= ( double )SHRT_MAX ) { - yylval.iNumber = lNumber; + yylval.valInteger.iNumber = lNumber; + yylval.valInteger.szValue = yytext; return NUM_INTEGER; } else if( ( double )LONG_MIN <= lNumber && lNumber <= ( double )LONG_MAX ) { - yylval.lNumber = lNumber; + yylval.valLong.lNumber = lNumber; + yylval.valLong.szValue = yytext; return NUM_LONG; } else { - yylval.dNum.dNumber = lNumber; - yylval.dNum.bDec = 0; + yylval.valDouble.dNumber = lNumber; + yylval.valDouble.bDec = 0; + yylval.valDouble.szValue = yytext; return NUM_DOUBLE; } } +{TrueValue} { hb_comp_iState =SEPARATOR; return TRUEVALUE; } +{FalseValue} { hb_comp_iState =SEPARATOR; return FALSEVALUE; } + {Array} { if( ! i_INDEX_STATE ) { @@ -1240,14 +1216,14 @@ Separator {SpaceTab} yytext[yyleng] = 0; { - if( _bRestrictSymbolLength && strlen( yytext ) > 10 ) + if( hb_comp_bRestrictSymbolLength && strlen( yytext ) > 10 ) { yytext[ 10 ] = 0; yyleng = 10; } yylval.string = yy_strupr( yy_strdup( yytext ) ); /*printf( "\nIdentifier = '%s'\n", yy_strupr( yy_strdup( yytext ) ) );*/ - _iState = IDENTIFIER; + hb_comp_iState = IDENTIFIER; return IDENTIFIER; } } @@ -1261,7 +1237,7 @@ Separator {SpaceTab} } unput( '[' ); - _iState = OPERATOR; + hb_comp_iState = OPERATOR; --_iOpenBracket; return ')'; } @@ -1277,7 +1253,7 @@ Separator {SpaceTab} iIndexSets--; unput( '[' ); - _iState = OPERATOR; + hb_comp_iState = OPERATOR; return ']'; } @@ -1290,34 +1266,19 @@ Separator {SpaceTab} } unput( '[' ); - _iState = OPERATOR; + hb_comp_iState = OPERATOR; --_iOpenBracket; return '}'; } -"_FIELD->"{Identifier}"->" { - unput( yytext[ yyleng-1 ] ); - unput( yytext[ yyleng-2 ] ); - yytext[ yyleng - 2 ] = 0; - - if( _bRestrictSymbolLength && strlen( yytext ) > 20 ) - { - yytext[ 18 ] = 0; - yyleng = 10; - } - yylval.string = yy_strupr( yy_strdup( yytext + 8 ) ); - _iState = IDENTIFIER; - return IDENTIFIER; - } - {Identifier} { - if( _bRestrictSymbolLength && strlen( yytext ) > 10 ) + if( hb_comp_bRestrictSymbolLength && strlen( yytext ) > 10 ) { yytext[ 10 ] = 0; yyleng = 10; } yylval.string = yy_strupr( yy_strdup( yytext ) ); - _iState =IDENTIFIER; + hb_comp_iState =IDENTIFIER; return IDENTIFIER; } @@ -1341,30 +1302,34 @@ static int yy_ConvertNumber( char * szBuffer ) { char * ptr; - yylval.dNum.dNumber = atof( szBuffer ); + yylval.valDouble.dNumber = atof( szBuffer ); ptr = strchr( szBuffer, '.' ); if( ptr ) { - yylval.dNum.bDec = strlen( ptr + 1 ); + yylval.valDouble.bDec = strlen( ptr + 1 ); + yylval.valDouble.szValue = szBuffer; return NUM_DOUBLE; } else { - if( ( double )SHRT_MIN <= yylval.dNum.dNumber && - yylval.dNum.dNumber <= ( double )SHRT_MAX ) + if( ( double )SHRT_MIN <= yylval.valDouble.dNumber && + yylval.valDouble.dNumber <= ( double )SHRT_MAX ) { - yylval.iNumber = ( int ) yylval.dNum.dNumber; + yylval.valInteger.iNumber = ( int ) yylval.valDouble.dNumber; + yylval.valInteger.szValue = szBuffer; return NUM_INTEGER; } - else if( ( double )LONG_MIN <= yylval.dNum.dNumber && - yylval.dNum.dNumber <= ( double )LONG_MAX ) + else if( ( double )LONG_MIN <= yylval.valDouble.dNumber && + yylval.valDouble.dNumber <= ( double )LONG_MAX ) { - yylval.lNumber = ( long ) yylval.dNum.dNumber; + yylval.valLong.lNumber = ( long ) yylval.valDouble.dNumber; + yylval.valLong.szValue = szBuffer; return NUM_LONG; } else { - yylval.dNum.bDec = 0; + yylval.valDouble.bDec = 0; + yylval.valDouble.szValue = szBuffer; return NUM_DOUBLE; } } diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 28005bf5b3..0c87a94044 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -46,126 +46,18 @@ * 6) support for expr:expr (QSELF():cVar) syntax. * see tests/broken/clasname.prg * 7) Change the pcode generated by ::cVar from Self:cVar to QSELF():cVar - * 8) Support this syntax: nPtr := @Hello() - * 9) Support for syntax: FOR [ array | object | alias_expr | other ] := value + * 8) Support this syntax: _FIELD->c->mmezo := mt + * 9) Support this syntax: nPtr := @Hello() + *10) Support for syntax: FOR [ array | object | alias_expr | other ] := value */ +#include "compiler.h" + /* Compile using: bison -d -v harbour.y */ -#include -#include -#include -#include -#include /* required for allocating and freeing memory */ -#include -#include -#include "extend.h" -#include "pcode.h" /* pcode values */ -#include "compiler.h" -#include "hberrors.h" -#include "hbpp.h" -#include "hbver.h" - -#define debug_msg( x, z ) - extern FILE *yyin; /* currently yacc parsed file */ extern int iLine; /* currently parsed file line number */ - /* Following two lines added for preprocessor */ -extern BOOL _bPPO; /* flag indicating, is ppo output needed */ -extern FILE *yyppo; /* output .ppo file */ -extern char *yytext; /* have accees to original string form of numbers */ - -typedef struct /* #include support */ -{ - FILE * handle; /* handle of the opened file */ - void * pBuffer; /* buffer used by yacc */ - char * szFileName; /* name of the file */ - void * pPrev; /* pointer to the previous opened file */ - void * pNext; /* pointer to the next opened file */ - int iLine; /* currently processed line number */ -} _FILE, * PFILE; /* structure to hold an opened PRG or CH */ - -typedef struct -{ - PFILE pLast; /* pointer to the last opened file */ - int iFiles; /* number of files currently opened */ -} FILES; /* structure to control several opened PRGs and CHs */ - -int Include( char * szFileName, PATHNAMES * pSearchPath ); /* end #include support */ - -/* pcode chunks bytes size */ -#define PCODE_CHUNK 100 - -typedef struct __ELSEIF -{ - ULONG ulOffset; - struct __ELSEIF * pNext; -} _ELSEIF, * PELSEIF; /* support structure for else if pcode fixups */ - -typedef struct _LOOPEXIT -{ - ULONG ulOffset; - int iLine; - USHORT wSeqCounter; - struct _LOOPEXIT * pLoopList; - struct _LOOPEXIT * pExitList; - struct _LOOPEXIT * pNext; -} LOOPEXIT, * PTR_LOOPEXIT; /* support structure for EXIT and LOOP statements */ -static void LoopStart( void ); -static void LoopEnd( void ); -static void LoopLoop( void ); -static void LoopExit( void ); -static void LoopHere( void ); - -typedef struct __EXTERN -{ - char * szName; - struct __EXTERN * pNext; -} _EXTERN, * PEXTERN; /* support structure for extern symbols */ -/* as they have to be placed on the symbol table later than the first public symbol */ - -/* Support for aliased expressions - */ -typedef struct _ALIASID -{ - char type; - union { - int iAlias; - char * szAlias; - } alias; - struct _ALIASID * pPrev; -} ALIASID, *ALIASID_PTR; - -#define ALIAS_NUMBER 1 -#define ALIAS_NAME 2 -#define ALIAS_EVAL 3 - -static ULONG PackDateTime( void ); - -void AliasAddInt( int ); -void AliasAddExp( void ); -void AliasAddStr( char * ); -void AliasPush( void ); -void AliasPop( void ); -void AliasSwap( void ); -void AliasAdd( ALIASID_PTR ); -void AliasRemove( void ); - -/* Support for parenthesized expressions - */ -typedef struct _EXPLIST -{ - BYTE * prevPCode; /* pcode buffer used at the start of expression */ - ULONG prevSize; - ULONG prevPos; - BYTE * exprPCode; /* pcode buffer for current expression */ - ULONG exprSize; - struct _EXPLIST *pPrev; /* previous expression in the list */ - struct _EXPLIST *pNext; /* next expression in the list */ -} EXPLIST, *EXPLIST_PTR; - -void ExpListPush( void ); /* pushes the new expression on the stack */ -void ExpListPop( int ); /* pops previous N expressions */ +extern char *yytext; #ifdef __cplusplus typedef struct yy_buffer_state *YY_BUFFER_STATE; @@ -187,351 +79,62 @@ extern "C" int yywrap( void ); #else int yywrap( void ); /* manages the EOF of current processed file */ #endif - /* Following line added for preprocessor */ -void Hbpp_init ( void ); -/* production related functions */ -static void ArrayAt( void ); -static void ArrayPut( void ); -void ArrayDim( int iDimensions ); /* instructs the virtual machine to build an array with wDimensions */ +static void LoopStart( void ); +static void LoopEnd( void ); +static void LoopLoop( void ); +static void LoopExit( void ); +static void LoopHere( void ); -PFUNCTION AddFunCall( char * szFuntionName ); -void AddExtern( char * szExternName ); /* defines a new extern name */ -void AddSearchPath( char *, PATHNAMES * * ); /* add pathname to a search list */ -void AddVar( char * szVarName ); /* add a new param, local, static variable to a function definition or a public or private */ -void SetVarMacro( void ); /* Set the stack for the creation of a MACRO variable */ -void FunMacroAssign( void ); /* stores the last interpreted macro to be reused if inline assignment */ -PCOMSYMBOL AddSymbol( char *, USHORT * ); -void CheckDuplVars( PVAR pVars, char * szVarName, int iVarScope ); /*checks for duplicate variables definitions */ -void Dec( void ); /* generates the pcode to decrement the latest value on the virtual machine stack */ -void Do( BYTE bParams ); /* generates the pcode to execute a Clipper function discarding its result */ -void Duplicate( void ); /* duplicates the virtual machine latest stack latest value and places it on the stack */ -void DupPCode( ULONG ulStart ); /* duplicates the current generated pcode from an offset */ -void FieldPCode( BYTE , char * ); /* generates the pcode for database field */ -void FixElseIfs( void * pIfElseIfs ); /* implements the ElseIfs pcode fixups */ -void FixReturns( void ); /* fixes all last defined function returns jumps offsets */ -void Function( BYTE bParams ); /* generates the pcode to execute a Clipper function pushing its result */ -PFUNCTION FunctionNew( char *, char ); /* creates and initialises the _FUNC structure */ -void FunDef( char * szFunName, HB_SYMBOLSCOPE cScope, int iType ); /* starts a new Clipper language function definition */ -void GenArray( int iElements ); /* instructs the virtual machine to build an array and load elemnst from the stack */ -void GenBreak( void ); /* generate code for BREAK statement */ -void * GenElseIf( void * pFirstElseIf, ULONG ulOffset ); /* generates a support structure for elseifs pcode fixups */ -void GenExterns( void ); /* generates the symbols for the EXTERN names */ -void GenIfInline( void ); /* generates pcodes for IIF( expr1, expr2, expr3 ) */ -int GetFieldVarPos( char *, PFUNCTION ); /* return if passed name is a field variable */ -int GetMemvarPos( char *, PFUNCTION ); /* return if passed name is a memvar variable */ -USHORT GetVarPos( PVAR pVars, char * szVarName ); /* returns the order + 1 of a variable if defined or zero */ -int GetLocalVarPos( char * szVarName ); /* returns the order + 1 of a local variable */ -void Inc( void ); /* generates the pcode to increment the latest value on the virtual machine stack */ -ULONG Jump( LONG lOffset ); /* generates the pcode to jump to a specific offset */ -ULONG JumpFalse( LONG lOffset ); /* generates the pcode to jump if false */ -void JumpHere( ULONG ulOffset ); /* returns the pcode pos where to set a jump offset */ -void JumpThere( ULONG ulFrom, ULONG ulTo ); /* sets a jump offset */ -ULONG JumpTrue( LONG lOffset ); /* generates the pcode to jump if true */ -void Line( void ); /* generates the pcode with the currently compiled source code line */ -void LineDebug( void ); /* generates the pcode with the currently compiled source code line */ -void LineBody( void ); /* generates the pcode with the currently compiled source code line */ -void VariablePCode( BYTE , char * ); /* generates the pcode for undeclared variable */ -void MemvarPCode( BYTE , char * ); /* generates the pcode for memvar variable */ -void Message( char * szMsgName ); /* sends a message to an object */ -void MessageFix( char * szMsgName ); /* fix a generated message to an object */ -void MessageDupl( char * szMsgName ); /* fix a one generated message to an object and duplicate */ -void PopId( char * szVarName ); /* generates the pcode to pop a value from the virtual machine stack onto a variable */ -void PushDouble( double fNumber, BYTE bDec ); /* Pushes a number on the virtual machine stack */ -void PushFunCall( char * ); /* generates the pcode to push function's call */ -void PushId( char * szVarName ); /* generates the pcode to push a variable value to the virtual machine stack */ -void PushIdByRef( char * szVarName ); /* generates the pcode to push a variable by reference to the virtual machine stack */ -void PushInteger( int iNumber ); /* Pushes a integer number on the virtual machine stack */ -void PushLogical( int iTrueFalse ); /* pushes a logical value on the virtual machine stack */ -void PushLong( long lNumber ); /* Pushes a long number on the virtual machine stack */ -void PushNil( void ); /* Pushes nil on the virtual machine stack */ -void PushString( char * szText ); /* Pushes a string on the virtual machine stack */ -void PushSymbol( char * szSymbolName, int iIsFunction ); /* Pushes a symbol on to the Virtual machine stack */ -char * SetData( char * szMsg ); /* generates an underscore-symbol name for a data assignment */ -static void GenPlusPCode( BYTE ); /* Generates opcode for plus/minus operands */ -static void GenNumPCode( BYTE ); /* Generates opcode for numerical operands */ -static void GenRelPCode( BYTE ); /* Generates opcode for relational operands */ -static void GenNotPCode( void ); /* Generates HB_P_NOT opcode */ -static void GenNegatePCode( void ); /* Generates HB_P_NEGATE opcode */ -static void GenPopPCode( void ); /* Generates HB_P_POP opcode */ -static void RemoveExtraPush( void ); /* Removes redundant push opcode */ -static void SetLastPushPos( void ); /* Resets postion of last possible redundant push opcode */ +/* Misc functions defined in harbour.c */ +extern PHB_FNAME hb_fsFNameSplit( char * szFileName ); +extern char * hb_fsFNameMerge( char * szFileName, PHB_FNAME pFileName ); +extern void * hb_xgrab( ULONG ulSize ); /* allocates fixed memory, exits on failure */ +extern void * hb_xrealloc( void * pMem, ULONG ulSize ); /* reallocates memory */ +extern void hb_xfree( void * pMem ); /* frees fixed memory */ +extern char * yy_strupr( char * p ); +extern char * yy_strdup( char * p ); +extern void hb_compGenError( char* _szErrors[], char cPrefix, int iError, char * szError1, char * szError2 ); +extern void hb_compGenWarning( char* _szWarnings[], char cPrefix, int iWarning, char * szWarning1, char * szWarning2); -static void GenPCode1( BYTE ); /* generates 1 byte of pcode */ -static void GenPCode3( BYTE, BYTE, BYTE ); /* generates 3 bytes of pcode */ -static void GenPCodeN( BYTE * pBuffer, ULONG ulSize ); /* copy bytes to a pcode buffer */ - -ULONG SequenceBegin( void ); -ULONG SequenceEnd( void ); -void SequenceFinish( ULONG, int ); - -/* Managing value type */ -extern void ValTypePush( char cType ); /* Pushes the type of expression (used with -w3 option */ -extern void ValTypePop( int ); -extern void ValTypePlus( void ); -extern void ValTypeRelational( void ); -extern void ValTypeCheck( char, int, int ); -extern void ValTypeCheck2( char, int, int ); -extern char ValTypeGet( void ); -extern void ValTypePut( char ); -extern void ValTypeAssign( char * ); -extern void ValTypeReset( void ); - -/* support for FIELD declaration */ -void FieldsSetAlias( char *, int ); -int FieldsCount( void ); - -/* Codeblocks */ -void CodeBlockStart( void ); /* starts a codeblock creation */ -void CodeBlockEnd( void ); /* end of codeblock creation */ - -/* Static variables */ -void StaticDefStart( void ); -void StaticDefEnd( int ); -void StaticAssign( void ); /* checks if static variable is initialized with function call */ - -/* output related functions */ -extern void GenCCode( PHB_FNAME ); /* generates the C language output */ -extern void GenJava( PHB_FNAME ); /* generates the Java language output */ -extern void GenPascal( PHB_FNAME ); /* generates the Pascal language output */ -extern void GenRC( PHB_FNAME ); /* generates the RC language output */ -extern void GenPortObj( PHB_FNAME ); /* generates the portable objects */ -#ifdef HARBOUR_OBJ_GENERATION -extern void GenObj32( PHB_FNAME ); /* generates OBJ 32 bits */ -#endif - -/* argument checking */ -void CheckArgs( char *, int ); -static BOOL SwitchCmp( char * szString, char * szSwitch ); - -void PrintUsage( char * ); -void PrintCredits( void ); #ifdef HARBOUR_YYDEBUG #define YYDEBUG 1 /* Parser debug information support */ #endif -typedef enum -{ - LANG_C, /* C language (by default) */ - LANG_OBJ32, /* DOS/Windows 32 bits */ - LANG_JAVA, /* Java */ - LANG_PASCAL, /* Pascal */ - LANG_RESOURCES, /* Resources */ - LANG_PORT_OBJ /* Portable objects */ -} LANGUAGES; /* supported Harbour output languages */ -int iVarScope = VS_LOCAL; /* holds the scope for next variables to be defined */ - /* different values for iVarScope */ +USHORT hb_comp_wSeqCounter = 0; +USHORT hb_comp_wForCounter = 0; +USHORT hb_comp_wIfCounter = 0; +USHORT hb_comp_wWhileCounter = 0; +USHORT hb_comp_wCaseCounter = 0; -/* Table with parse errors */ -char * _szCErrors[] = -{ - "Statement not allowed outside of procedure or function", - "Redefinition of procedure or function: \'%s\'", - "Duplicate variable declaration: \'%s\'", - "%s declaration follows executable statement", - "Outer codeblock variable is out of reach: \'%s\'", - "Invalid numeric format '.'", - "Unterminated string: \'%s\'", - "Redefinition of predefined function %s: \'%s\'", - "Illegal initializer: \'%s\'", - "ENDIF does not match IF", - "ENDDO does not match WHILE", - "ENDCASE does not match DO CASE", - "NEXT does not match FOR", - "ELSE does not match IF", - "ELSEIF does not match IF", - "Syntax error: \'%s\'", - "Unclosed control structures", - "%s statement with no loop in sight", - "Syntax error: \'%s\' in: \'%s\'", - "Incomplete statement: %s", - "Incorrect number of arguments: %s %s", - "Invalid lvalue", - "Invalid use of \'@\' (pass by reference): \'%s\'", - "Formal parameters already declared", - "Invalid %s from within of SEQUENCE code", - "Unterminated array index", - "Memory allocation error", - "Memory reallocation error", - "Freeing a NULL memory pointer", - "Parser says: \"%s\"", - "Jump offset too long", - "Can't create output file: \'%s\'", - "Can't create preprocessed output file: \'%s\'", - "Bad command line option: \'%s\'", - "Bad command line parameter: \'%s\'", - "Invalid filename: \'%s\'", - "Mayhem in CASE handler", - "Invalid alias expression: \'%s'" -}; - -/* Table with parse warnings */ -/* NOTE: The first character stores the warning's level that triggers this - * warning. The warning's level is set by -w command line option. - */ -char * _szCWarnings[] = -{ - "1Ambiguous reference: \'%s\'", - "1Ambiguous reference, assuming memvar: \'%s\'", - "2Variable: \'%s\' declared but not used in function: \'%s\'", - "2CodeBlock Parameter: \'%s\' declared but not used in function: \'%s\'", - "1RETURN statement with no return value in function", - "1Procedure returns value", - "1Function \'%s\' does not end with RETURN statement", - "3Incompatible type in assignment to: \'%s\' expected: \'%s\'", - "3Incompatible operand type: \'%s\' expected: \'Logical\'", - "3Incompatible operand type: \'%s\' expected: \'Numeric\'", - "3Incompatible operand types: \'%s\' and: \'%s\'", - "3Suspicious type in assignment to: \'%s\' expected: \'%s\'", - "3Suspicious operand type: \'UnKnown\' expected: \'%s\'", - "3Suspicious operand type: \'UnKnown\' expected: \'Logical\'", - "3Suspicious operand type: \'UnKnown\' expected: \'Numeric\'" -}; - -/* Table with reserved functions names - * NOTE: THIS TABLE MUST BE SORTED ALPHABETICALLY -*/ -static const char * _szReservedFun[] = { - "AADD" , - "ABS" , - "ASC" , - "AT" , - "BOF" , - "BREAK" , - "CDOW" , - "CHR" , - "CMONTH" , - "COL" , - "CTOD" , - "DATE" , - "DAY" , - "DELETED" , - "DEVPOS" , - "DOW" , - "DTOC" , - "DTOS" , - "EMPTY" , - "EOF" , - "EXP" , - "FCOUNT" , - "FIELDNAME" , - "FLOCK" , - "FOUND" , - "INKEY" , - "INT" , - "LASTREC" , - "LEFT" , - "LEN" , - "LOCK" , - "LOG" , - "LOWER" , - "LTRIM" , - "MAX" , - "MIN" , - "MONTH" , - "PCOL" , - "PCOUNT" , - "PROW" , - "QSELF" , - "RECCOUNT" , - "RECNO" , - "REPLICATE" , - "RLOCK" , - "ROUND" , - "ROW" , - "RTRIM" , - "SECONDS" , - "SELECT" , - "SETPOS" , - "SETPOSBS" , - "SPACE" , - "SQRT" , - "STR" , - "SUBSTR" , - "TIME" , - "TRANSFORM" , - "TRIM" , - "TYPE" , - "UPPER" , - "VAL" , - "WORD" , - "YEAR" -}; -#define RESERVED_FUNCTIONS sizeof( _szReservedFun ) / sizeof( char * ) - -static char * reserved_name( char * ); - -#define RESERVED_FUNC(szName) reserved_name( (szName) ) - -FILES files; -FUNCTIONS functions, funcalls; -PFUNCTION _pInitFunc; -SYMBOLS symbols; - -/* /ES command line setting types */ -#define HB_EXITLEVEL_DEFAULT 0 -#define HB_EXITLEVEL_SETEXIT 1 -#define HB_EXITLEVEL_DELTARGET 2 - -int iFunctions = 0; - -BOOL _bStartProc = TRUE; /* holds if we need to create the starting procedure */ -BOOL _bLineNumbers = TRUE; /* holds if we need pcodes with line numbers */ -BOOL _bCredits = FALSE; /* print credits */ -BOOL _bLogo = TRUE; /* print logo */ -BOOL _bQuiet = FALSE; /* quiet mode */ -BOOL _bSyntaxCheckOnly = FALSE; /* syntax check only */ -int _iLanguage = LANG_C; /* default Harbour generated output language */ -BOOL _bRestrictSymbolLength = FALSE; /* generate 10 chars max symbols length */ -BOOL _bShortCuts = TRUE; /* .and. & .or. expressions shortcuts */ -int _iWarnings = 0; /* enable parse warnings */ -BOOL _bAnyWarning = FALSE; /* holds if there was any warning during the compilation process */ -BOOL _bAutoMemvarAssume = FALSE; /* holds if undeclared variables are automatically assumed MEMVAR (-a)*/ -BOOL _bForceMemvars = FALSE; /* holds if memvars are assumed when accesing undeclared variable (-v)*/ -BOOL _bDebugInfo = FALSE; /* holds if generate debugger required info */ -char _szPrefix[ 20 ] = { '\0' }; /* holds the prefix added to the generated symbol init function name (in C output currently) */ -BOOL _bGenCVerbose = TRUE; /* C code generation should be verbose (use comments) or not */ -int _iExitLevel = HB_EXITLEVEL_DEFAULT; /* holds if there was any warning during the compilation process */ - -USHORT _wSeqCounter = 0; -USHORT _wForCounter = 0; -USHORT _wIfCounter = 0; -USHORT _wWhileCounter = 0; -USHORT _wCaseCounter = 0; -ULONG _ulMessageFix = 0; /* Position of the message which needs to be changed */ -ULONG _ulBookMark = 0; -int _iStatics = 0; /* number of defined statics variables on the PRG */ -PEXTERN pExterns = NULL; -PTR_LOOPEXIT pLoops = NULL; -PATHNAMES *_pIncludePath = NULL; -PHB_FNAME _pFileName = NULL; -PHB_FNAME _pOutPath = NULL; -ALIASID_PTR pAliasId = NULL; -ULONG _ulLastLinePos = 0; /* position of last opcode with line number */ -BOOL _bDontGenLineNum = FALSE; /* suppress line number generation */ - -EXPLIST_PTR _pExpList = NULL; /* stack used for parenthesized expressions */ - -char _cVarType = ' '; /* current declared variable type */ - -#define LOOKUP 0 -extern int _iState; /* current parser state (defined in harbour.l */ %} -%union /* special structure used by lex and yacc to share info */ +%union /* special structure used by lex and yacc to share info */ { - char * string; /* to hold a string returned by lex */ - int iNumber; /* to hold a number returned by lex */ - long lNumber; /* to hold a long number returned by lex */ + char * string; /* to hold a string returned by lex */ + int iNumber; /* to hold a temporary integer number */ + long lNumber; /* to hold a temporary long number */ struct { - double dNumber; /* to hold a double number returned by lex */ + int iNumber; /* to hold a number returned by lex */ + char * szValue; + } valInteger; + struct + { + long lNumber; /* to hold a long number returned by lex */ + char * szValue; + } valLong; + struct + { + double dNumber; /* to hold a double number returned by lex */ /* NOTE: Intentionally using "unsigned char" instead of "BYTE" */ unsigned char bDec; /* to hold the number of decimal points in the value */ - } dNum; + char * szValue; + } valDouble; + HB_EXPR_PTR asExpr; void * pVoid; /* to hold any memory structure we may need */ }; @@ -543,7 +146,6 @@ extern int _iState; /* current parser state (defined in harbour.l */ %token PLUSEQ MINUSEQ MULTEQ DIVEQ POWER EXPEQ MODEQ EXITLOOP %token PRIVATE BEGINSEQ BREAK RECOVER USING DO WITH SELF LINE %token AS_NUMERIC AS_CHARACTER AS_LOGICAL AS_DATE AS_ARRAY AS_BLOCK AS_OBJECT DECLARE_FUN -%token DOT MACROALIAS MACROOP /*the lowest precedence*/ /*postincrement and postdecrement*/ @@ -563,32 +165,63 @@ extern int _iState; /* current parser state (defined in harbour.l */ %left '+' '-' %left '*' '/' '%' %left POWER -%left UNARY +%right UNARY /*preincrement and predecrement*/ %left PRE /*special operators*/ -%left ALIASOP MACROOP '@' ')' +%left ALIASOP '&' '@' %right '\n' ';' ',' /*the highest precedence*/ -%type IDENTIFIER LITERAL FunStart MethStart IdSend ObjectData AliasVar -%type NUM_DOUBLE -%type ArgList ElemList PareExpList ExpList FunCall FunScope IncDec -%type Params ParamList Logical ArrExpList -%type NUM_INTEGER BlockExpList Argument IfBegin VarList MethParams ObjFunCall, ExtVarList -%type MethCall BlockList FieldList DoArgList VarAt -%type NUM_LONG WhileBegin BlockBegin +%type IDENTIFIER LITERAL +%type NUM_DOUBLE +%type NUM_INTEGER +%type NUM_LONG +%type FunScope AsType +%type Params ParamList +%type IfBegin VarList +%type FieldList DoArgList +%type WhileBegin %type IfElseIf Cases +%type Argument ArgList ElemList BlockExpList BlockVarList BlockNoVar +%type PareExpList1 PareExpList2 PareExpList3 PareExpListN +%type ExpList ExpList1 ExpList2 ExpList3 +%type NumValue NumAlias +%type NilValue NilAlias +%type LiteralValue LiteralAlias +%type CodeBlock CodeBlockAlias +%type Logical LogicalAlias +%type SelfValue SelfAlias +%type Array ArrayAlias +%type ArrayAt ArrayAtAlias +%type Variable VarAlias +%type MacroVar MacroVarAlias +%type MacroExpr MacroExprAlias +%type AliasVar AliasExpr +%type VariableAt VariableAtAlias +%type FunCall FunCallAlias +%type ObjectData ObjectDataAlias +%type ObjectMethod ObjectMethodAlias +%type IfInline IfInlineAlias +%type PareExpList PareExpListAlias +%type Expression SimpleExpression LValue +%type EmptyExpression +%type ExprAssign ExprOperEq ExprEqual ExprPreOp ExprPostOp +%type ExprEqual ExprMath ExprBool ExprRelation +%type ArrayIndex IndexList +%type DimIndex DimList +%type FieldAlias FieldVarAlias +%type PostOp %% Main : { Line(); } Source { FixReturns(); /* fix all previous function returns offsets */ - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) { - if( ! _bStartProc ) - --iFunctions; - printf( "\rLines %i, Functions/Procedures %i\n", iLine, iFunctions ); + if( ! hb_comp_bStartProc ) + --hb_comp_iFunctionCnt; + printf( "\rLines %i, Functions/Procedures %i\n", iLine, hb_comp_iFunctionCnt ); } } @@ -601,7 +234,7 @@ Source : Crlf | Line | Source Crlf | Source Function - | Source { LineBody(); } Statement + | Source Statement | Source VarDefs | Source FieldsDef | Source MemvarDef @@ -612,9 +245,9 @@ Line : LINE NUM_INTEGER LITERAL Crlf | LINE NUM_INTEGER LITERAL '@' LITERAL Crlf /* XBase++ style */ ; -Function : FunScope FUNCTION IDENTIFIER { _cVarType = ' '; FunDef( $3, ( HB_SYMBOLSCOPE ) $1, 0 ); } Params Crlf {} - | FunScope PROCEDURE IDENTIFIER { _cVarType = ' '; FunDef( $3, ( HB_SYMBOLSCOPE ) $1, FUN_PROCEDURE ); } Params Crlf {} - | FunScope DECLARE_FUN IDENTIFIER Params AsType Crlf { AddSymbol( $3, NULL ); } +Function : FunScope FUNCTION IDENTIFIER { hb_comp_cVarType = ' '; hb_compFunDef( $3, ( HB_SYMBOLSCOPE ) $1, 0 ); } Params Crlf {} + | FunScope PROCEDURE IDENTIFIER { hb_comp_cVarType = ' '; hb_compFunDef( $3, ( HB_SYMBOLSCOPE ) $1, FUN_PROCEDURE ); } Params Crlf {} + | FunScope DECLARE_FUN IDENTIFIER Params AsType Crlf { hb_compAddSymbol( $3, NULL ); } ; FunScope : { $$ = FS_PUBLIC; } @@ -625,79 +258,72 @@ FunScope : { $$ = FS_PUBLIC; } Params : { $$ = 0; } | '(' ')' { $$ = 0; } - | '(' { iVarScope = VS_PARAMETER; } ParamList ')' { $$ = $3; } + | '(' { hb_comp_iVarScope = VS_PARAMETER; } ParamList ')' { $$ = $3; } ; -AsType : /* unknown */ { _cVarType = ' '; } - | AS_NUMERIC { _cVarType = 'N'; } - | AS_CHARACTER { _cVarType = 'C'; } - | AS_DATE { _cVarType = 'D'; } - | AS_LOGICAL { _cVarType = 'L'; } - | AS_ARRAY { _cVarType = 'A'; } - | AS_BLOCK { _cVarType = 'B'; } - | AS_OBJECT { _cVarType = 'O'; } +AsType : /* not specified */ { hb_comp_cVarType = ' '; } + | AS_NUMERIC { hb_comp_cVarType = 'N'; } + | AS_CHARACTER { hb_comp_cVarType = 'C'; } + | AS_DATE { hb_comp_cVarType = 'D'; } + | AS_LOGICAL { hb_comp_cVarType = 'L'; } + | AS_ARRAY { hb_comp_cVarType = 'A'; } + | AS_BLOCK { hb_comp_cVarType = 'B'; } + | AS_OBJECT { hb_comp_cVarType = 'O'; } ; -ParamList : IDENTIFIER AsType { AddVar( $1 ); $$ = 1; } - | ParamList ',' IDENTIFIER AsType { AddVar( $3 ); $$++; } +ParamList : IDENTIFIER AsType { hb_compAddVar( $1, ' ' ); $$ = 1; } + | ParamList ',' IDENTIFIER AsType { hb_compAddVar( $3, $4 ); $$++; } ; -Statement : ExecFlow Crlf {} - | FunCall Crlf { Do( $1 ); } - | AliasFunc Crlf {} - | IfInline Crlf { GenPopPCode(); } - | ObjectMethod Crlf { GenPopPCode(); } - | VarUnary Crlf { GenPopPCode(); } - | VarExpr Crlf { RemoveExtraPush(); } - - | { PushSymbol( yy_strdup( "__MVPUT" ), 1); PushNil(); } VarMacro MacroAssign Expression { Do( 2 ); } Crlf - - | IDENTIFIER '=' Expression { PopId( $1 ); } Crlf - | AliasVar '=' { $$=( void * )pAliasId; pAliasId = NULL; } Expression { pAliasId=(ALIASID_PTR) $3; PopId( $1 ); AliasRemove(); } Crlf - | AliasFunc '=' Expression { --iLine; GenError( _szCErrors, 'E', ERR_INVALID_LVALUE, NULL, NULL ); } Crlf - | VarAt '=' Expression { ArrayPut(); GenPopPCode(); } Crlf - | ArrayAt '=' Expression { GenPopPCode();GenPopPCode(); GenPopPCode(); } Crlf - | FunCallArray '=' Expression { ArrayPut(); GenPopPCode(); } Crlf - | ObjectData '=' { MessageFix( SetData( $1 ) ); } Expression { Function( 1 ); GenPopPCode(); } Crlf - | ObjectData ArrayIndex '=' Expression { ArrayPut(); GenPopPCode(); } Crlf - | ObjectMethod ArrayIndex '=' Expression { ArrayPut(); GenPopPCode(); } Crlf - - | BREAK { GenBreak(); } Crlf { Do( 0 ); } - | BREAK { GenBreak(); } Expression Crlf { Do( 1 ); } - | RETURN { - if( _wSeqCounter ) +/* NOTE: This alllows the use of Expression as a statement. + * The Expression is validated later in reduction phase of + * hb_compExprGenStatement(). With this solution we don't have to + * stop compilation if invalid syntax will be used. + */ +Statement : ExecFlow CrlfStmnt { } + | Expression { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } CrlfStmnt + | BREAK { hb_compGenBreak(); } CrlfStmnt { hb_compGenDoProc( 0 ); } + | BREAK { hb_compGenBreak(); } Expression CrlfStmnt { hb_compExprDelete( hb_compExprGenPush( $3 ) ); hb_compGenDoProc( 1 ); } + | RETURN CrlfStmnt { + if( hb_comp_wSeqCounter ) { - GenError( _szCErrors, 'E', ERR_EXIT_IN_SEQUENCE, "RETURN", NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_EXIT_IN_SEQUENCE, "RETURN", NULL ); } - GenPCode1( HB_P_ENDPROC ); - if( (functions.pLast->bFlags & FUN_PROCEDURE) == 0 ) + hb_compGenPCode1( HB_P_ENDPROC ); + if( (hb_comp_functions.pLast->bFlags & FUN_PROCEDURE) == 0 ) { /* return from a function without a return value */ - GenWarning( _szCWarnings, 'W', WARN_NO_RETURN_VALUE, NULL, NULL ); + hb_compGenWarning( hb_comp_szCWarnings, 'W', WARN_NO_RETURN_VALUE, NULL, NULL ); } - functions.pLast->bFlags |= FUN_WITH_RETURN; - } Crlf - | RETURN Expression { - if( _wSeqCounter ) + hb_comp_functions.pLast->bFlags |= FUN_WITH_RETURN; + hb_comp_bDontGenLineNum = TRUE; + } + | RETURN Expression CrlfStmnt { + if( hb_comp_wSeqCounter ) { - GenError( _szCErrors, 'E', ERR_EXIT_IN_SEQUENCE, "RETURN", NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_EXIT_IN_SEQUENCE, "RETURN", NULL ); } - GenPCode1( HB_P_RETVALUE ); GenPCode1( HB_P_ENDPROC ); - ValTypePop( 1 ); /* TODO: check if return value agree with declared value */ - if( functions.pLast->bFlags & FUN_PROCEDURE ) + hb_compExprGenPush( $2 ); /* TODO: check if return value agree with declared value */ + hb_compGenPCode1( HB_P_RETVALUE ); + hb_compGenPCode1( HB_P_ENDPROC ); + if( hb_comp_functions.pLast->bFlags & FUN_PROCEDURE ) { /* procedure returns a value */ - GenWarning( _szCWarnings, 'W', WARN_PROC_RETURN_VALUE, NULL, NULL ); + hb_compGenWarning( hb_comp_szCWarnings, 'W', WARN_PROC_RETURN_VALUE, NULL, NULL ); } - functions.pLast->bFlags |= FUN_WITH_RETURN; - } Crlf - | PUBLIC { iVarScope = VS_PUBLIC; } ExtVarList Crlf - | PRIVATE { iVarScope = VS_PRIVATE; } ExtVarList Crlf + hb_comp_functions.pLast->bFlags |= FUN_WITH_RETURN; + hb_comp_bDontGenLineNum = TRUE; + } + | PUBLIC { hb_comp_iVarScope = VS_PUBLIC; } VarList CrlfStmnt + | PRIVATE { hb_comp_iVarScope = VS_PRIVATE; } VarList CrlfStmnt - | EXITLOOP Crlf { LoopExit(); } - | LOOP Crlf { LoopLoop(); } - | DoProc Crlf - | EXTERN ExtList Crlf + | EXITLOOP CrlfStmnt { LoopExit(); } + | LOOP CrlfStmnt { LoopLoop(); } + | DoProc CrlfStmnt + | EXTERN { hb_comp_bExternal = TRUE; } ExtList CrlfStmnt ; +CrlfStmnt : { LineBody(); } Crlf +; + LineStat : Crlf { $$ = 0; } | Statement { $$ = 1; } ; @@ -706,319 +332,395 @@ Statements : LineStat { $$ = $1; } | Statements { Line(); } LineStat { $$ += $3; } ; -ExtList : IDENTIFIER { AddExtern( $1 ); } - | ExtList ',' IDENTIFIER { AddExtern( $3 ); } +ExtList : IDENTIFIER { hb_compAddExtern( $1 ); } + | ExtList ',' IDENTIFIER { hb_compAddExtern( $3 ); } ; -FunCall : FunStart ')' { $$=0; CheckArgs( $1, $$ ); } - | FunStart ArgList ')' { $$=$2; CheckArgs( $1, $$ ); } +/* Numeric values + */ +NumValue : NUM_DOUBLE { $$ = hb_compExprNewDouble( $1.dNumber, $1.bDec ); } + | NUM_INTEGER { $$ = hb_compExprNewLong( $1.iNumber ); } + | NUM_LONG { $$ = hb_compExprNewLong( $1.lNumber ); } ; -FunStart : IDENTIFIER '(' { StaticAssign(); PushFunCall( $1 ); $$ = $1; } +NumAlias : NUM_INTEGER ALIASOP { $$ = hb_compExprNewLong( $1.iNumber ); } + | NUM_LONG ALIASOP { $$ = hb_compExprNewLong( $1.lNumber ); } + | NUM_DOUBLE ALIASOP { $$ = hb_compErrorAlias( hb_compExprNewDouble( $1.dNumber, $1.bDec ) ); } ; -MethCall : MethStart ')' { $$ = 0; } - | MethStart ArgList ')' { $$ = $2; } +/* NIL value + */ +NilValue : NIL { $$ = hb_compExprNewNil(); } +; + +NilAlias : NilValue ALIASOP { $$ = $1; } +; + +/* Literal string value + */ +LiteralValue : LITERAL { $$ = hb_compExprNewString( $1 ); } +; + +LiteralAlias : LiteralValue ALIASOP { $$ = $1; } +; + +/* Codeblock value + */ +CodeBlockAlias : CodeBlock ALIASOP { $$ = $1; } +; + +/* Logical value + */ +Logical : TRUEVALUE { $$ = hb_compExprNewLogical( TRUE ); } + | FALSEVALUE { $$ = hb_compExprNewLogical( FALSE ); } ; -MethStart : IDENTIFIER '(' { StaticAssign(); Message( $1 ); $$ = $1; } +LogicalAlias : Logical ALIASOP { $$ = $1; } +; + +/* SELF value and expressions + */ +SelfValue : SELF { $$ = hb_compExprNewSelf(); } +; + +SelfAlias : SelfValue ALIASOP { $$ = $1; } +; + +/* Literal array + */ +Array : '{' ElemList '}' { $$ = hb_compExprNewArray( $2 ); } ; -ArgList : ',' { PushNil(); PushNil(); $$ = 2; } - | Argument { $$ = 1; } - | ArgList ',' { PushNil(); $$++; } - | ArgList ',' Argument { $$++; } - | ',' { PushNil(); } Argument { $$ = 2; } - ; +ArrayAlias : Array ALIASOP { $$ = $1; } +; -Argument : Expression {} - | '@' IDENTIFIER { PushIdByRef( $2 ); } - | '@' IDENTIFIER '(' ')' { PushSymbol( $2, 1 ); GenPCode1( HB_P_FUNCPTR ); } - ; +/* Literal array access + */ +ArrayAt : Array ArrayIndex { $$ = $2; } +; -MethParams : /* empty */ { $$ = 0; } - | ArgList { $$ = $1; } - ; +ArrayAtAlias : ArrayAt ALIASOP { $$ = $1; } +; -ObjectData : IdSend IDENTIFIER { $$ = $2; _ulMessageFix = functions.pLast->lPCodePos; Message( $2 ); Function( 0 ); } - | VarAtSend IDENTIFIER { $$ = $2; _ulMessageFix = functions.pLast->lPCodePos; Message( $2 ); Function( 0 ); } - | ObjFunCall IDENTIFIER { $$ = $2; _ulMessageFix = functions.pLast->lPCodePos; Message( $2 ); Function( 0 ); } - | ObjFunArray ':' IDENTIFIER { $$ = $3; _ulMessageFix = functions.pLast->lPCodePos; Message( $3 ); Function( 0 ); } - | ObjectMethod ':' IDENTIFIER { $$ = $3; _ulMessageFix = functions.pLast->lPCodePos; Message( $3 ); Function( 0 ); } - | ObjectData ':' IDENTIFIER { $$ = $3; _ulMessageFix = functions.pLast->lPCodePos; Message( $3 ); Function( 0 ); } - | ObjectArr IDENTIFIER { $$ = $2; _ulMessageFix = functions.pLast->lPCodePos; Message( $2 ); Function( 0 ); } - ; +/* Variables + */ +Variable : IDENTIFIER { $$ = hb_compExprNewVar( $1 ); } +; -ObjectMethod : IdSend IDENTIFIER { Message( $2 ); } '(' MethParams ')' { Function( $5 ); } - | VarAtSend MethCall { Function( $2 ); } - | ObjFunCall MethCall { Function( $2 ); } - | ObjFunArray ':' MethCall { Function( $3 ); } - | ObjectData ':' MethCall { Function( $3 ); } - | ObjectArr MethCall { Function( $2 ); } - | ObjectMethod ':' MethCall { Function( $3 ); } - ; +VarAlias : IDENTIFIER ALIASOP { $$ = hb_compExprNewSymbol( $1 ); } +; -VarAtSend : VarAt ':' { ArrayAt(); } - | ArrayAt ':' { ArrayAt(); } - ; - -ObjectArr : ObjectData ArrayIndex ':' { ArrayAt(); } - ; - -IdSend : IDENTIFIER ':' { PushId( $1 ); $$ = $1; } - ; - -ObjFunCall : FunCall ':' { Function( $1 ); $$ = $1; } - ; - -FunCallArray : FunCall { Function( $1 ); } ArrayIndex - ; - -ObjFunArray : FunCallArray ':' { ArrayAt(); } +/* Macro variables + */ +MacroVar : '&' IDENTIFIER { hb_compExprNewMacro( hb_compExprNewVar( $2 ), NULL ); } + | '&' IDENTIFIER '.' { hb_compExprNewMacro( hb_compExprNewVar( $2 ), NULL ); } + | '&' IDENTIFIER '.' IDENTIFIER { hb_compExprNewMacro( hb_compExprNewVar( $2 ), $4 ); } + | '&' IDENTIFIER '.' NUM_INTEGER { hb_compExprNewMacro( hb_compExprNewVar( $2 ), $4.szValue ); } + | '&' IDENTIFIER '.' NUM_LONG { hb_compExprNewMacro( hb_compExprNewVar( $2 ), $4.szValue ); } ; -NumExpression : NUM_DOUBLE { PushDouble( $1.dNumber,$1.bDec ); } - | NUM_INTEGER { PushInteger( $1 ); ValTypePush( 'N' ); } - | NUM_LONG { PushLong( $1 ); } - ; +MacroVarAlias : MacroVar ALIASOP { $$ = $1; } +; -ConExpression : NIL { PushNil(); } - | LITERAL { PushString( $1 ); } - | CodeBlock {} - | Logical { PushLogical( $1 ); } - | SELF { GenPCode1( HB_P_PUSHSELF ); ValTypePush( 'O' ); } - ; +/* Macro expressions + */ +MacroExpr : '&' PareExpList { $$ = hb_compExprNewMacro( $2, NULL ); } +; -DynExpression : Variable - | VarUnary - | Operators {} - | FunCall { Function( $1 ); } - | IfInline {} - | Array {} - | ObjectMethod {} - | Macro {} - | AliasVar { PushId( $1 ); AliasRemove(); } - | AliasFunc {} - ; +MacroExprAlias : MacroExpr ALIASOP { $$ = $1; } +; + +/* Aliased variables + */ +/* special case: _FIELD-> and FIELD-> can be nested + */ +FieldAlias : FIELD ALIASOP { $$ = hb_compExprNewSymbol( "FIELD" ); } + | FIELD ALIASOP FieldAlias { $$ = $3; } + ; + +/* ignore _FIELD-> or FIELD-> if a real alias is specified + */ +FieldVarAlias : FieldAlias VarAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias NumAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias PareExpListAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias MacroVarAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias MacroExprAlias { hb_compExprDelete( $1 ); $$ = $2; } + | FieldAlias NilAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias LiteralAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias LogicalAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias CodeBlockAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias SelfAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias ArrayAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias ArrayAtAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + | FieldAlias IfInlineAlias { hb_compExprDelete( $1 ); $$ = hb_compErrorAlias( $2 ); } + ; + +AliasVar : NumAlias IDENTIFIER { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | MacroVarAlias IDENTIFIER { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | MacroExprAlias IDENTIFIER { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | PareExpListAlias IDENTIFIER { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | NilAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } + | LiteralAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } + | LogicalAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } + | CodeBlockAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } + | SelfAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } + | ArrayAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } + | ArrayAtAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | VariableAtAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | IfInlineAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | FunCallAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | ObjectDataAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | ObjectMethodAlias IDENTIFIER { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | VarAlias IDENTIFIER { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | FieldAlias IDENTIFIER { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | FieldVarAlias IDENTIFIER { $$ = hb_compExprNewAliasVar( $1, $2 ); } + ; + +/* Aliased expressions + */ +/* NOTE: In the case: + * alias->( Expression ) + * alias always selects a workarea at runtime + */ +AliasExpr : NumAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, hb_compExprReduce( $2 ) ); } + | VarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, hb_compExprReduce( $2 ) ); } + | MacroVarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, hb_compExprReduce( $2 ) ); } + | MacroExprAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, hb_compExprReduce( $2 ) ); } + | PareExpListAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, hb_compExprReduce( $2 ) ); } + | FieldAlias PareExpList { $$ = hb_compErrorAlias( $2 ); } /* QUESTION: Clipper reports error here - we can handle it */ + ; + +/* Array expressions access + */ +VariableAt : NilValue ArrayIndex { $$ = $2; } + | LiteralValue ArrayIndex { $$ = $2; } + | CodeBlock ArrayIndex { $$ = $2; } + | Logical ArrayIndex { $$ = $2; } + | SelfValue ArrayIndex { $$ = $2; } + | Variable ArrayIndex { $$ = $2; } + | AliasVar ArrayIndex { $$ = $2; } + | AliasExpr ArrayIndex { $$ = $2; } + | MacroVar ArrayIndex { $$ = $2; } + | MacroExpr ArrayIndex { $$ = $2; } + | ObjectData ArrayIndex { $$ = $2; } + | ObjectMethod ArrayIndex { $$ = $2; } + | FunCall ArrayIndex { $$ = $2; } + | IfInline ArrayIndex { $$ = $2; } + | PareExpList ArrayIndex { $$ = $2; } + ; + +VariableAtAlias : VariableAt ALIASOP { $$ = $1; } +; + +/* Function call + */ +FunCall : IDENTIFIER '(' ArgList ')' { $$ = hb_compExprNewFunCall( $1, $3 ); } +; + +ArgList : Argument { $$ = hb_compExprNewArgList( $1 ); } + | ArgList ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } + ; + +Argument : EmptyExpression { $$ = $1; } + | '@' IDENTIFIER { $$ = hb_compExprNewVarRef( $2 ); } + | '@' IDENTIFIER '(' ')' { $$ = hb_compExprNewFunRef( $2 ); } + ; + +FunCallAlias : FunCall ALIASOP { $$ = $1; } +; + +/* Object's instance variable + */ +ObjectData : NumValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | NilValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | LiteralValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | CodeBlock ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | Logical ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | SelfValue ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | Array ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | ArrayAt ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | Variable ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | AliasVar ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | AliasExpr ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | MacroVar ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | MacroExpr ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | FunCall ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | IfInline ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | PareExpList ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | VariableAt ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | ObjectMethod ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + | ObjectData ':' IDENTIFIER { $$ = hb_compExprNewSend( $1, $3 ); } + ; + +ObjectDataAlias : ObjectData ALIASOP { $$ = $1; } +; + +/* Object's method + */ +ObjectMethod : ObjectData '(' ArgList ')' { $$ = hb_compExprNewMethodCall( $1, $3 ); } + ; + +ObjectMethodAlias : ObjectMethod ALIASOP { $$ = $1; } +; /* NOTE: We have to distinguish IDENTIFIER here because it is repeated * in DoExpression (a part of DO WITH .. statement) * where it generates different action. */ -SimpleExpression : IDENTIFIER { PushId( $1 ); } - | NumExpression - | ConExpression - | DynExpression - ; +SimpleExpression : + NumValue + | NilValue { $$ = $1; } + | LiteralValue { $$ = $1; } + | CodeBlock { $$ = $1; } + | Logical { $$ = $1; } + | SelfValue { $$ = $1; } + | Array { $$ = $1; } + | ArrayAt { $$ = $1; } + | AliasVar { $$ = $1; } + | MacroVar { $$ = $1; } + | MacroExpr { $$ = $1; } + | VariableAt { $$ = $1; } + | FunCall { $$ = $1; } + | IfInline { $$ = $1; } + | ObjectData { $$ = $1; } + | ObjectMethod { $$ = $1; } + | AliasExpr { $$ = $1; } + | ExprAssign { $$ = $1; } + | ExprOperEq { $$ = $1; } + | ExprEqual { $$ = $1; } + | ExprPostOp { $$ = $1; } + | ExprPreOp { $$ = $1; } + | ExprMath { $$ = $1; } + | ExprBool { $$ = $1; } + | ExprRelation { $$ = $1; } +; -Expression : SimpleExpression {} - | PareExpList {} - ; +Expression : Variable { $$ = $1; } + | SimpleExpression { $$ = $1; } + | PareExpList { $$ = $1; } +; -EmptyExpression: /* nothing => nil */ +EmptyExpression: /* nothing => nil */ { $$ = hb_compExprNewEmpty(); } | Expression - ; +; -IfInline : IIF PareExpList3 { GenIfInline(); } - | IF PareExpList3 { GenIfInline(); } - ; +LValue : IDENTIFIER { $$ = hb_compExprNewVar( $1 ); } + | AliasVar + | MacroVar + | MacroExpr + | ObjectData + | VariableAt + ; -AliasVar : NUM_INTEGER ALIASOP { AliasAddInt( $1 ); } IDENTIFIER { $$ = $4; } - | IDENTIFIER ALIASOP { AliasAddStr( $1 ); } IDENTIFIER { $$ = $4; } - | PareExpList ALIASOP { AliasAddExp(); } IDENTIFIER { $$ = $4; } - ; - -/* NOTE: In the case: - * alias->( Expression ) - * alias always selects a workarea even if it is MEMVAR or M +/* NOTE: PostOp can be used in one context only - it uses $0 rule + * (the rule that stands before PostOp) */ -AliasFunc : NUM_INTEGER ALIASOP { AliasPush(); PushInteger( $1 ); AliasPop(); } PareExpList { AliasSwap(); } - | IDENTIFIER ALIASOP { AliasPush(); PushSymbol( $1, 0 ); AliasPop(); } PareExpList { AliasSwap(); } - | PareExpList ALIASOP { AliasPush(); AliasSwap(); } PareExpList { AliasSwap(); } +PostOp : INC { $$ = hb_compExprNewPostInc( $0 ); } + | DEC { $$ = hb_compExprNewPostDec( $0 ); } + ; + +/* NOTE: We cannot use 'Expression PostOp' because it caused + * shift/reduce conflicts + */ +ExprPostOp : NumValue PostOp %prec POST { $$ = $2; } + | NilValue PostOp %prec POST { $$ = $2; } + | LiteralValue PostOp %prec POST { $$ = $2; } + | CodeBlock PostOp %prec POST { $$ = $2; } + | Logical PostOp %prec POST { $$ = $2; } + | SelfValue PostOp %prec POST { $$ = $2; } + | Array PostOp %prec POST { $$ = $2; } + | ArrayAt PostOp %prec POST { $$ = $2; } + | Variable PostOp %prec POST { $$ = $2; } + | MacroVar PostOp %prec POST { $$ = $2; } + | MacroExpr PostOp %prec POST { $$ = $2; } + | AliasVar PostOp %prec POST { $$ = $2; } + | AliasExpr PostOp %prec POST { $$ = $2; } + | VariableAt PostOp %prec POST { $$ = $2; } + | PareExpList PostOp %prec POST { $$ = $2; } + | IfInline PostOp %prec POST { $$ = $2; } + | FunCall PostOp %prec POST { $$ = $2; } + | ObjectData PostOp %prec POST { $$ = $2; } + | ObjectMethod PostOp %prec POST { $$ = $2; } + ; + +ExprPreOp : INC Expression %prec PRE { $$ = hb_compExprNewPreInc( $2 ); } + | DEC Expression %prec PRE { $$ = hb_compExprNewPreDec( $2 ); } + | NOT Expression %prec UNARY { $$ = hb_compExprNewNot( $2 ); } + | '-' Expression %prec UNARY { $$ = hb_compExprNewNegate( $2 ); } + | '+' Expression %prec UNARY { $$ = $2; } + ; + +ExprAssign : Expression INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } +; + +ExprOperEq : Expression PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3 ); } + | Expression MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3 ); } + | Expression MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3 ); } + | Expression DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3 ); } + | Expression MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3 ); } + | Expression EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3 ); } + ; + +ExprEqual : Expression '=' Expression { $$ = hb_compExprSetOperand( hb_compExprNewEqual( $1 ), $3 ); } + ; + +ExprMath : Expression '+' Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlus( $1 ), $3 ); } + | Expression '-' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinus( $1 ), $3 ); } + | Expression '*' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMult( $1 ), $3 ); } + | Expression '/' Expression { $$ = hb_compExprSetOperand( hb_compExprNewDiv( $1 ), $3 ); } + | Expression '%' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMod( $1 ), $3 ); } + | Expression POWER Expression { $$ = hb_compExprSetOperand( hb_compExprNewPower( $1 ), $3 ); } + ; + +ExprBool : Expression AND Expression { $$ = hb_compExprSetOperand( hb_compExprNewAnd( $1 ), $3 ); } + | Expression OR Expression { $$ = hb_compExprSetOperand( hb_compExprNewOr( $1 ), $3 ); } + ; + +ExprRelation: Expression EQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewEQ( $1 ), $3 ); } + | Expression '<' Expression { $$ = hb_compExprSetOperand( hb_compExprNewLT( $1 ), $3 ); } + | Expression '>' Expression { $$ = hb_compExprSetOperand( hb_compExprNewGT( $1 ), $3 ); } + | Expression LE Expression { $$ = hb_compExprSetOperand( hb_compExprNewLE( $1 ), $3 ); } + | Expression GE Expression { $$ = hb_compExprSetOperand( hb_compExprNewGE( $1 ), $3 ); } + | Expression NE1 Expression { $$ = hb_compExprSetOperand( hb_compExprNewNE( $1 ), $3 ); } + | Expression NE2 Expression { $$ = hb_compExprSetOperand( hb_compExprNewNE( $1 ), $3 ); } + | Expression '$' Expression { $$ = hb_compExprSetOperand( hb_compExprNewIN( $1 ), $3 ); } + ; + +ArrayIndex : IndexList ']' { $$ = $1; } ; -VarUnary : IDENTIFIER IncDec %prec POST { PushId( $1 ); Duplicate(); $2 ? Inc(): Dec(); PopId( $1 ); } - | IncDec IDENTIFIER %prec PRE { PushId( $2 ); $1 ? Inc(): Dec(); Duplicate(); PopId( $2 ); } - | VarAt IncDec %prec POST { DupPCode( $1 ); ArrayAt(); $2 ? Inc(): Dec(); ArrayPut(); $2 ? Dec(): Inc(); } - | IncDec VarAt %prec PRE { DupPCode( $2 ); ArrayAt(); $1 ? Inc(): Dec(); ArrayPut(); } - | ArrayAt IncDec %prec POST { ArrayAt(); } - | IncDec ArrayAt %prec PRE { ArrayAt(); $1 ? Inc(): Dec(); } - | FunCallArray IncDec %prec POST { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); $2 ? Inc(): Dec(); ArrayPut(); $2 ? Dec(): Inc(); } - | IncDec FunCallArray %prec PRE { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); $1 ? Inc(): Dec(); ArrayPut(); } - | ObjectData IncDec %prec POST { MessageDupl( SetData( $1 ) ); Function( 0 ); $2 ? Inc(): Dec(); Function( 1 ); $2 ? Dec(): Inc(); } - | IncDec ObjectData %prec PRE { MessageDupl( SetData( $2 ) ); Function( 0 ); $1 ? Inc(): Dec(); Function( 1 ); } - | ObjectData ArrayIndex IncDec %prec POST { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); $3 ? Inc(): Dec(); ArrayPut(); $3 ? Dec(): Inc(); } - | IncDec ObjectData ArrayIndex %prec PRE { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); $1 ? Inc(): Dec(); ArrayPut(); } - | ObjectMethod ArrayIndex IncDec %prec POST { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); $3 ? Inc(): Dec(); ArrayPut(); $3 ? Dec(): Inc(); } - | IncDec ObjectMethod ArrayIndex %prec PRE { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); $1 ? Inc(): Dec(); ArrayPut(); } - | AliasVar IncDec %prec POST { PushId( $1 ); Duplicate(); $2 ? Inc(): Dec(); PopId( $1 ); AliasRemove(); } - | IncDec AliasVar %prec PRE { PushId( $2 ); $1 ? Inc(): Dec(); Duplicate(); PopId( $2 ); AliasRemove(); } +/* NOTE: $0 represents the expression before ArrayIndex + * Don't use ArrayIndex in other context than as an array index! + */ +IndexList : '[' Expression { $$ = hb_compExprNewArrayAt( $0, $2 ); } + | IndexList ',' Expression { $$ = hb_compExprNewArrayAt( $1, $3 ); } + | IndexList ']' '[' Expression { $$ = hb_compExprNewArrayAt( $1, $4 ); } ; -IncDec : INC { $$ = 1; } - | DEC { $$ = 0; } +ElemList : EmptyExpression { $$ = hb_compExprNewList( $1 ); } + | ElemList ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } ; -Variable : VarAt { ArrayAt(); } - | ArrayAt { ArrayAt(); } - | FunCallArray { ArrayAt(); } - | ObjectData {} - | ObjectData ArrayIndex { ArrayAt(); } - | ObjectMethod ArrayIndex { ArrayAt(); } +CodeBlock : '{' '|' { $$ = hb_compExprNewCodeBlock(); } BlockNoVar + '|' BlockExpList '}' { $$ = $3; } + | '{' '|' { $$ = hb_compExprNewCodeBlock(); } BlockVarList + '|' BlockExpList '}' { $$ = $3; } ; -VarAt : IDENTIFIER { $$ = functions.pLast->lPCodePos; PushId( $1 ); } ArrayIndex { $$ =$2; } +/* NOTE: This uses $-2 then don't use BlockExpList in other context + */ +BlockExpList : Expression { $$ = hb_compExprAddListExpr( $-2, $1 ); } + | BlockExpList ',' Expression { $$ = hb_compExprAddListExpr( $-2, $3 ); } ; -ArrayAt : Array ArrayIndex - ; +/* NOTE: This is really not needed however it allows the use of $-2 item + * in BlockExpList to refer the same rule defined in Codeblock + */ +BlockNoVar : /* empty list */ { $$ = NULL; } +; -ArrayIndex : '[' IndexList ']' - | ArrayIndex { ArrayAt(); } '[' IndexList ']' - ; - -IndexList : Expression - | IndexList { ArrayAt(); } ',' Expression - ; - -VarAssign : IDENTIFIER INASSIGN Expression { PopId( $1 ); SetLastPushPos(); PushId( $1 ); } - | VarAt INASSIGN Expression { ArrayPut(); } - | ArrayAt INASSIGN { GenPopPCode();GenPopPCode(); } Expression - | FunCallArray INASSIGN Expression { ArrayPut(); } - | ObjectData INASSIGN { MessageFix ( SetData( $1 ) ); } Expression { Function( 1 ); } - | ObjectData ArrayIndex INASSIGN Expression { ArrayPut(); } - | ObjectMethod ArrayIndex INASSIGN Expression { ArrayPut(); } - | AliasVar INASSIGN { $$=( void * ) pAliasId; pAliasId = NULL; } Expression { pAliasId=(ALIASID_PTR) $3; PopId( $1 ); SetLastPushPos(); PushId( $1 ); AliasRemove(); } - | AliasFunc INASSIGN Expression { --iLine; GenError( _szCErrors, 'E', ERR_INVALID_LVALUE, NULL, NULL ); } - ; - -VarOpEq : IDENTIFIER PLUSEQ { PushId( $1 ); } Expression { GenPlusPCode( HB_P_PLUS ); PopId( $1 ); SetLastPushPos(); PushId( $1 ); } - | IDENTIFIER MINUSEQ { PushId( $1 ); } Expression { GenPlusPCode( HB_P_MINUS ); PopId( $1 ); SetLastPushPos(); PushId( $1 ); } - | IDENTIFIER MULTEQ { PushId( $1 ); } Expression { GenNumPCode( HB_P_MULT ); PopId( $1 ); SetLastPushPos(); PushId( $1 ); } - | IDENTIFIER DIVEQ { PushId( $1 ); } Expression { GenNumPCode( HB_P_DIVIDE ); PopId( $1 ); SetLastPushPos(); PushId( $1 ); } - | IDENTIFIER EXPEQ { PushId( $1 ); } Expression { GenNumPCode( HB_P_POWER ); PopId( $1 ); SetLastPushPos(); PushId( $1 ); } - | IDENTIFIER MODEQ { PushId( $1 ); } Expression { GenNumPCode( HB_P_MODULUS ); PopId( $1 ); SetLastPushPos(); PushId( $1 ); } - | VarAt PLUSEQ { DupPCode( $1 ); ArrayAt(); } Expression { GenPlusPCode( HB_P_PLUS ); ArrayPut(); } - | VarAt MINUSEQ { DupPCode( $1 ); ArrayAt(); } Expression { GenPlusPCode( HB_P_MINUS ); ArrayPut(); } - | VarAt MULTEQ { DupPCode( $1 ); ArrayAt(); } Expression { GenNumPCode( HB_P_MULT ); ArrayPut(); } - | VarAt DIVEQ { DupPCode( $1 ); ArrayAt(); } Expression { GenNumPCode( HB_P_DIVIDE ); ArrayPut(); } - | VarAt EXPEQ { DupPCode( $1 ); ArrayAt(); } Expression { GenNumPCode( HB_P_POWER ); ArrayPut(); } - | VarAt MODEQ { DupPCode( $1 ); ArrayAt(); } Expression { GenNumPCode( HB_P_MODULUS ); ArrayPut(); } - | ArrayAt PLUSEQ { ArrayAt(); } Expression { GenPlusPCode( HB_P_PLUS ); } - | ArrayAt MINUSEQ { ArrayAt(); } Expression { GenPlusPCode( HB_P_MINUS ); } - | ArrayAt MULTEQ { ArrayAt(); } Expression { GenNumPCode( HB_P_MULT ); } - | ArrayAt DIVEQ { ArrayAt(); } Expression { GenNumPCode( HB_P_DIVIDE ); } - | ArrayAt EXPEQ { ArrayAt(); } Expression { GenNumPCode( HB_P_POWER ); } - | ArrayAt MODEQ { ArrayAt(); } Expression { GenNumPCode( HB_P_MODULUS ); } - | FunCallArray PLUSEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenPlusPCode( HB_P_PLUS ); ArrayPut(); } - | FunCallArray MINUSEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenPlusPCode( HB_P_MINUS ); ArrayPut(); } - | FunCallArray MULTEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_MULT ); ArrayPut(); } - | FunCallArray DIVEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_DIVIDE ); ArrayPut(); } - | FunCallArray EXPEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_POWER ); ArrayPut(); } - | FunCallArray MODEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_MODULUS ); ArrayPut(); } - | ObjectData PLUSEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenPlusPCode( HB_P_PLUS ); Function( 1 ); } - | ObjectData MINUSEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenPlusPCode( HB_P_MINUS ); Function( 1 ); } - | ObjectData MULTEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenNumPCode( HB_P_MULT ); Function( 1 ); } - | ObjectData DIVEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenNumPCode( HB_P_DIVIDE ); Function( 1 ); } - | ObjectData EXPEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenNumPCode( HB_P_POWER ); Function( 1 ); } - | ObjectData MODEQ { MessageDupl( SetData( $1 ) ); Function( 0 ); } Expression { GenNumPCode( HB_P_MODULUS ); Function( 1 ); } - | ObjectData ArrayIndex PLUSEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenPlusPCode( HB_P_PLUS ); ArrayPut(); } - | ObjectData ArrayIndex MINUSEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenPlusPCode( HB_P_MINUS ); ArrayPut(); } - | ObjectData ArrayIndex MULTEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_MULT ); ArrayPut(); } - | ObjectData ArrayIndex DIVEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_DIVIDE ); ArrayPut(); } - | ObjectData ArrayIndex EXPEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_POWER ); ArrayPut(); } - | ObjectData ArrayIndex MODEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_MODULUS ); ArrayPut(); } - | ObjectMethod ArrayIndex PLUSEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenPlusPCode( HB_P_PLUS ); ArrayPut(); } - | ObjectMethod ArrayIndex MINUSEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenPlusPCode( HB_P_MINUS ); ArrayPut(); } - | ObjectMethod ArrayIndex MULTEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_MULT ); ArrayPut(); } - | ObjectMethod ArrayIndex DIVEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_DIVIDE ); ArrayPut(); } - | ObjectMethod ArrayIndex EXPEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_POWER ); ArrayPut(); } - | ObjectMethod ArrayIndex MODEQ { GenPCode1( HB_P_DUPLTWO ); ArrayAt(); } Expression { GenNumPCode( HB_P_MODULUS ); ArrayPut(); } - | AliasVar PLUSEQ { PushId( $1 ); $$=(void*)pAliasId; pAliasId = NULL; } Expression { GenPlusPCode( HB_P_PLUS ); pAliasId=(ALIASID_PTR) $3; PopId( $1 ); SetLastPushPos(); PushId( $1 ); AliasRemove(); } - | AliasVar MINUSEQ { PushId( $1 ); $$=(void*)pAliasId; pAliasId = NULL; } Expression { GenPlusPCode( HB_P_MINUS ); pAliasId=(ALIASID_PTR) $3; PopId( $1 ); SetLastPushPos(); PushId( $1 ); AliasRemove(); } - | AliasVar MULTEQ { PushId( $1 ); $$=(void*)pAliasId; pAliasId = NULL; } Expression { GenNumPCode( HB_P_MULT ); pAliasId=(ALIASID_PTR) $3; PopId( $1 ); SetLastPushPos(); PushId( $1 ); AliasRemove(); } - | AliasVar DIVEQ { PushId( $1 ); $$=(void*)pAliasId; pAliasId = NULL; } Expression { GenNumPCode( HB_P_DIVIDE ); pAliasId=(ALIASID_PTR) $3; PopId( $1 ); SetLastPushPos(); PushId( $1 ); AliasRemove(); } - | AliasVar EXPEQ { PushId( $1 ); $$=(void*)pAliasId; pAliasId = NULL; } Expression { GenNumPCode( HB_P_POWER ); pAliasId=(ALIASID_PTR) $3; PopId( $1 ); SetLastPushPos(); PushId( $1 ); AliasRemove(); } - | AliasVar MODEQ { PushId( $1 ); $$=(void*)pAliasId; pAliasId = NULL; } Expression { GenNumPCode( HB_P_MODULUS ); pAliasId=(ALIASID_PTR) $3; PopId( $1 ); SetLastPushPos(); PushId( $1 ); AliasRemove(); } - | AliasFunc PLUSEQ Expression { --iLine; GenError( _szCErrors, 'E', ERR_INVALID_LVALUE, NULL, NULL ); } - | AliasFunc MINUSEQ Expression { --iLine; GenError( _szCErrors, 'E', ERR_INVALID_LVALUE, NULL, NULL ); } - | AliasFunc MULTEQ Expression { --iLine; GenError( _szCErrors, 'E', ERR_INVALID_LVALUE, NULL, NULL ); } - | AliasFunc DIVEQ Expression { --iLine; GenError( _szCErrors, 'E', ERR_INVALID_LVALUE, NULL, NULL ); } - | AliasFunc EXPEQ Expression { --iLine; GenError( _szCErrors, 'E', ERR_INVALID_LVALUE, NULL, NULL ); } - | AliasFunc MODEQ Expression { --iLine; GenError( _szCErrors, 'E', ERR_INVALID_LVALUE, NULL, NULL ); } - ; - -VarExpr : VarAssign - | VarOpEq - ; - -Operators : Expression '=' Expression { GenRelPCode( HB_P_EQUAL ); } /* compare */ - | Expression '+' Expression { GenPlusPCode( HB_P_PLUS ); } - | Expression '-' Expression { GenPlusPCode( HB_P_MINUS ); } - | Expression '*' Expression { GenNumPCode( HB_P_MULT ); } - | Expression '/' Expression { GenNumPCode( HB_P_DIVIDE ); } - | Expression '<' Expression { GenRelPCode( HB_P_LESS ); } - | Expression '>' Expression { GenRelPCode( HB_P_GREATER ); } - | Expression '$' Expression { GenRelPCode( HB_P_INSTRING ); } - | Expression '%' Expression { GenNumPCode( HB_P_MODULUS ); } - | Expression LE Expression { GenRelPCode( HB_P_LESSEQUAL ); } - | Expression GE Expression { GenRelPCode( HB_P_GREATEREQUAL ); } - | Expression AND { if( _bShortCuts ){ Duplicate(); $$ = JumpFalse( 0 ); } } - Expression { GenPCode1( HB_P_AND ); if( _bShortCuts ) JumpHere( $3 ); } - | Expression OR { if( _bShortCuts ){ Duplicate(); $$ = JumpTrue( 0 ); } } - Expression { GenPCode1( HB_P_OR ); if( _bShortCuts ) JumpHere( $3 ); } - | Expression EQ Expression { GenRelPCode( HB_P_EXACTLYEQUAL ); } - | Expression NE1 Expression { GenRelPCode( HB_P_NOTEQUAL ); } - | Expression NE2 Expression { GenRelPCode( HB_P_NOTEQUAL ); } - | Expression POWER Expression { GenNumPCode( HB_P_POWER ); } - | NOT Expression { GenNotPCode( ); } - | '-' Expression %prec UNARY { GenNegatePCode( ); } - | '+' Expression %prec UNARY - | VarExpr { } - ; - -Logical : TRUEVALUE { $$ = 1; } - | FALSEVALUE { $$ = 0; } - ; - -Array : '{' ElemList '}' { GenArray( $2 ); } - ; - -ElemList : /*empty array*/ { $$ = 0; } - | Expression { $$ = 1; } - | ElemList ',' { if( $$ == 0 ) { - PushNil(); - PushNil(); - $$ = 2; - } else { - PushNil(); - $$++; - } } - | ElemList ',' Expression { if( $$ == 0 ) - { - PushNil(); - $$ = 2; - } - else - $$++; } - ; - -CodeBlock : BlockBegin '|' BlockExpList '}' { CodeBlockEnd(); } - | BlockBegin { $$=iVarScope; iVarScope=VS_LOCAL; } BlockList '|' - BlockExpList '}' { CodeBlockEnd(); iVarScope=$2; } - ; - -BlockBegin : '{' '|' { CodeBlockStart(); } - ; - -BlockExpList : Expression { $$ = 1; } - | ',' { SetLastPushPos(); PushNil(); RemoveExtraPush(); PushNil(); $$ = 2; } - | BlockExpList ',' { RemoveExtraPush(); PushNil(); $$++; } - | BlockExpList ',' { RemoveExtraPush(); } Expression { $$++; } - ; - -BlockList : IDENTIFIER AsType { AddVar( $1 ); $$ = 1; } - | BlockList ',' IDENTIFIER AsType { AddVar( $3 ); $$++; } +BlockVarList : IDENTIFIER AsType { hb_comp_iVarScope = VS_LOCAL; $$ = hb_compExprCBVarAdd( $0, $1, $2 ); } + | BlockVarList ',' IDENTIFIER AsType { hb_comp_iVarScope = VS_LOCAL; $$ = hb_compExprCBVarAdd( $0, $3, $4 ); } ; /* There is a conflict between the use of IF( Expr1, Expr2, Expr3 ) @@ -1028,152 +730,186 @@ BlockList : IDENTIFIER AsType { AddVar( $1 ); $$ = 1; } * Also the generation of pcodes have to be delayed and moved to the * end of whole parenthesized expression. */ -PareExpList1: ExpList1 ')' { ExpListPop( 1 ); } +PareExpList1: ExpList1 ')' { $$ = $1; } ; -PareExpList2: ExpList2 ')' { ExpListPop( 2 ); } +PareExpList2: ExpList2 ')' { $$ = $1; } ; -PareExpList3: ExpList3 ')' { /* this needs the special handling if used in inline IF */ } +PareExpList3: ExpList3 ')' { $$ = $1; } ; -PareExpListN: ExpList ')' { ExpListPop( $1 ); } +PareExpListN: ExpList ')' { $$ = $1; } ; -PareExpList : PareExpList1 { } - | PareExpList2 { } - | PareExpList3 { ExpListPop( 3 ); } - | PareExpListN { } +PareExpList : PareExpList1 { $$ = $1; } + | PareExpList2 { $$ = $1; } + | PareExpList3 { $$ = $1; } + | PareExpListN { $$ = $1; } ; -ExpList1 : '(' { ExpListPush(); } EmptyExpression +PareExpListAlias : PareExpList ALIASOP { $$ = hb_compExprReduce( $1 ); } +; + +ExpList1 : '(' EmptyExpression { $$ = hb_compExprNewList( $2 ); } +; + +ExpList2 : ExpList1 ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } +; + +ExpList3 : ExpList2 ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } +; + +ExpList : ExpList3 ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } + | ExpList ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } ; -ExpList2 : ExpList1 ',' { ExpListPush(); } EmptyExpression +IfInline : IIF PareExpList3 { $$ = hb_compExprNewIIF( $2 ); } + | IF ExpList1 ',' EmptyExpression ',' + { $$ = hb_compExprAddListExpr( $2, $4 ); } + EmptyExpression ')' + { $$ = hb_compExprNewIIF( hb_compExprAddListExpr( $6, $7 ) ); } ; -ExpList3 : ExpList2 ',' { ExpListPush(); } EmptyExpression - ; +IfInlineAlias : IfInline ALIASOP { $$ = $1; } +; -ExpList : ExpList3 { ExpListPush(); } ',' EmptyExpression { $$ = 4; } - | ExpList { ExpListPush(); } ',' EmptyExpression { $$++; } - ; - -VarDefs : LOCAL { iVarScope = VS_LOCAL; Line(); } VarList Crlf { _cVarType = ' '; } - | STATIC { StaticDefStart() } VarList Crlf { StaticDefEnd( $3 ); } - | PARAMETERS { if( functions.pLast->bFlags & FUN_USES_LOCAL_PARAMS ) - GenError( _szCErrors, 'E', ERR_PARAMETERS_NOT_ALLOWED, NULL, NULL ); +VarDefs : LOCAL { hb_comp_iVarScope = VS_LOCAL; Line(); } VarList Crlf { hb_comp_cVarType = ' '; } + | STATIC { hb_comp_iVarScope = VS_STATIC; Line(); } VarList Crlf { hb_comp_cVarType = ' '; } + | PARAMETERS { if( hb_comp_functions.pLast->bFlags & FUN_USES_LOCAL_PARAMS ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_PARAMETERS_NOT_ALLOWED, NULL, NULL ); else - functions.pLast->wParamNum=0; iVarScope = ( VS_PRIVATE | VS_PARAMETER ); } + hb_comp_functions.pLast->wParamNum=0; hb_comp_iVarScope = ( VS_PRIVATE | VS_PARAMETER ); } MemvarList Crlf ; - -ExtVarList : VarDef { $$ = 1; } - | ExtVarList ',' VarDef { $$++; } - | SetVarMacro { Do( 1 ); } - | ExtVarList ',' SetVarMacro { Do( 1 ); } - | SetVarMacro MacroAssign { FunMacroAssign(); } Expression { Do( 2 ); } - | ExtVarList ',' SetVarMacro MacroAssign { FunMacroAssign(); } Expression { Do( 2 ); } - ; - -SetVarMacro : { SetVarMacro(); } VarMacro - ; - -VarMacro : MACROOP IDENTIFIER { PushId( $2 ); } - | MACROALIAS IDENTIFIER { PushId( $2 ); } - | Macro - | VarMacro DOT IDENTIFIER { PushString( $3 ); GenPlusPCode( HB_P_PLUS ); } - | VarMacro NUM_DOUBLE { PushString( yy_strdup( yytext + 1 ) ); GenPlusPCode( HB_P_PLUS ); } - ; - -MacroAssign : INASSIGN - | '=' - ; - -Macro : MACROOP Variable - | MACROOP '(' Expression ')' - | MACROALIAS Variable - | MACROALIAS '(' Expression ')' - ; - - -VarList : VarDef { $$ = 1; } - | VarList ',' VarDef { $$++; } - ; - -VarDef : IDENTIFIER AsType { AddVar( $1 ); } - | IDENTIFIER AsType INASSIGN { AddVar( $1 ); } Expression { PopId( $1 ); } - | IDENTIFIER ArrExpList ']' { _cVarType = 'A'; AddVar( $1 ); ArrayDim( $2 ); PopId( $1 ); } - | IDENTIFIER ArrExpList ']' AS_ARRAY { _cVarType = 'A'; AddVar( $1 ); ArrayDim( $2 ); PopId( $1 ); } - ; - -ArrExpList : '[' Expression { $$ = 1; } - | ArrExpList ',' Expression { $$++; } - | ArrExpList ']' '[' Expression { $$++; } - ; - -FieldsDef : FIELD { iVarScope = VS_FIELD; } FieldList Crlf - ; - -FieldList : IDENTIFIER AsType { $$=FieldsCount(); AddVar( $1 ); } - | FieldList ',' IDENTIFIER AsType { AddVar( $3 ); } - | FieldList IN IDENTIFIER { FieldsSetAlias( $3, $1 ); } - ; - -MemvarDef : MEMVAR { iVarScope = VS_MEMVAR; } MemvarList Crlf - ; - -MemvarList : IDENTIFIER { AddVar( $1 ); } - | MemvarList ',' IDENTIFIER { AddVar( $3 ); } - ; - -ExecFlow : IfEndif - | DoCase - | DoWhile - | ForNext - | BeginSeq - ; - -IfEndif : IfBegin EndIf { JumpHere( $1 ); } - | IfBegin IfElse EndIf { JumpHere( $1 ); } - | IfBegin IfElseIf EndIf { JumpHere( $1 ); FixElseIfs( $2 ); } - | IfBegin IfElseIf IfElse EndIf { JumpHere( $1 ); FixElseIfs( $2 ); } - ; - -EmptyStats : /* empty */ - | Statements - ; - -IfBegin : IF SimpleExpression { ++_wIfCounter; } Crlf { $$ = JumpFalse( 0 ); Line(); } - EmptyStats - { $$ = Jump( 0 ); JumpHere( $5 ); } - - | IF PareExpList1 { ++_wIfCounter; } Crlf { $$ = JumpFalse( 0 ); Line(); } - EmptyStats - { $$ = Jump( 0 ); JumpHere( $5 ); } - - | IF PareExpList2 { ++_wIfCounter; } Crlf { $$ = JumpFalse( 0 ); Line(); } - EmptyStats - { $$ = Jump( 0 ); JumpHere( $5 ); } - - | IF PareExpListN { ++_wIfCounter; } Crlf { $$ = JumpFalse( 0 ); Line(); } - EmptyStats - { $$ = Jump( 0 ); JumpHere( $5 ); } - ; - -IfElse : ELSE Crlf { Line(); } EmptyStats - ; - -IfElseIf : ELSEIF Expression Crlf { $$ = JumpFalse( 0 ); Line(); } - EmptyStats { $$ = GenElseIf( 0, Jump( 0 ) ); JumpHere( $4 ); } - - | IfElseIf ELSEIF Expression Crlf { $$ = JumpFalse( 0 ); Line(); } - EmptyStats { $$ = GenElseIf( $1, Jump( 0 ) ); JumpHere( $5 ); } +VarList : VarDef { $$ = 1; } + | VarList ',' VarDef { $$++; } ; -EndIf : ENDIF { --_wIfCounter; functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } - | END { --_wIfCounter; functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } +VarDef : IDENTIFIER AsType + { + if( hb_comp_iVarScope == VS_STATIC ) + { + hb_compStaticDefStart(); /* switch to statics pcode buffer */ + hb_compAddVar( $1, $2 ); + hb_compStaticDefEnd(); + } + else + hb_compAddVar( $1, $2 ); + } + + | IDENTIFIER AsType INASSIGN Expression + { + if( hb_comp_iVarScope == VS_STATIC ) + { + hb_compStaticDefStart(); /* switch to statics pcode buffer */ + hb_compAddVar( $1, $2 ); + hb_compExprDelete( hb_compExprGenStatement( hb_compExprAssignStatic( hb_compExprNewVar( $1 ), $4 ) ) ); + hb_compStaticDefEnd(); + } + else + { + hb_compAddVar( $1, $2 ); + hb_compExprDelete( hb_compExprGenStatement( hb_compExprAssign( hb_compExprNewVar( $1 ), $4 ) ) ); + } + } + + | IDENTIFIER DimList + { + USHORT uCount = hb_compExprListLen( $2 ); + hb_compAddVar( $1, 'A' ); + hb_compExprDelete( hb_compExprGenPush( $2 ) ); + hb_compGenPCode3( HB_P_ARRAYDIM, HB_LOBYTE( uCount ), HB_HIBYTE( uCount ) ); + hb_compExprDelete( hb_compExprGenPop( hb_compExprNewVar( $1 ) ) ); + } + | IDENTIFIER DimList AS_ARRAY + { + USHORT uCount = hb_compExprListLen( $2 ); + hb_compAddVar( $1, 'A' ); + hb_compExprDelete( hb_compExprGenPush( $2 ) ); + hb_compGenPCode3( HB_P_ARRAYDIM, HB_LOBYTE( uCount ), HB_HIBYTE( uCount ) ); + hb_compExprDelete( hb_compExprGenPop( hb_compExprNewVar( $1 ) ) ); + } + ; + +/* NOTE: DimList and DimIndex is the same as ArrayIndex and IndexList + * however we are using quite different actions here + */ +DimList : DimIndex ']' { $$ = $1; } + ; + +DimIndex : '[' Expression { $$ = hb_compExprNewArgList( $2 ); } + | DimIndex ',' Expression { $$ = hb_compExprAddListExpr( $1, $3 ); } + | DimIndex ']' '[' Expression { $$ = hb_compExprAddListExpr( $1, $4 ); } + ; + + +FieldsDef : FIELD { hb_comp_iVarScope = VS_FIELD; } FieldList Crlf + ; + +FieldList : IDENTIFIER AsType { $$=FieldsCount(); hb_compAddVar( $1, $2 ); } + | FieldList ',' IDENTIFIER AsType { hb_compAddVar( $3, $4 ); } + | FieldList IN IDENTIFIER { FieldsSetAlias( $3, $1 ); } + ; + +MemvarDef : MEMVAR { hb_comp_iVarScope = VS_MEMVAR; } MemvarList Crlf + ; + +MemvarList : IDENTIFIER { hb_compAddVar( $1, ' ' ); } + | MemvarList ',' IDENTIFIER { hb_compAddVar( $3, ' ' ); } + ; + +ExecFlow : IfEndif + | DoCase + | DoWhile + | ForNext + | BeginSeq + ; + +IfEndif : IfBegin EndIf { hb_compGenJumpHere( $1 ); } + | IfBegin IfElse EndIf { hb_compGenJumpHere( $1 ); } + | IfBegin IfElseIf EndIf { hb_compGenJumpHere( $1 ); FixElseIfs( $2 ); } + | IfBegin IfElseIf IfElse EndIf { hb_compGenJumpHere( $1 ); FixElseIfs( $2 ); } + ; + +EmptyStats : /* empty */ + | Statements + ; + +IfBegin : IF SimpleExpression { ++hb_comp_wIfCounter; Line(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); Line(); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + + | IF Variable { ++hb_comp_wIfCounter; Line(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); Line(); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + + | IF PareExpList1 { ++hb_comp_wIfCounter; Line(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); Line(); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + + | IF PareExpList2 { ++hb_comp_wIfCounter; Line(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); Line(); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + + | IF PareExpListN { ++hb_comp_wIfCounter; Line(); } Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); Line(); } + EmptyStats + { $$ = hb_compGenJump( 0 ); hb_compGenJumpHere( $5 ); } + ; + +IfElse : ELSE Crlf { Line(); } EmptyStats + ; + +IfElseIf : ELSEIF Expression Crlf { hb_compExprDelete( hb_compExprGenPush( $2 ) ); $$ = hb_compGenJumpFalse( 0 ); Line(); } + EmptyStats { $$ = GenElseIf( 0, hb_compGenJump( 0 ) ); hb_compGenJumpHere( $4 ); } + + | IfElseIf ELSEIF Expression Crlf { hb_compExprDelete( hb_compExprGenPush( $3 ) ); $$ = hb_compGenJumpFalse( 0 ); Line(); } + EmptyStats { $$ = GenElseIf( $1, hb_compGenJump( 0 ) ); hb_compGenJumpHere( $5 ); } + ; + +EndIf : ENDIF { --hb_comp_wIfCounter; hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } + | END { --hb_comp_wIfCounter; hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } ; DoCase : DoCaseBegin @@ -1193,11 +929,11 @@ DoCase : DoCaseBegin EndCase { FixElseIfs( $2 ); } ; -EndCase : ENDCASE { --_wCaseCounter; functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } - | END { --_wCaseCounter; functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } +EndCase : ENDCASE { --hb_comp_wCaseCounter; hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } + | END { --hb_comp_wCaseCounter; hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } ; -DoCaseStart : DOCASE { ++_wCaseCounter; } Crlf { Line(); } +DoCaseStart : DOCASE { ++hb_comp_wCaseCounter; } Crlf { Line(); } ; DoCaseBegin : DoCaseStart { } @@ -1205,112 +941,125 @@ DoCaseBegin : DoCaseStart { } if( $2 > 0 ) { --iLine; - GenError( _szCErrors, 'E', ERR_MAYHEM_IN_CASE, NULL, NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_MAYHEM_IN_CASE, NULL, NULL ); } } ; -Cases : CASE Expression Crlf { - $$ = JumpFalse( 0 ); - Line(); - } - EmptyStats { - $$ = GenElseIf( 0, Jump( 0 ) ); - JumpHere( $4 ); - Line(); - } +Cases : CASE Expression Crlf + { + hb_compExprDelete( hb_compExprGenPush( $2 ) ); + $$ = hb_compGenJumpFalse( 0 ); + Line(); + } + EmptyStats + { + $$ = GenElseIf( 0, hb_compGenJump( 0 ) ); + hb_compGenJumpHere( $4 ); + Line(); + } - | Cases CASE Expression Crlf { - $$ = JumpFalse( 0 ); - Line(); - } - EmptyStats { - $$ = GenElseIf( $1, Jump( 0 ) ); - JumpHere( $5 ); - Line(); - } + | Cases CASE Expression Crlf + { + hb_compExprDelete( hb_compExprGenPush( $3 ) ); + $$ = hb_compGenJumpFalse( 0 ); + Line(); + } + EmptyStats + { + $$ = GenElseIf( $1, hb_compGenJump( 0 ) ); + hb_compGenJumpHere( $5 ); + Line(); + } ; Otherwise : OTHERWISE Crlf { Line(); } EmptyStats ; -/* -DoWhile : WhileBegin Expression Crlf { $$ = JumpFalse( 0 ); Line(); } - { Jump( $1 - functions.pLast->lPCodePos ); } - EndWhile { JumpHere( $4 ); --_wWhileCounter; functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } - - | WhileBegin Expression Crlf { $$ = JumpFalse( 0 ); Line(); } - Statements { LoopHere(); Jump( $1 - functions.pLast->lPCodePos ); } - EndWhile { JumpHere( $4 ); --_wWhileCounter; LoopEnd(); functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } - ; -*/ -DoWhile : WhileBegin Expression Crlf { - $$ = JumpFalse( 0 ); - Line(); - } - EmptyStats { - LoopHere(); - Jump( $1 - functions.pLast->lPCodePos ); - } - EndWhile { - JumpHere( $4 ); --_wWhileCounter; +DoWhile : WhileBegin Expression Crlf + { + hb_compExprDelete( hb_compExprGenPush( $2 ) ); + $$ = hb_compGenJumpFalse( 0 ); + Line(); + } + EmptyStats + { + LoopHere(); + hb_compGenJump( $1 - hb_comp_functions.pLast->lPCodePos ); + } + EndWhile + { + hb_compGenJumpHere( $4 ); --hb_comp_wWhileCounter; LoopEnd(); - functions.pLast->bFlags &= ~ FUN_WITH_RETURN; - } + hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; + } ; -WhileBegin : WHILE { $$ = functions.pLast->lPCodePos; ++_wWhileCounter; LoopStart(); } +WhileBegin : WHILE { $$ = hb_comp_functions.pLast->lPCodePos; ++hb_comp_wWhileCounter; LoopStart(); } ; EndWhile : END | ENDDO ; -ForNext : FOR IDENTIFIER ForAssign Expression { PopId( $2 ); $$ = functions.pLast->lPCodePos; ++_wForCounter; LoopStart(); } - TO Expression { PushId( $2 ); } - StepExpr Crlf { if( $9 ) - GenPCode1( HB_P_FORTEST ); - else - GenPCode1( HB_P_LESS ); - ValTypePop( 1 ); /* TODO: check for proper type of loop variable */ - $$ = JumpTrue( 0 ); - Line(); - } - ForStatements { LoopHere(); - PushId( $2 ); - if( $9 ) - GenPCode1( HB_P_PLUS ); - else - Inc(); - PopId( $2 ); - Jump( $5 - functions.pLast->lPCodePos ); - JumpHere( $11 ); - LoopEnd(); - if( $9 ) - GenPopPCode(); - functions.pLast->bFlags &= ~ FUN_WITH_RETURN; - } +ForNext : FOR LValue ForAssign Expression /* 1 2 3 4 */ + { + ++hb_comp_wForCounter; /* 5 */ + $$ = hb_compExprGenStatement( hb_compExprAssign( $2, $4 ) ); + } + TO Expression StepExpr /* 6 7 8 */ + { + LoopStart(); + $$ = hb_comp_functions.pLast->lPCodePos; /* 9 */ + if( $8 ) + hb_compExprGenPush( $8 ); /* step */ + hb_compExprGenPush( $2 ); /* counter */ + hb_compExprGenPush( $7 ); /* end */ + } + Crlf /* 10 */ + { + if( $8 ) + hb_compGenPCode1( HB_P_FORTEST ); + else + hb_compGenPCode1( HB_P_LESSEQUAL ); + $$ = hb_compGenJumpFalse( 0 ); /* 11 */ + Line(); + } + ForStatements /* 12 */ + { + LoopHere(); + if( $8 ) + hb_compExprGenStatement( hb_compExprSetOperand( hb_compExprNewPlusEq( $2 ), $8 ) ); + else + hb_compExprGenStatement( hb_compExprNewPreInc( $2 ) ); + hb_compGenJump( $9 - hb_comp_functions.pLast->lPCodePos ); + hb_compGenJumpHere( $11 ); + LoopEnd(); + hb_compExprDelete( $7 ); + hb_compExprDelete( $5 ); + hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; + } ; ForAssign : '=' | INASSIGN ; -StepExpr : /* default step expression */ { $$ =0; } - | STEP Expression { $$ =1; } +StepExpr : /* default step expression */ { $$ = NULL; } + | STEP Expression { $$ = $2; } ; -ForStatements : EmptyStats NEXT { --_wForCounter; } - | EmptyStats NEXT IDENTIFIER { --_wForCounter; } +ForStatements : EmptyStats NEXT { --hb_comp_wForCounter; } + | EmptyStats NEXT IDENTIFIER { --hb_comp_wForCounter; } ; -BeginSeq : BEGINSEQ { ++_wSeqCounter; $$ = SequenceBegin(); } Crlf { Line(); } +BeginSeq : BEGINSEQ { ++hb_comp_wSeqCounter; $$ = SequenceBegin(); } Crlf { Line(); } EmptyStats { /* Set jump address for HB_P_SEQBEGIN opcode - this address * will be used in BREAK code if there is no RECOVER clause */ - JumpHere( $2 ); + hb_compGenJumpHere( $2 ); $$ = SequenceEnd(); Line(); } @@ -1320,7 +1069,7 @@ BeginSeq : BEGINSEQ { ++_wSeqCounter; $$ = SequenceBegin(); } Crlf { * HB_P_SEQBEGIN opcode if there is RECOVER clause */ if( $7 ) - JumpThere( $2, $7-( _bLineNumbers ? 3 : 0 ) ); + hb_compGenJumpThere( $2, $7-( hb_comp_bLineNumbers ? 3 : 0 ) ); } END { @@ -1328,13 +1077,13 @@ BeginSeq : BEGINSEQ { ++_wSeqCounter; $$ = SequenceBegin(); } Crlf { * There is no line number after HB_P_SEQEND in case no * RECOVER clause is used */ - JumpThere( $6, functions.pLast->lPCodePos-((_bLineNumbers && !$7)?3:0) ); + hb_compGenJumpThere( $6, hb_comp_functions.pLast->lPCodePos-((hb_comp_bLineNumbers && !$7)?3:0) ); if( $7 ) /* only if there is RECOVER clause */ LineDebug(); else - --_wSeqCounter; /* RECOVER is also considered as end of sequence */ + --hb_comp_wSeqCounter; /* RECOVER is also considered as end of sequence */ SequenceFinish( $2, $5 ); - functions.pLast->bFlags &= ~ FUN_WITH_RETURN; + hb_comp_functions.pLast->bFlags &= ~ FUN_WITH_RETURN; } ; @@ -1345,19 +1094,19 @@ RecoverSeq : /* no recover */ { $$ = 0; } RecoverEmpty : RECOVER { - $$ = functions.pLast->lPCodePos; - --_wSeqCounter; - GenPCode1( HB_P_SEQRECOVER ); - GenPopPCode(); + $$ = hb_comp_functions.pLast->lPCodePos; + --hb_comp_wSeqCounter; + hb_compGenPCode1( HB_P_SEQRECOVER ); + hb_compGenPCode1( HB_P_POP ); } ; RecoverUsing : RECOVER USING IDENTIFIER { - $$ = functions.pLast->lPCodePos; - --_wSeqCounter; - GenPCode1( HB_P_SEQRECOVER ); - PopId( $3 ); + $$ = hb_comp_functions.pLast->lPCodePos; + --hb_comp_wSeqCounter; + hb_compGenPCode1( HB_P_SEQRECOVER ); + hb_compGenPopVar( $3 ); } ; @@ -1367,1084 +1116,83 @@ RecoverUsing : RECOVER USING IDENTIFIER * DO .. WITH ++variable * will pass the value of variable not a reference */ -DoProc : DO IDENTIFIER { PushSymbol( $2, 1 ); PushNil(); Do( 0 ); } - | DO IDENTIFIER { PushSymbol( $2, 1 ); PushNil(); } WITH DoArgList { Do( $5 ); } - | WHILE { PushSymbol( yy_strdup("WHILE"), 1 ); PushNil(); } WITH DoArgList { Do( $4 ); } +DoProc : DO IDENTIFIER { hb_compPushSymbol( $2, 1 ); hb_compGenPushNil(); hb_compGenDoProc( 0 ); } + | DO IDENTIFIER { hb_compPushSymbol( $2, 1 ); hb_compGenPushNil(); } WITH DoArgList { hb_compGenDoProc( $5 ); } + | WHILE { hb_compPushSymbol( yy_strdup("WHILE"), 1 ); hb_compGenPushNil(); } WITH DoArgList { hb_compGenDoProc( $4 ); } ; -DoArgList : ',' { PushNil(); PushNil(); $$ = 2; } +DoArgList : ',' { hb_compGenPushNil(); hb_compGenPushNil(); $$ = 2; } | DoExpression { $$ = 1; } - | DoArgList ',' { PushNil(); $$++; } + | DoArgList ',' { hb_compGenPushNil(); $$++; } | DoArgList ',' DoExpression { $$++; } - | ',' { PushNil(); } DoExpression { $$ = 2; } + | ',' { hb_compGenPushNil(); } DoExpression { $$ = 2; } ; -DoExpression: IDENTIFIER { PushIdByRef( $1 ); } - | NumExpression { } - | ConExpression { } - | DynExpression { } +DoExpression: IDENTIFIER { hb_compGenPushVarRef( $1 ); } + | SimpleExpression { } | PareExpList { } ; Crlf : '\n' { ++iLine; } - | ';' { _bDontGenLineNum = TRUE; } + | ';' { hb_comp_bDontGenLineNum = TRUE; } ; %% -void yyerror( char * s ) -{ - GenError( _szCErrors, 'E', ERR_YACC, s, NULL ); -} - -void * GenElseIf( void * pFirst, ULONG ulOffset ) -{ - PELSEIF pElseIf = ( PELSEIF ) hb_xgrab( sizeof( _ELSEIF ) ), pLast; - - pElseIf->ulOffset = ulOffset; - pElseIf->pNext = 0; - - if( ! pFirst ) - pFirst = pElseIf; - else - { - pLast = ( PELSEIF ) pFirst; - while( pLast->pNext ) - pLast = pLast->pNext; - pLast->pNext = pElseIf; - } - return pFirst; -} - -void GenError( char* _szErrors[], char cPrefix, int iError, char * szError1, char * szError2 ) -{ - if( files.pLast != NULL && files.pLast->szFileName != NULL ) - printf( "\r%s(%i) ", files.pLast->szFileName, iLine ); - - printf( "Error %c%04i ", cPrefix, iError ); - printf( _szErrors[ iError - 1 ], szError1, szError2 ); - printf( "\n" ); - - exit( EXIT_FAILURE ); -} - -void GenWarning( char* _szWarnings[], char cPrefix, int iWarning, char * szWarning1, char * szWarning2) -{ - if( _iWarnings ) - { - char *szText = _szWarnings[ iWarning - 1 ]; - - if( (szText[ 0 ] - '0') <= _iWarnings ) - { - printf( "\r%s(%i) ", files.pLast->szFileName, iLine ); - printf( "Warning %c%04i ", cPrefix, iWarning ); - printf( szText + 1, szWarning1, szWarning2 ); - printf( "\n" ); - - _bAnyWarning = TRUE; /* report warnings at exit */ - } - } -} - -void EXTERNAL_LINKAGE close_on_exit( void ) -{ - PFILE pFile = files.pLast; - - while( pFile ) - { /* - printf( "\nClosing file: %s\n", pFile->szFileName ); -*/ - fclose( pFile->handle ); - pFile = ( PFILE ) pFile->pPrev; - } -} - -int harbour_main( int argc, char * argv[] ) -{ - int iStatus = 0; - int iArg; - BOOL bSkipGen; - - /* Check for the nologo switch /q0 before everything else. */ - - for( iArg = 1; iArg < argc; iArg++ ) - { - if( SwitchCmp( argv[ iArg ], "Q0" ) ) - _bLogo = FALSE; - - else if( SwitchCmp( argv[ iArg ], "CREDITS" ) || - SwitchCmp( argv[ iArg ], "CREDIT" ) || - SwitchCmp( argv[ iArg ], "CREDI" ) || - SwitchCmp( argv[ iArg ], "CRED" ) ) - _bCredits = TRUE; - } - - if( _bLogo ) - { - printf( "Harbour Compiler, Build %i%s (%04d.%02d.%02d)\n", - hb_build, hb_revision, hb_year, hb_month, hb_day ); - printf( "Copyright 1999, http://www.harbour-project.org\n" ); - } - - if( _bCredits ) - { - PrintCredits(); - return iStatus; - } - - if( argc > 1 ) - { - char szFileName[ _POSIX_PATH_MAX ]; /* filename to parse */ - char szPpoName[ _POSIX_PATH_MAX ]; - - _pFileName = NULL; - _pOutPath = NULL; - - Hbpp_init(); /* Initialization of preprocessor arrays */ - /* Command line options */ - for( iArg = 1; iArg < argc; iArg++ ) - { - if( IS_OPT_SEP( argv[ iArg ][ 0 ] ) ) - { - switch( argv[ iArg ][ 1 ] ) - { - case '1': - if( argv[ iArg ][ 2 ] == '0' ) - _bRestrictSymbolLength = TRUE; - break; - - case 'a': - case 'A': - /* variables declared by PRIVATE and PUBLIC statement are - * automatically assumed as MEMVAR - */ - _bAutoMemvarAssume = TRUE; - break; - - case 'b': - case 'B': - _bDebugInfo = TRUE; - _bLineNumbers = TRUE; - break; - - case 'd': - case 'D': /* defines a Lex #define from the command line */ - { - unsigned int i = 0; - char * szDefText = yy_strdup( argv[ iArg ] + 2 ); - while( i < strlen( szDefText ) && szDefText[ i ] != '=' ) - i++; - if( szDefText[ i ] != '=' ) - AddDefine( szDefText, 0 ); - else - { - szDefText[ i ] = '\0'; - AddDefine( szDefText, szDefText + i + 1 ); - } - free( szDefText ); - } - break; - - case 'e': - case 'E': - - if( argv[ iArg ][ 2 ] == 's' || - argv[ iArg ][ 2 ] == 'S' ) - { - switch( argv[ iArg ][ 3 ] ) - { - case '\0': - case '0': - _iExitLevel = HB_EXITLEVEL_DEFAULT; - break; - - case '1': - _iExitLevel = HB_EXITLEVEL_SETEXIT; - break; - - case '2': - _iExitLevel = HB_EXITLEVEL_DELTARGET; - break; - - default: - GenError( _szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); - } - } - else - GenError( _szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); - - break; - case 'g': - case 'G': - switch( argv[ iArg ][ 2 ] ) - { - case 'c': - case 'C': - _iLanguage = LANG_C; - - switch( argv[ iArg ][ 3 ] ) - { - case '\0': - case '1': - _bGenCVerbose = TRUE; - break; - - case '0': - _bGenCVerbose = FALSE; - break; - - default: - GenError( _szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); - } - break; - - case 'f': - case 'F': - _iLanguage = LANG_OBJ32; - break; - - case 'j': - case 'J': - _iLanguage = LANG_JAVA; - break; - - case 'p': - case 'P': - _iLanguage = LANG_PASCAL; - break; - - case 'r': - case 'R': - _iLanguage = LANG_RESOURCES; - break; - - case 'h': - case 'H': - _iLanguage = LANG_PORT_OBJ; - break; - - default: - printf( "\nUnsupported output language option\n" ); - exit( EXIT_FAILURE ); - } - break; - - case 'i': - case 'I': - { - char * pPath; - char * pDelim; - char * szInclude; - - pPath = szInclude = yy_strdup( argv[ iArg ] + 2 ); - while( ( pDelim = strchr( pPath, OS_PATH_LIST_SEPARATOR ) ) != NULL ) - { - * pDelim = '\0'; - AddSearchPath( pPath, &_pIncludePath ); - pPath = pDelim + 1; - } - AddSearchPath( pPath, &_pIncludePath ); - } - break; - - case 'l': - case 'L': - _bLineNumbers = FALSE; - break; - - case 'm': - case 'M': - /* TODO: Implement this switch */ - printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); - break; - - case 'n': - case 'N': - _bStartProc = FALSE; - break; - - case 'o': - case 'O': - _pOutPath = hb_fsFNameSplit( argv[ iArg ] + 2 ); - break; - - /* Added for preprocessor needs */ - case 'p': - case 'P': - _bPPO = TRUE; - break; - - case 'q': - case 'Q': - _bQuiet = TRUE; - break; - - case 'r': - case 'R': - /* TODO: Implement this switch */ - printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); - break; - - case 's': - case 'S': - _bSyntaxCheckOnly = TRUE; - break; - - case 't': - case 'T': - /* TODO: Implement this switch */ - printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); - break; - - case 'u': - case 'U': - /* TODO: Implement this switch */ - printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); - break; - - case 'v': - case 'V': - /* All undeclared variables are assumed MEMVAR variables - */ - _bForceMemvars = TRUE; - break; - - case 'w': - case 'W': - _iWarnings = 1; - if( argv[ iArg ][ 2 ] ) - { /*there is -w<0,1,2,3> probably */ - _iWarnings = argv[ iArg ][ 2 ] - '0'; - if( _iWarnings < 0 || _iWarnings > 3 ) - GenError( _szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); - } - break; - - case 'x': - case 'X': - { - if( strlen( argv[ iArg ] + 2 ) == 0 ) - sprintf( _szPrefix, "%08lX_", PackDateTime() ); - else - { - strncpy( _szPrefix, argv[ iArg ] + 2, 16 ); - _szPrefix[ 16 ] = '\0'; - strcat( _szPrefix, "_" ); - } - } - break; - -#ifdef YYDEBUG - case 'y': - case 'Y': - yydebug = TRUE; - break; -#endif - - case 'z': - case 'Z': - _bShortCuts = FALSE; - break; - - default: - GenError( _szCErrors, 'E', ERR_BADOPTION, argv[ iArg ], NULL ); - break; - } - } - else if( argv[ iArg ][ 0 ] == '@' ) - /* TODO: Implement this switch */ - printf( "Not yet supported command line option: %s\n", argv[ iArg ] ); - else - { - if( _pFileName ) - GenError( _szCErrors, 'E', ERR_BADPARAM, argv[ iArg ], NULL ); - else - { - _pFileName = hb_fsFNameSplit( argv[ iArg ] ); - - if( ! _pFileName->szName ) - GenError( _szCErrors, 'E', ERR_BADFILENAME, argv[ iArg ], NULL ); - } - } - } - - if( _pFileName ) - { - if( !_pFileName->szExtension ) - _pFileName->szExtension = ".prg"; - hb_fsFNameMerge( szFileName, _pFileName ); - if( _bPPO ) - { - _pFileName->szExtension = ".ppo"; - hb_fsFNameMerge( szPpoName, _pFileName ); - yyppo = fopen( szPpoName, "w" ); - if( ! yyppo ) - { - GenError( _szCErrors, 'E', ERR_CREATE_PPO, szPpoName, NULL ); - return iStatus; - } - } - } - else - { - PrintUsage( argv[ 0 ] ); - return iStatus; - } - - files.iFiles = 0; /* initialize support variables */ - files.pLast = NULL; - functions.iCount = 0; - functions.pFirst = NULL; - functions.pLast = NULL; - funcalls.iCount = 0; - funcalls.pFirst = NULL; - funcalls.pLast = NULL; - symbols.iCount = 0; - symbols.pFirst = NULL; - symbols.pLast = NULL; - - _pInitFunc = NULL; - _bAnyWarning = FALSE; - - atexit( close_on_exit ); - - if( Include( szFileName, NULL ) ) - { - char * szInclude = getenv( "INCLUDE" ); - - if( szInclude ) - { - char * pPath; - char * pDelim; - - pPath = szInclude = yy_strdup( szInclude ); - while( ( pDelim = strchr( pPath, OS_PATH_LIST_SEPARATOR ) ) != NULL ) - { - *pDelim = '\0'; - AddSearchPath( pPath, &_pIncludePath ); - pPath = pDelim + 1; - } - AddSearchPath( pPath, &_pIncludePath ); - } - - /* Generate the starting procedure frame - */ - if( _bStartProc ) - FunDef( yy_strupr( yy_strdup( _pFileName->szName ) ), 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. - */ - FunDef( yy_strupr( yy_strdup( "" ) ), FS_PUBLIC, FUN_PROCEDURE ); - - yyparse(); - - GenExterns(); /* generates EXTERN symbols names */ - fclose( yyin ); - files.pLast = NULL; - - bSkipGen = FALSE; - - if( _bAnyWarning ) - { - if( _iExitLevel == HB_EXITLEVEL_SETEXIT ) - iStatus = 1; - if( _iExitLevel == HB_EXITLEVEL_DELTARGET ) - { - iStatus = 1; - bSkipGen = TRUE; - printf( "\nNo code generated\n" ); - } - } - - if( ! _bSyntaxCheckOnly && ! bSkipGen ) - { - if( _pInitFunc ) - { - PCOMSYMBOL pSym; - - /* Fix the number of static variables */ - _pInitFunc->pCode[ 3 ] = HB_LOBYTE( _iStatics ); - _pInitFunc->pCode[ 4 ] = HB_HIBYTE( _iStatics ); - _pInitFunc->iStaticsBase = _iStatics; - - pSym = AddSymbol( _pInitFunc->szName, NULL ); - pSym->cScope |= _pInitFunc->cScope; - functions.pLast->pNext = _pInitFunc; - ++functions.iCount; - } - - _pFileName->szPath = NULL; - _pFileName->szExtension = NULL; - - /* we create a the output file */ - if( _pOutPath ) - { - if( _pOutPath->szPath ) - _pFileName->szPath = _pOutPath->szPath; - if( _pOutPath->szName ) - { - _pFileName->szName = _pOutPath->szName; - if( _pOutPath->szExtension ) - _pFileName->szExtension = _pOutPath->szExtension; - } - } - - switch( _iLanguage ) - { - case LANG_C: - GenCCode( _pFileName ); - break; - - case LANG_OBJ32: -#ifdef HARBOUR_OBJ_GENERATION - GenObj32( _pFileName ); -#endif - break; - - case LANG_JAVA: - GenJava( _pFileName ); - break; - - case LANG_PASCAL: - GenPascal( _pFileName ); - break; - - case LANG_RESOURCES: - GenRC( _pFileName ); - break; - - case LANG_PORT_OBJ: - GenPortObj( _pFileName ); - break; - } - } - - if( _bPPO ) - fclose( yyppo ); - } - else - { - printf( "Cannot open input file: %s\n", szFileName ); - iStatus = 1; - } - hb_xfree( ( void * ) _pFileName ); - if( _pOutPath ) - hb_xfree( _pOutPath ); - } - else - PrintUsage( argv[ 0 ] ); - - return iStatus; -} - -/* - * Prints available options -*/ -void PrintUsage( char * szSelf ) -{ - printf( "\nSyntax: %s [options]" - "\n" - "\nOptions: /a automatic memvar declaration" - "\n /b debug info" - "\n /d[=] #define " - "\n /es[] set exit severity" - "\n /g output type generated is (see below)" - "\n /gc[] output type: C source (.c) (default)" - "\n : 0=without comments, 1=normal (default)" -#ifdef HARBOUR_OBJ_GENERATION - "\n /gf output type: Windows/DOS OBJ32 (.obj)" -#endif - "\n /gh output type: Harbour Portable Object (.hrb)" - "\n /gj output type: Java source (.java)" - "\n /gp output type: Pascal source (.pas)" - "\n /gr output type: Windows resource (.rc)" - "\n /i add #include file search path" - "\n /l suppress line number information" -/* TODO: "\n /m compile module only" */ - "\n /n no implicit starting procedure" - "\n /o object file drive and/or path" - "\n /p generate pre-processed output (.ppo) file" - "\n /q quiet" - "\n /q0 quiet and don't display program header" -/* TODO: "\n /r[] request linker to search (or none)" */ - "\n /s syntax check only" -/* TODO: "\n /t path for temp file creation" */ -/* TODO: "\n /u[] use command def set in (or none)" */ - "\n /v variables are assumed M->" - "\n /w[] set warning level number (0..3, default 1)" - "\n /x[] set symbol init function name prefix (for .c only)" -#ifdef YYDEBUG - "\n /y trace lex & yacc activity" -#endif - "\n /z suppress shortcutting (.and. & .or.)" - "\n /10 restrict symbol length to 10 characters" -/* TODO: "\n @ compile list of modules in " */ - "\n" - , szSelf ); -} - -/* - * Prints credits -*/ -void PrintCredits( void ) -{ - printf( "\nCredits: The Harbour Team at www.harbour-project.com" - ); -} - -/* - * Function that adds specified path to the list of pathnames to search + ** ------------------------------------------------------------------------ ** */ -void AddSearchPath( char * szPath, PATHNAMES * * pSearchList ) -{ - PATHNAMES * pPath = *pSearchList; - if( pPath ) - { - while( pPath->pNext ) - pPath = pPath->pNext; - pPath->pNext = ( PATHNAMES * ) hb_xgrab( sizeof( PATHNAMES ) ); - pPath = pPath->pNext; - } +int harbour_main( char * szName ) +{ + /* Generate the starting procedure frame + */ + if( hb_comp_bStartProc ) + hb_compFunDef( yy_strupr( yy_strdup( szName ) ), FS_PUBLIC, FUN_PROCEDURE ); else - { - *pSearchList = pPath = ( PATHNAMES * ) hb_xgrab( sizeof( PATHNAMES ) ); - } - pPath->pNext = NULL; - pPath->szPath = szPath; -} + /* 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_compFunDef( yy_strupr( yy_strdup( "" ) ), FS_PUBLIC, FUN_PROCEDURE ); + yyparse(); -/* - * This function adds the name of called function into the list - * as they have to be placed on the symbol table later than the first - * public symbol - */ -PFUNCTION AddFunCall( char * szFunctionName ) -{ - PFUNCTION pFunc = FunctionNew( szFunctionName, 0 ); + hb_compGenExterns(); /* generates EXTERN symbols names */ - if( ! funcalls.iCount ) - { - funcalls.pFirst = pFunc; - funcalls.pLast = pFunc; - } - else - { - ( ( PFUNCTION ) funcalls.pLast )->pNext = pFunc; - funcalls.pLast = pFunc; - } - funcalls.iCount++; - - return pFunc; -} - -/* - * This function adds the name of external symbol into the list of externals - * as they have to be placed on the symbol table later than the first - * public symbol - */ -void AddExtern( char * szExternName ) /* defines a new extern name */ -{ - PEXTERN pExtern = ( PEXTERN ) hb_xgrab( sizeof( _EXTERN ) ), pLast; - - pExtern->szName = szExternName; - pExtern->pNext = NULL; - - if( pExterns == NULL ) - pExterns = pExtern; - else - { - pLast = pExterns; - while( pLast->pNext ) - pLast = pLast->pNext; - pLast->pNext = pExtern; - } -} - -void SetVarMacro( void ) -{ - if( iVarScope == VS_PRIVATE ) - PushSymbol( yy_strdup( "__MVPRIVATE" ), 1); - else - PushSymbol( yy_strdup( "__MVPUBLIC" ), 1); - - PushNil(); - - /* Mark Position of the begining ogf the interpreted macro pcode. */ - _ulBookMark = functions.pLast->lPCodePos ; -} - -void FunMacroAssign( void ) -{ - ULONG _ulBufferSize, i = 0; - BYTE * _pCodeBuffer; - - /* We'll need the interpreted value of the macro (recently pushed) again for use by __MVPUT() */ - _ulBufferSize = functions.pLast->lPCodePos - _ulBookMark ; - _pCodeBuffer = ( BYTE * ) hb_xgrab( _ulBufferSize + 1); - - while( i < _ulBufferSize ) - { - _pCodeBuffer[ i ] = functions.pLast->pCode[ _ulBookMark + i ]; - i++; - } - - Do( 1 ); - - if( functions.pLast->lPCodeSize - functions.pLast->lPCodePos <= _ulBufferSize ) - functions.pLast->pCode = ( BYTE * ) hb_xrealloc( functions.pLast->pCode, functions.pLast->lPCodeSize += ( _ulBufferSize + PCODE_CHUNK ) ); - - PushSymbol( yy_strdup( "__MVPUT" ), 1); - PushNil(); - - i = 0; - while( i < _ulBufferSize ) - { - functions.pLast->pCode[ functions.pLast->lPCodePos++ ] = _pCodeBuffer[ i ]; - i++ ; - } - - hb_xfree( ( void * ) _pCodeBuffer ); -} - -void AddVar( char * szVarName ) -{ - PVAR pVar, pLastVar; - PFUNCTION pFunc = functions.pLast; - - if( ! _bStartProc && functions.iCount <= 1 && iVarScope == VS_LOCAL ) - { - /* Variable declaration is outside of function/procedure body. - In this case only STATIC and PARAMETERS variables are allowed. */ - --iLine; - GenError( _szCErrors, 'E', ERR_OUTSIDE, NULL, NULL ); - } - - /* check if we are declaring local/static variable after some - * executable statements - * Note: FIELD and MEMVAR are executable statements - */ - if( ( functions.pLast->bFlags & FUN_STATEMENTS ) && !( iVarScope == VS_FIELD || ( iVarScope & VS_MEMVAR ) ) ) - { - --iLine; - GenError( _szCErrors, 'E', ERR_FOLLOWS_EXEC, ( iVarScope == VS_LOCAL ? "LOCAL" : "STATIC" ), NULL ); - } - - /* When static variable is added then functions.pLast points to function - * that will initialise variables. The function where variable is being - * defined is stored in pOwner member. - */ - if( iVarScope == VS_STATIC ) - { - pFunc = pFunc->pOwner; - /* Check if an illegal action was invoked during a static variable - * value initialization - */ - if( _pInitFunc->bFlags & FUN_ILLEGAL_INIT ) - GenError( _szCErrors, 'E', ERR_ILLEGAL_INIT, szVarName, pFunc->szName ); - } - - /* Check if a declaration of duplicated variable name is requested */ - if( pFunc->szName ) - { - /* variable defined in a function/procedure */ - CheckDuplVars( pFunc->pFields, szVarName, iVarScope ); - CheckDuplVars( pFunc->pStatics, szVarName, iVarScope ); - if( !( iVarScope == VS_PRIVATE || iVarScope == VS_PUBLIC ) ) - CheckDuplVars( pFunc->pMemvars, szVarName, iVarScope ); - } - else - /* variable defined in a codeblock */ - iVarScope = VS_PARAMETER; - CheckDuplVars( pFunc->pLocals, szVarName, iVarScope ); - - pVar = ( PVAR ) hb_xgrab( sizeof( VAR ) ); - pVar->szName = szVarName; - pVar->szAlias = NULL; - pVar->cType = _cVarType; - pVar->iUsed = 0; - pVar->pNext = NULL; - - if( iVarScope & VS_MEMVAR ) + if( hb_comp_pInitFunc ) { PCOMSYMBOL pSym; - USHORT wPos; - if( _bAutoMemvarAssume || iVarScope == VS_MEMVAR ) - { - /** add this variable to the list of MEMVAR variables - */ - if( ! pFunc->pMemvars ) - pFunc->pMemvars = pVar; - else - { - pLastVar = pFunc->pMemvars; - while( pLastVar->pNext ) - pLastVar = pLastVar->pNext; - pLastVar->pNext = pVar; - } - } + /* Fix the number of static variables */ + hb_comp_pInitFunc->pCode[ 3 ] = HB_LOBYTE( hb_comp_iStaticCnt ); + hb_comp_pInitFunc->pCode[ 4 ] = HB_HIBYTE( hb_comp_iStaticCnt ); + hb_comp_pInitFunc->iStaticsBase = hb_comp_iStaticCnt; - switch( iVarScope ) - { - case VS_MEMVAR: - /* variable declared in MEMVAR statement */ - break; - case ( VS_PARAMETER | VS_PRIVATE ): - { - BOOL bNewParameter = FALSE; - - if( ++functions.pLast->wParamNum > functions.pLast->wParamCount ) - { - functions.pLast->wParamCount = functions.pLast->wParamNum; - bNewParameter = TRUE; - } - - pSym = GetSymbol( szVarName, &wPos ); /* check if symbol exists already */ - if( ! pSym ) - pSym = AddSymbol( yy_strdup( szVarName ), &wPos ); - pSym->cScope |= VS_MEMVAR; - GenPCode3( HB_P_PARAMETER, HB_LOBYTE( wPos ), HB_HIBYTE( wPos ) ); - GenPCode1( HB_LOBYTE( functions.pLast->wParamNum ) ); - - /* Add this variable to the local variables list - this will - * allow to use the correct positions for real local variables. - * The name of variable have to be hidden because we should - * not find this name on the local variables list. - * We have to use the new structure because it is used in - * memvars list already. - */ - if( bNewParameter ) - { - pVar = ( PVAR ) hb_xgrab( sizeof( VAR ) ); - pVar->szName = yy_strdup( szVarName ); - pVar->szAlias = NULL; - pVar->cType = _cVarType; - pVar->iUsed = 0; - pVar->pNext = NULL; - pVar->szName[ 0 ] ='!'; - if( ! pFunc->pLocals ) - pFunc->pLocals = pVar; - else - { - pLastVar = pFunc->pLocals; - while( pLastVar->pNext ) - pLastVar = pLastVar->pNext; - pLastVar->pNext = pVar; - } - } - } - break; - case VS_PRIVATE: - { - PushSymbol( yy_strdup( "__MVPRIVATE" ), 1); - PushNil(); - PushSymbol( yy_strdup( szVarName ), 0 ); - Do( 1 ); - pSym = GetSymbol( szVarName, NULL ); - pSym->cScope |= VS_MEMVAR; - } - break; - case VS_PUBLIC: - { - PushSymbol( yy_strdup( "__MVPUBLIC" ), 1); - PushNil(); - PushSymbol( yy_strdup( szVarName ), 0 ); - Do( 1 ); - pSym = GetSymbol( szVarName, NULL ); - pSym->cScope |= VS_MEMVAR; - } - break; - } + pSym = hb_compAddSymbol( hb_comp_pInitFunc->szName, NULL ); + pSym->cScope |= hb_comp_pInitFunc->cScope; + hb_comp_functions.pLast->pNext = hb_comp_pInitFunc; + ++hb_comp_functions.iCount; } + + /* Close processed file (it is opened in Include() function ) + */ + fclose( yyin ); + + hb_comp_files.pLast = NULL; + + return 0; +} + + +/* ------------------------------------------------------------------------ */ + +void yyerror( char * s ) +{ + if( yytext[ 0 ] == '\n' ) + hb_compGenError( hb_comp_szCErrors, 'E', ERR_YACC, s, "" ); else - { - switch( iVarScope ) - { - case VS_LOCAL: - case VS_PARAMETER: - { - USHORT wLocal = 1; - - if( ! pFunc->pLocals ) - pFunc->pLocals = pVar; - else - { - pLastVar = pFunc->pLocals; - while( pLastVar->pNext ) - { - pLastVar = pLastVar->pNext; - wLocal++; - } - pLastVar->pNext = pVar; - } - if( iVarScope == VS_PARAMETER ) - { - ++functions.pLast->wParamCount; - functions.pLast->bFlags |= FUN_USES_LOCAL_PARAMS; - } - if( _bDebugInfo ) - { - GenPCode3( HB_P_LOCALNAME, HB_LOBYTE( wLocal ), HB_HIBYTE( wLocal ) ); - GenPCodeN( ( BYTE * )szVarName, strlen( szVarName ) ); - GenPCode1( 0 ); - } - } - break; - - case VS_STATIC: - if( ! pFunc->pStatics ) - pFunc->pStatics = pVar; - else - { - pLastVar = pFunc->pStatics; - while( pLastVar->pNext ) - pLastVar = pLastVar->pNext; - pLastVar->pNext = pVar; - } - break; - - case VS_FIELD: - if( ! pFunc->pFields ) - pFunc->pFields = pVar; - else - { - pLastVar = pFunc->pFields; - while( pLastVar->pNext ) - pLastVar = pLastVar->pNext; - pLastVar->pNext = pVar; - } - break; - } - - } -} - -PCOMSYMBOL AddSymbol( char * szSymbolName, USHORT * pwPos ) -{ - PCOMSYMBOL pSym = ( PCOMSYMBOL ) hb_xgrab( sizeof( COMSYMBOL ) ); - - pSym->szName = szSymbolName; - pSym->cScope = 0; - pSym->cType = _cVarType; - pSym->pNext = NULL; - - if( ! symbols.iCount ) - { - symbols.pFirst = pSym; - symbols.pLast = pSym; - } - else - { - ( ( PCOMSYMBOL ) symbols.pLast )->pNext = pSym; - symbols.pLast = pSym; - } - symbols.iCount++; - - if( pwPos ) - *pwPos = symbols.iCount; - - /*if( _cVarType != ' ') printf("\nDeclared %s as type %c at symbol %i\n", szSymbolName, _cVarType, symbols.iCount );*/ - return pSym; -} - -/* Adds new alias to the alias stack - */ -void AliasAdd( ALIASID_PTR pAlias ) -{ - pAlias->pPrev = pAliasId; - pAliasId = pAlias; -} - -/* Restores previously selected alias - */ -void AliasRemove( void ) -{ - ALIASID_PTR pAlias = pAliasId; - - pAliasId = pAliasId->pPrev; - hb_xfree( pAlias ); -} - -/* Adds an integer workarea number into alias stack - */ -void AliasAddInt( int iWorkarea ) -{ - ALIASID_PTR pAlias = ( ALIASID_PTR ) hb_xgrab( sizeof( ALIASID ) ); - - pAlias->type = ALIAS_NUMBER; - pAlias->alias.iAlias = iWorkarea; - AliasAdd( pAlias ); -} - -/* Adds an expression into alias stack - */ -void AliasAddExp( void ) -{ - ALIASID_PTR pAlias = ( ALIASID_PTR ) hb_xgrab( sizeof( ALIASID ) ); - - pAlias->type = ALIAS_EVAL; - AliasAdd( pAlias ); -} - -/* Adds an alias name into alias stack - */ -void AliasAddStr( char * szAlias ) -{ - ALIASID_PTR pAlias = ( ALIASID_PTR ) hb_xgrab( sizeof( ALIASID ) ); - - pAlias->type = ALIAS_NAME; - pAlias->alias.szAlias = szAlias; - AliasAdd( pAlias ); -} - -/* Generates pcodes to store the current workarea number - */ -void AliasPush( void ) -{ - GenPCode1( HB_P_PUSHALIAS ); -} - -/* Generates pcodes to select the workarea number using current value - * from the eval stack - */ -void AliasPop( void ) -{ - GenPCode1( HB_P_POPALIAS ); -} - -/* Generates pcodes to swap two last items from the eval stack. - * Last item (after swaping) is next popped as current workarea - */ -void AliasSwap( void ) -{ - GenPCode1( HB_P_SWAPALIAS ); -} - -/* Generates pcodes to access an array element - */ -static void ArrayAt( void ) -{ - GenPCode1( HB_P_ARRAYAT ); - - ValTypeCheck( 'N', WARN_NUMERIC_TYPE, WARN_NUMERIC_SUSPECT ); - ValTypePop( 1 ); -} - -/* Generates pcodes to assign a value to an array element - */ -static void ArrayPut( void ) -{ - GenPCode1( HB_P_ARRAYPUT ); - - /* Pop a value and a last array index - * - rest of array indexes were popped in ArrayAt() - */ - ValTypePop( 2 ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_YACC, s, yytext ); } @@ -2480,7 +1228,7 @@ int Include( char * szFileName, PATHNAMES * pSearch ) return 0; } - if( ! _bQuiet ) + if( ! hb_comp_bQuiet ) printf( "\nCompiling \'%s\'\n", szFileName ); pFile = ( PFILE ) hb_xgrab( sizeof( _FILE ) ); @@ -2488,21 +1236,21 @@ int Include( char * szFileName, PATHNAMES * pSearch ) pFile->szFileName = szFileName; pFile->pPrev = NULL; - if( ! files.iFiles ) - files.pLast = pFile; + if( ! hb_comp_files.iFiles ) + hb_comp_files.pLast = pFile; else { - files.pLast->iLine = iLine; + hb_comp_files.pLast->iLine = iLine; iLine = 1; - pFile->pPrev = files.pLast; - files.pLast = pFile; + pFile->pPrev = hb_comp_files.pLast; + hb_comp_files.pLast = pFile; } #ifdef __cplusplus yy_switch_to_buffer( ( YY_BUFFER_STATE ) ( pFile->pBuffer = yy_create_buffer( yyin, 8192 * 2 ) ) ); #else yy_switch_to_buffer( pFile->pBuffer = yy_create_buffer( yyin, 8192 * 2 ) ); #endif - files.iFiles++; + hb_comp_files.iFiles++; return 1; } @@ -2510,1858 +1258,34 @@ int yywrap( void ) /* handles the EOF of the currently processed file */ { void * pLast; - if( files.iFiles == 1 ) + if( hb_comp_files.iFiles == 1 ) return 1; /* we have reached the main EOF */ else { - pLast = files.pLast; - fclose( files.pLast->handle ); - files.pLast = ( PFILE ) ( ( PFILE ) files.pLast )->pPrev; - iLine = files.pLast->iLine; - if( ! _bQuiet ) - printf( "\nCompiling %s\n", files.pLast->szFileName ); + pLast = hb_comp_files.pLast; + fclose( hb_comp_files.pLast->handle ); + hb_comp_files.pLast = ( PFILE ) ( ( PFILE ) hb_comp_files.pLast )->pPrev; + iLine = hb_comp_files.pLast->iLine; + if( ! hb_comp_bQuiet ) + printf( "\nCompiling %s\n", hb_comp_files.pLast->szFileName ); #ifdef __cplusplus yy_delete_buffer( ( YY_BUFFER_STATE ) ( ( PFILE ) pLast )->pBuffer ); #else yy_delete_buffer( ( ( PFILE ) pLast )->pBuffer ); #endif free( pLast ); - files.iFiles--; - yyin = files.pLast->handle; + hb_comp_files.iFiles--; + yyin = hb_comp_files.pLast->handle; #ifdef __cplusplus - yy_switch_to_buffer( ( YY_BUFFER_STATE ) files.pLast->pBuffer ); + yy_switch_to_buffer( ( YY_BUFFER_STATE ) hb_comp_files.pLast->pBuffer ); #else - yy_switch_to_buffer( files.pLast->pBuffer ); + yy_switch_to_buffer( hb_comp_files.pLast->pBuffer ); #endif return 0; /* we close the currently include file and continue */ } } -void Duplicate( void ) -{ - GenPCode1( HB_P_DUPLICATE ); - - ValTypePush( ValTypeGet() ); -} - -void DupPCode( ULONG ulStart ) /* duplicates the current generated pcode from an offset */ -{ - ULONG w, wEnd = functions.pLast->lPCodePos - ulStart; - - for( w = 0; w < wEnd; w++ ) - GenPCode1( functions.pLast->pCode[ ulStart + w ] ); -} - -/* - * Starts a new expression in the parenthesized epressions list - */ -void ExpListPush( void ) -{ - EXPLIST_PTR pExp = ( EXPLIST_PTR ) hb_xgrab( sizeof( EXPLIST ) ); - - pExp->pNext = pExp->pPrev = NULL; - - /* Store the previous state on the stack */ - if( _pExpList ) - { - _pExpList->pNext = pExp; - pExp->pPrev = _pExpList; - /* save currently used pcode buffer */ - _pExpList->exprSize = functions.pLast->lPCodePos; - _pExpList->exprPCode = functions.pLast->pCode; - } - _pExpList = pExp; - - /* store current pcode buffer */ - pExp->prevPCode = functions.pLast->pCode; - pExp->prevSize = functions.pLast->lPCodeSize; - pExp->prevPos = functions.pLast->lPCodePos; - - /* and create the new one */ - functions.pLast->pCode = ( BYTE * ) hb_xgrab( PCODE_CHUNK ); - functions.pLast->lPCodeSize = PCODE_CHUNK; - functions.pLast->lPCodePos = 0; - - pExp->exprPCode = functions.pLast->pCode; -} - -/* - * Pops specified number of expressions from the stack - */ -void ExpListPop( int iExpCount ) -{ - EXPLIST_PTR pExp, pDel; - - /* save currently used pcode buffer */ - _pExpList->exprSize = functions.pLast->lPCodePos; - _pExpList->exprPCode = functions.pLast->pCode; - - /* find the first expression in the list */ - while( --iExpCount ) - _pExpList = _pExpList->pPrev; - - /* return to the original pcode buffer */ - functions.pLast->pCode = _pExpList->prevPCode; - functions.pLast->lPCodeSize = _pExpList->prevSize; - functions.pLast->lPCodePos = _pExpList->prevPos; - - pExp = _pExpList; - if( _pExpList->pPrev ) - { - _pExpList = _pExpList->pPrev; - _pExpList->pNext = NULL; - } - else - _pExpList = NULL; - - while( pExp ) - { - if( pExp->exprSize ) - { - GenPCodeN( pExp->exprPCode, pExp->exprSize ); - if( pExp->pNext ) - GenPopPCode(); - } - else - { - /* exprN, , exprN1 - * in this context empty expression is not allowed - * - * NOTE: - * We don't have to generate this error - it is safe to continue - * pcode generation - in this case an empty expression will not - * generate any opcode - */ - GenError( _szCErrors, 'E', ERR_SYNTAX, ")", NULL ); - } - - hb_xfree( pExp->exprPCode ); - - pDel = pExp; - pExp = pExp->pNext; - hb_xfree( pDel ); - } -} - - -/* - * Function generates passed pcode for passed database field - */ -void FieldPCode( BYTE bPCode, char * szVarName ) -{ - USHORT wVar; - PCOMSYMBOL pVar; - - pVar = GetSymbol( szVarName, &wVar ); - if( ! pVar ) - pVar = AddSymbol( szVarName, &wVar ); - pVar->cScope |= VS_MEMVAR; - GenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ) ); -} - -/* - * This function creates and initialises the _FUNC structure - */ -PFUNCTION FunctionNew( char * szName, HB_SYMBOLSCOPE cScope ) -{ - PFUNCTION pFunc; - - pFunc = ( PFUNCTION ) hb_xgrab( sizeof( _FUNC ) ); - pFunc->szName = szName; - pFunc->cScope = cScope; - pFunc->pLocals = NULL; - pFunc->pStatics = NULL; - pFunc->pFields = NULL; - pFunc->pMemvars = NULL; - pFunc->pCode = NULL; - pFunc->lPCodeSize = 0; - pFunc->lPCodePos = 0; - pFunc->lLastPushPos = -1; - pFunc->pNext = NULL; - pFunc->wParamCount = 0; - pFunc->wParamNum = 0; - pFunc->iStaticsBase = _iStatics; - pFunc->pOwner = NULL; - pFunc->bFlags = 0; - - return pFunc; -} - -/* - * Stores a Clipper defined function/procedure - * szFunName - name of a function - * cScope - scope of a function - * iType - FUN_PROCEDURE if a procedure or 0 - */ -void FunDef( char * szFunName, HB_SYMBOLSCOPE cScope, int iType ) -{ - PCOMSYMBOL pSym; - PFUNCTION pFunc; - char * szFunction; - - FixReturns(); /* fix all previous function returns offsets */ - - pFunc = GetFunction( szFunName ); - if( pFunc ) - { - /* The name of a function/procedure is already defined */ - if( ( pFunc != functions.pFirst ) || _bStartProc ) - /* it is not a starting procedure that was automatically created */ - GenError( _szCErrors, 'E', ERR_FUNC_DUPL, szFunName, NULL ); - } - - szFunction = RESERVED_FUNC( szFunName ); - if( szFunction && !( functions.iCount==0 && !_bStartProc ) ) - { - /* We are ignoring it when it is the name of PRG file and we are - * not creating implicit starting procedure - */ - GenError( _szCErrors, 'E', ERR_FUNC_RESERVED, szFunction, szFunName ); - } - - iFunctions++; - - - pSym = GetSymbol( szFunName, NULL ); - if( ! pSym ) - /* there is not a symbol on the symbol table for this function name */ - pSym = AddSymbol( szFunName, NULL ); - - if( cScope != FS_PUBLIC ) -/* pSym->cScope = FS_PUBLIC; */ -/* else */ - pSym->cScope |= cScope; /* we may have a non public function and a object message */ - - pFunc = FunctionNew( szFunName, cScope ); - pFunc->bFlags |= iType; - - if( functions.iCount == 0 ) - { - functions.pFirst = pFunc; - functions.pLast = pFunc; - } - else - { - functions.pLast->pNext = pFunc; - functions.pLast = pFunc; - } - functions.iCount++; - - _ulLastLinePos = 0; /* optimization of line numbers opcode generation */ - - GenPCode3( HB_P_FRAME, 0, 0 ); /* frame for locals and parameters */ - GenPCode3( HB_P_SFRAME, 0, 0 ); /* frame for statics variables */ - - if( _bDebugInfo ) - { - GenPCode1( HB_P_MODULENAME ); - GenPCodeN( ( BYTE * )files.pLast->szFileName, strlen( files.pLast->szFileName ) ); - GenPCode1( ':' ); - GenPCodeN( ( BYTE * )szFunName, strlen( szFunName ) ); - GenPCode1( 0 ); - } -} - -PFUNCTION KillFunction( PFUNCTION pFunc ) -{ - PFUNCTION pNext = pFunc->pNext; - PVAR pVar; - - while( pFunc->pLocals ) - { - pVar = pFunc->pLocals; - pFunc->pLocals = pVar->pNext; - - hb_xfree( ( void * ) pVar->szName ); - hb_xfree( ( void * ) pVar ); - } - - while( pFunc->pStatics ) - { - pVar = pFunc->pStatics; - pFunc->pStatics = pVar->pNext; - - hb_xfree( ( void * ) pVar->szName ); - hb_xfree( ( void * ) pVar ); - } - - while( pFunc->pFields ) - { - pVar = pFunc->pFields; - pFunc->pFields = pVar->pNext; - - hb_xfree( ( void * ) pVar->szName ); - if( pVar->szAlias ) - { - hb_xfree( ( void * ) pVar->szAlias ); - } - hb_xfree( ( void * ) pVar ); - } - - while( pFunc->pMemvars ) - { - pVar = pFunc->pMemvars; - pFunc->pMemvars = pVar->pNext; - - hb_xfree( ( void * ) pVar->szName ); - if( pVar->szAlias ) - { - hb_xfree( ( void * ) pVar->szAlias ); - } - hb_xfree( ( void * ) pVar ); - } - - hb_xfree( ( void * ) pFunc->pCode ); -/* hb_xfree( ( void * ) pFunc->szName ); The name will be released in KillSymbol() */ - hb_xfree( ( void * ) pFunc ); - - return pNext; -} - - -PCOMSYMBOL KillSymbol( PCOMSYMBOL pSym ) -{ - PCOMSYMBOL pNext = pSym->pNext; - - hb_xfree( ( void * ) pSym->szName ); - hb_xfree( ( void * ) pSym ); - - return pNext; -} - -void GenBreak( void ) -{ - PushSymbol( yy_strdup("BREAK"), 1 ); - PushNil(); -} - -void GenExterns( void ) /* generates the symbols for the EXTERN names */ -{ - PEXTERN pDelete; - - if( _bDebugInfo ) - AddExtern( yy_strdup( "__DBGENTRY" ) ); - - while( pExterns ) - { - if( GetSymbol( pExterns->szName, NULL ) ) - { - if( ! GetFuncall( pExterns->szName ) ) - AddFunCall( pExterns->szName ); - } - else - { - AddSymbol( pExterns->szName, NULL ); - AddFunCall( pExterns->szName ); - } - pDelete = pExterns; - pExterns = pExterns->pNext; - hb_xfree( ( void * ) pDelete ); - } -} - -/* This function generates pcodes for IIF( expr1, expr2, expr3 ) - * or IF( expr1, expr2, expr3 ) - * - * NOTE: - * 'IF' followed by parenthesized expression containing 3 expressions - * is always interpreted as IF inlined - it is not possible to distinguish - * it from IF( expr1, expr2, expr3 ); ENDIF syntax - * (This behaviour is Clipper compatible) - */ -void GenIfInline( void ) -{ - EXPLIST_PTR pExp, pDel; - int iExpCount = 3; /* We are expecting 3 expressions here */ - BOOL bGenPCode; - - /* save currently used pcode buffer */ - _pExpList->exprSize = functions.pLast->lPCodePos; - _pExpList->exprPCode = functions.pLast->pCode; - - /* find the first expression in the list */ - while( --iExpCount ) - _pExpList = _pExpList->pPrev; - - /* return to the original pcode buffer */ - functions.pLast->pCode = _pExpList->prevPCode; - functions.pLast->lPCodeSize = _pExpList->prevSize; - functions.pLast->lPCodePos = _pExpList->prevPos; - - /* Update the pointer for nested or next expressions */ - pExp = _pExpList; - if( _pExpList->pPrev ) - { - _pExpList = _pExpList->pPrev; - _pExpList->pNext = NULL; - } - else - _pExpList = NULL; - - bGenPCode = TRUE; - pDel = pExp; /* save it for later use */ - - /* pExp points now to pcode buffer for logical condition - */ - if( pExp->exprSize == 0 ) - { - /* The logical condition have to be specified. - * If it is empty then generate the syntax error - */ - GenError( _szCErrors, 'E', ERR_SYNTAX, ",", NULL ); - } - else if( pExp->exprSize == 1 ) - { - /* one byte opcode for logical condition - check if it is TRUE or FALSE - */ - if( pExp->exprPCode[ 0 ] == HB_P_TRUE ) - { - /* move to the second expression */ - pExp = pExp->pNext; - if( pExp->exprSize ) - GenPCodeN( pExp->exprPCode, pExp->exprSize ); - else - PushNil(); /* IIF have to return some value */ - bGenPCode = FALSE; - } - else if( pExp->exprPCode[ 0 ] == HB_P_FALSE ) - { - /* move to the third expression */ - pExp = pExp->pNext; - pExp = pExp->pNext; - if( pExp->exprSize ) - GenPCodeN( pExp->exprPCode, pExp->exprSize ); - else - PushNil(); /* IIF have to return some value */ - bGenPCode = FALSE; - } - } - - if( bGenPCode ) - { - /* generate pcodes for all expressions - */ - LONG lPosFalse, lPosEnd; - - GenPCodeN( pExp->exprPCode, pExp->exprSize ); - lPosFalse = JumpFalse( 0 ); - - pExp = pExp->pNext; - if( pExp->exprSize ) - GenPCodeN( pExp->exprPCode, pExp->exprSize ); - else - PushNil(); /* IIF have to return some value */ - lPosEnd = Jump( 0 ); - JumpHere( lPosFalse ); - - pExp = pExp->pNext; - if( pExp->exprSize ) - GenPCodeN( pExp->exprPCode, pExp->exprSize ); - else - PushNil(); /* IIF have to return some value */ - JumpHere( lPosEnd ); - } - - while( pDel ) - { - pExp = pDel; - pDel = pDel->pNext; - hb_xfree( pExp->exprPCode ); - hb_xfree( pExp ); - } - - ValTypePop( 1 ); -} - - -PFUNCTION GetFuncall( char * szFunctionName ) /* returns a previously called defined function */ -{ - PFUNCTION pFunc = funcalls.pFirst; - - while( pFunc ) - { - if( ! strcmp( pFunc->szName, szFunctionName ) ) - return pFunc; - else - { - if( pFunc->pNext ) - pFunc = pFunc->pNext; - else - return NULL; - } - } - return NULL; -} - -PFUNCTION GetFunction( char * szFunctionName ) /* returns a previously defined function */ -{ - PFUNCTION pFunc = functions.pFirst; - - while( pFunc ) - { - if( ! strcmp( pFunc->szName, szFunctionName ) ) - return pFunc; - else - { - if( pFunc->pNext ) - pFunc = pFunc->pNext; - else - return NULL; - } - } - return NULL; -} - -PVAR GetVar( PVAR pVars, USHORT wOrder ) /* returns variable if defined or zero */ -{ - USHORT w = 1; - - while( pVars->pNext && w++ < wOrder ) - pVars = pVars->pNext; - - return pVars; -} - -USHORT GetVarPos( PVAR pVars, char * szVarName ) /* returns the order + 1 of a variable if defined or zero */ -{ - USHORT wVar = 1; - - while( pVars ) - { - if( pVars->szName && ! strcmp( pVars->szName, szVarName ) ) - { - /* TODO: This is not the best place to push the variable type - * in some cases it will be called two times for the same variable - */ - ValTypePush( pVars->cType ); - pVars->iUsed = 1; - return wVar; - } - else - { - if( pVars->pNext ) - { - pVars = pVars->pNext; - wVar++; - } - else - return 0; - } - } - return 0; -} - -int GetLocalVarPos( char * szVarName ) /* returns the order + 1 of a variable if defined or zero */ -{ - int iVar = 0; - PFUNCTION pFunc = functions.pLast; - - if( pFunc->szName ) - /* we are in a function/procedure -we don't need any tricks */ - return GetVarPos( pFunc->pLocals, szVarName ); - else - { - /* we are in a codeblock */ - iVar = GetVarPos( pFunc->pLocals, szVarName ); - if( iVar == 0 ) - { - /* this is not a current codeblock parameter - * we have to check the list of nested codeblocks up to a function - * where the codeblock is defined - */ - PFUNCTION pOutBlock = pFunc; /* the outermost codeblock */ - - pFunc = pFunc->pOwner; - while( pFunc ) - { - iVar = GetVarPos( pFunc->pLocals, szVarName ); - if( iVar ) - { - if( pFunc->pOwner ) - { - /* this variable is defined in a parent codeblock - * It is not possible to access a parameter of a codeblock in which - * the current codeblock is defined - */ - GenError( _szCErrors, 'E', ERR_OUTER_VAR, szVarName, NULL ); - } - else - { - /* We want to access a local variable defined in a function - * that owns this codeblock. We cannot access this variable in - * a normal way because at runtime the stack base will point - * to local variables of EVAL function. - * The codeblock cannot have static variables then we can - * use this structure to store temporarily all referenced - * local variables - */ - /* NOTE: The list of local variables defined in a function - * and referenced in a codeblock will be stored in a outer - * codeblock only. This makes sure that all variables will be - * detached properly - the inner codeblock can be created - * outside of a function where it was defined when the local - * variables are not accessible. - */ - iVar = -GetVarPos( pOutBlock->pStatics, szVarName ); - if( iVar == 0 ) - { - /* this variable was not referenced yet - add it to the list */ - PVAR pVar; - - pVar = ( PVAR ) hb_xgrab( sizeof( VAR ) ); - pVar->szName = szVarName; - pVar->cType = ' '; - pVar->iUsed = 0; - pVar->pNext = NULL; - - /* Use negative order to signal that we are accessing a local - * variable from a codeblock - */ - iVar = -1; /* first variable */ - if( ! pOutBlock->pStatics ) - pOutBlock->pStatics = pVar; - else - { - PVAR pLastVar = pOutBlock->pStatics; - - --iVar; /* this will be at least second variable */ - while( pLastVar->pNext ) - { - pLastVar = pLastVar->pNext; - --iVar; - } - pLastVar->pNext = pVar; - } - } - return iVar; - } - } - pOutBlock = pFunc; - pFunc = pFunc->pOwner; - } - } - } - return iVar; -} - -/* - * Gets position of passed static variables. - * All static variables are hold in a single array at runtime then positions - * are numbered for whole PRG module. - */ -int GetStaticVarPos( char * szVarName ) -{ - int iPos; - PFUNCTION pFunc = functions.pLast; - - /* First we have to check if this name belongs to a static variable - * defined in current function - */ - if( pFunc->pOwner ) - pFunc = pFunc->pOwner; /* we are in the static variable definition state */ - iPos = GetVarPos( pFunc->pStatics, szVarName ); - if( iPos ) - return iPos + pFunc->iStaticsBase; - - /* Next we have to check the list of global static variables - * Note: It is not possible to have global static variables when - * implicit starting procedure is defined - */ - if( !_bStartProc ) - { - iPos = GetVarPos( functions.pFirst->pStatics, szVarName ); - if( iPos ) - return iPos; - } - return 0; -} - -/* Checks if passed variable name is declared as FIELD - * Returns 0 if not found in FIELD list or its position in this list if found - */ -int GetFieldVarPos( char * szVarName, PFUNCTION pFunc ) -{ - int iVar; - - if( pFunc->szName ) - /* we are in a function/procedure -we don't need any tricks */ - iVar = GetVarPos( pFunc->pFields, szVarName ); - else - { - /* we have to check the list of nested codeblock up to a function - * where the codeblock is defined - */ - while( pFunc->pOwner ) - pFunc = pFunc->pOwner; - iVar = GetVarPos( pFunc->pFields, szVarName ); - } - return iVar; -} - -/** Checks if passed variable name is declared as MEMVAR - * Returns 0 if not found in MEMVAR list or its position in this list if found - */ -int GetMemvarPos( char * szVarName, PFUNCTION pFunc ) -{ - int iVar; - - if( pFunc->szName ) - /* we are in a function/procedure -we don't need any tricks */ - iVar = GetVarPos( pFunc->pMemvars, szVarName ); - else - { - /* we have to check the list of nested codeblock up to a function - * where the codeblock is defined - */ - while( pFunc->pOwner ) - pFunc = pFunc->pOwner; - iVar = GetVarPos( pFunc->pMemvars, szVarName ); - } - return iVar; -} - -USHORT FixSymbolPos( USHORT wCompilePos ) -{ - return ( _bStartProc ? wCompilePos - 1 : wCompilePos - 2 ); -} - - -/* returns a symbol pointer from the symbol table - * and sets its position in the symbol table - */ -PCOMSYMBOL GetSymbol( char * szSymbolName, USHORT * pwPos ) -{ - PCOMSYMBOL pSym = symbols.pFirst; - USHORT wCnt = 1; - - if( pwPos ) - *pwPos = 0; - while( pSym ) - { - if( ! strcmp( pSym->szName, szSymbolName ) ) - { - if( pwPos ) - *pwPos = wCnt; - return pSym; - } - else - { - if( pSym->pNext ) - { - pSym = pSym->pNext; - ++wCnt; - } - else - return NULL; - } - } - return NULL; -} - -PCOMSYMBOL GetSymbolOrd( USHORT wSymbol ) /* returns a symbol based on its index on the symbol table */ -{ - PCOMSYMBOL pSym = symbols.pFirst; - USHORT w = 1; - - while( w++ < wSymbol && pSym->pNext ) - pSym = pSym->pNext; - - return pSym; -} - -USHORT GetFunctionPos( char * szFunctionName ) /* return 0 if not found or order + 1 */ -{ - PFUNCTION pFunc = functions.pFirst; - USHORT wFunction = _bStartProc; - - while( pFunc ) - { - if( ! strcmp( pFunc->szName, szFunctionName ) && pFunc != functions.pFirst ) - return wFunction; - else - { - if( pFunc->pNext ) - { - pFunc = pFunc->pNext; - wFunction++; - } - else - return 0; - } - } - return 0; -} - -void Inc( void ) -{ - GenPCode1( HB_P_INC ); - - ValTypeCheck( 'N', WARN_NUMERIC_TYPE, WARN_NUMERIC_SUSPECT ); -} - -ULONG Jump( LONG lOffset ) -{ - /* TODO: We need a longer offset (longer then two bytes) - */ - if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) - GenError( _szCErrors, 'E', ERR_JUMP_TOO_LONG, NULL, NULL ); - - GenPCode3( HB_P_JUMP, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ) ); - - return functions.pLast->lPCodePos - 2; -} - -ULONG JumpFalse( LONG lOffset ) -{ - /* TODO: We need a longer offset (longer then two bytes) - */ - if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) - GenError( _szCErrors, 'E', ERR_JUMP_TOO_LONG, NULL, NULL ); - - GenPCode3( HB_P_JUMPFALSE, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ) ); - - ValTypeCheck( 'L', WARN_LOGICAL_TYPE, WARN_LOGICAL_SUSPECT ); - ValTypePop( 1 ); - - return functions.pLast->lPCodePos - 2; -} - -void JumpThere( ULONG ulFrom, ULONG ulTo ) -{ - BYTE * pCode = functions.pLast->pCode; - LONG lOffset = ulTo - ulFrom + 1; - - /* TODO: We need a longer offset (longer then two bytes) - */ - if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) - GenError( _szCErrors, 'E', ERR_JUMP_TOO_LONG, NULL, NULL ); - - pCode[ ( ULONG ) ulFrom ] = HB_LOBYTE( lOffset ); - pCode[ ( ULONG ) ulFrom + 1 ] = HB_HIBYTE( lOffset ); -} - -void JumpHere( ULONG ulOffset ) -{ - JumpThere( ulOffset, functions.pLast->lPCodePos ); -} - -ULONG JumpTrue( LONG lOffset ) -{ - /* TODO: We need a longer offset (longer then two bytes) - */ - if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) - GenError( _szCErrors, 'E', ERR_JUMP_TOO_LONG, NULL, NULL ); - GenPCode3( HB_P_JUMPTRUE, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ) ); - - ValTypeCheck( 'L', WARN_LOGICAL_TYPE, WARN_LOGICAL_SUSPECT ); - ValTypePop( 1 ); - - return functions.pLast->lPCodePos - 2; -} - -void Line( void ) /* generates the pcode with the currently compiled source code line */ -{ - if( _bLineNumbers && ! _bDontGenLineNum ) - { - if( ( ( functions.pLast->lPCodePos - _ulLastLinePos ) > 3 ) || _bDebugInfo ) - { - _ulLastLinePos = functions.pLast->lPCodePos; - GenPCode3( HB_P_LINE, HB_LOBYTE( iLine ), HB_HIBYTE( iLine ) ); - } - else - { - functions.pLast->pCode[ _ulLastLinePos +1 ] = HB_LOBYTE( iLine ); - functions.pLast->pCode[ _ulLastLinePos +2 ] = HB_HIBYTE( iLine ); - } - } - _bDontGenLineNum = FALSE; - functions.pLast->bFlags &= ~ FUN_WITH_RETURN; /* clear RETURN flag */ - functions.pLast->lLastPushPos = -1; -} - -/* Generates the pcode with the currently compiled source code line - * if debug code was requested only - */ -void LineDebug( void ) -{ - if( _bDebugInfo ) - Line(); - else - functions.pLast->bFlags &= ~ FUN_WITH_RETURN; /* clear RETURN flag */ -} - -void LineBody( void ) /* generates the pcode with the currently compiled source code line */ -{ - /* This line can be placed inside a procedure or function only */ - /* except EXTERNAL */ - if( _iState != EXTERN ) - { - if( ! _bStartProc && functions.iCount <= 1 ) - { - GenError( _szCErrors, 'E', ERR_OUTSIDE, NULL, NULL ); - } - } - - functions.pLast->bFlags |= FUN_STATEMENTS; - Line(); -} - -/** - * Function generates passed pcode for passed variable name - */ -void VariablePCode( BYTE bPCode, char * szVarName ) -{ - USHORT wVar; - PCOMSYMBOL pSym; - PFUNCTION pOwnerFunc = NULL; - int iType = VS_LOCAL; /* not really */ - - /* Check if it is a FIELD declared in current function - */ - wVar = GetFieldVarPos( szVarName, functions.pLast ); - if( wVar == 0 ) - { - /* Check if it is a MEMVAR declared in current function - */ - wVar = GetMemvarPos( szVarName, functions.pLast ); - if( wVar ) - iType = VS_MEMVAR; - } - else - { - iType = VS_FIELD; - pOwnerFunc = functions.pLast; - } - - /* if it is not declared in current function then check if it is - * a symbol with file wide scope - */ - if( wVar == 0 && ! _bStartProc ) - { - wVar = GetFieldVarPos( szVarName, functions.pFirst ); - if( wVar == 0 ) - { - wVar = GetMemvarPos( szVarName, functions.pFirst ); - if( wVar ) - iType = VS_MEMVAR; - } - else - { - iType = VS_FIELD; - pOwnerFunc = functions.pFirst; - } - } - - if( wVar == 0 ) - { - /* This is undeclared variable */ - /* - * NOTE: - * Clipper always assumes a memvar variable if undeclared variable - * is popped (a value is asssigned to a variable). - * - */ -#if defined( HARBOUR_STRICT_CLIPPER_COMPATIBILITY ) - if( _bForceMemvars || bPCode == HB_P_POPVARIABLE ) -#else - if( _bForceMemvars ) -#endif - { - /* -v switch was used -> assume it is a memvar variable - */ - iType = VS_MEMVAR; - GenWarning( _szCWarnings, 'W', WARN_MEMVAR_ASSUMED, szVarName, NULL ); - } - else - GenWarning( _szCWarnings, 'W', WARN_AMBIGUOUS_VAR, szVarName, NULL ); - } - - if( iType == VS_FIELD ) - { /* variable is declared using FIELD statement */ - PVAR pField = GetVar( pOwnerFunc->pFields, wVar ); - - if( pField->szAlias ) - { /* the alias was specified in FIELD declaration */ - if( bPCode == HB_P_POPVARIABLE ) - bPCode = HB_P_POPALIASEDFIELD; - else if( bPCode == HB_P_PUSHVARIABLE ) - bPCode = HB_P_PUSHALIASEDFIELD; - else - /* pushing fields by reference is not allowed */ - GenError( _szCErrors, 'E', ERR_INVALID_REFER, szVarName, NULL ); - /* - * Push alias symbol before the field symbol - */ - PushSymbol( yy_strdup( pField->szAlias ), 0 ); - } - else - { /* this is unaliased field */ - if( bPCode == HB_P_POPVARIABLE ) - bPCode = HB_P_POPFIELD; - else if( bPCode == HB_P_PUSHVARIABLE ) - bPCode = HB_P_PUSHFIELD; - else if( bPCode == HB_P_PUSHMEMVARREF ) - /* pushing fields by reference is not allowed */ - GenError( _szCErrors, 'E', ERR_INVALID_REFER, szVarName, NULL ); - } - } - else if( iType == VS_MEMVAR ) - { - /* variable is declared or assumed MEMVAR */ - if( bPCode == HB_P_POPVARIABLE ) - bPCode = HB_P_POPMEMVAR; - else if( bPCode == HB_P_PUSHVARIABLE ) - bPCode = HB_P_PUSHMEMVAR; - } - - /* Check if this variable name is placed into the symbol table - */ - pSym = GetSymbol( szVarName, &wVar ); - if( ! pSym ) - pSym = AddSymbol( szVarName, &wVar ); - pSym->cScope |= VS_MEMVAR; - GenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ) ); -} - -/** - * Function generates passed pcode for passed memvar name - */ -void MemvarPCode( BYTE bPCode, char * szVarName ) -{ - USHORT wVar; - PCOMSYMBOL pSym; - - /* Check if this variable name is placed into the symbol table - */ - pSym = GetSymbol( szVarName, &wVar ); - if( ! pSym ) - pSym = AddSymbol( szVarName, &wVar ); - pSym->cScope |= VS_MEMVAR; - GenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ) ); -} - -void Message( char * szMsgName ) /* sends a message to an object */ -{ - USHORT wSym; - PCOMSYMBOL pSym = GetSymbol( szMsgName, &wSym ); - - if( ! pSym ) /* the symbol was not found on the symbol table */ - pSym = AddSymbol( szMsgName, &wSym ); - pSym->cScope |= FS_MESSAGE; - GenPCode3( HB_P_MESSAGE, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ) ); - - ValTypePush( pSym->cType ); -} - -void MessageDupl( char * szMsgName ) /* fix a generated message and duplicate to an object */ -{ - USHORT wSetSym; - PCOMSYMBOL pSym; - BYTE bLoGetSym, bHiGetSym; /* get symbol */ - PFUNCTION pFunc = functions.pLast; /* get the currently defined Clipper function */ - - pSym = GetSymbol( szMsgName, &wSetSym ); - if( ! pSym ) /* the symbol was not found on the symbol table */ - pSym = AddSymbol( szMsgName, &wSetSym ); - pSym->cScope |= FS_MESSAGE; - /* Get previously generated message */ - bLoGetSym = pFunc->pCode[ _ulMessageFix + 1]; - bHiGetSym = pFunc->pCode[ _ulMessageFix + 2]; - - pFunc->pCode[ _ulMessageFix + 1 ] = HB_LOBYTE( wSetSym ); - pFunc->pCode[ _ulMessageFix + 2 ] = HB_HIBYTE( wSetSym ); - - pFunc->lPCodePos -= 3; /* Remove unnecessary function call */ - Duplicate(); /* Duplicate object */ - GenPCode3( HB_P_MESSAGE, bLoGetSym, bHiGetSym ); - /* Generate new message */ -} - -void MessageFix( char * szMsgName ) /* fix a generated message to an object */ -{ - USHORT wSym; - PCOMSYMBOL pSym; - PFUNCTION pFunc = functions.pLast; /* get the currently defined Clipper function */ - - pSym = GetSymbol( szMsgName, &wSym ); - if( ! pSym ) /* the symbol was not found on the symbol table */ - pSym = AddSymbol( szMsgName, &wSym ); - pSym->cScope |= FS_MESSAGE; - - pFunc->pCode[ _ulMessageFix + 1 ] = HB_LOBYTE( wSym ); - pFunc->pCode[ _ulMessageFix + 2 ] = HB_HIBYTE( wSym ); - pFunc->lPCodePos -= 3; /* Remove unnecessary function call */ -} - -void PopId( char * szVarName ) /* generates the pcode to pop a value from the virtual machine stack onto a variable */ -{ - int iVar; - - if( pAliasId == NULL ) - { - iVar = GetLocalVarPos( szVarName ); - if( iVar ) - GenPCode3( HB_P_POPLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); - else - { - iVar = GetStaticVarPos( szVarName ); - if( iVar ) - { - GenPCode3( HB_P_POPSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); - functions.pLast->bFlags |= FUN_USES_STATICS; - } - else - { - VariablePCode( HB_P_POPVARIABLE, szVarName ); - } - } - } - else - { - if( pAliasId->type == ALIAS_NAME ) - { - if( pAliasId->alias.szAlias[ 0 ] == 'M' && pAliasId->alias.szAlias[ 1 ] == '\0' ) - { /* M->variable */ - MemvarPCode( HB_P_POPMEMVAR, szVarName ); - } - else - { - int iCmp = strncmp( pAliasId->alias.szAlias, "MEMVAR", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( pAliasId->alias.szAlias, "MEMVAR", strlen( pAliasId->alias.szAlias ) ); - if( iCmp == 0 ) - { /* MEMVAR-> or MEMVA-> or MEMV-> */ - MemvarPCode( HB_P_POPMEMVAR, szVarName ); - } - else - { /* field variable */ - iCmp = strncmp( pAliasId->alias.szAlias, "FIELD", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( pAliasId->alias.szAlias, "FIELD", strlen( pAliasId->alias.szAlias ) ); - if( iCmp == 0 ) - { /* FIELD-> */ - FieldPCode( HB_P_POPFIELD, szVarName ); - } - else - { /* database alias */ - PushSymbol( yy_strdup( pAliasId->alias.szAlias ), 0 ); - FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); - } - } - } - } - else if( pAliasId->type == ALIAS_NUMBER ) - { - PushInteger( pAliasId->alias.iAlias ); - FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); - } - else - /* Alias is already placed on stack */ - FieldPCode( HB_P_POPALIASEDFIELD, szVarName ); - } - - ValTypeAssign( szVarName ); -} - -void PushId( char * szVarName ) /* generates the pcode to push a variable value to the virtual machine stack */ -{ - int iVar; - - if( pAliasId == NULL ) - { - if( iVarScope == VS_STATIC && functions.pLast->szName ) - { - /* Reffering to any variable is not allowed during initialization - * of static variable - */ - _pInitFunc->bFlags |= FUN_ILLEGAL_INIT; - } - - iVar = GetLocalVarPos( szVarName ); - if( iVar ) - GenPCode3( HB_P_PUSHLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); - else - { - iVar = GetStaticVarPos( szVarName ); - if( iVar ) - { - GenPCode3( HB_P_PUSHSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); - functions.pLast->bFlags |= FUN_USES_STATICS; - } - else - { - VariablePCode( HB_P_PUSHVARIABLE, szVarName ); - } - } - } - else - { - if( pAliasId->type == ALIAS_NAME ) - { - if( pAliasId->alias.szAlias[ 0 ] == 'M' && pAliasId->alias.szAlias[ 1 ] == '\0' ) - { /* M->variable */ - MemvarPCode( HB_P_PUSHMEMVAR, szVarName ); - } - else - { - int iCmp = strncmp( pAliasId->alias.szAlias, "MEMVAR", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( pAliasId->alias.szAlias, "MEMVAR", strlen( pAliasId->alias.szAlias ) ); - if( iCmp == 0 ) - { /* MEMVAR-> or MEMVA-> or MEMV-> */ - MemvarPCode( HB_P_PUSHMEMVAR, szVarName ); - } - else - { /* field variable */ - iCmp = strncmp( pAliasId->alias.szAlias, "FIELD", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( pAliasId->alias.szAlias, "FIELD", strlen( pAliasId->alias.szAlias ) ); - if( iCmp == 0 ) - { /* FIELD-> */ - FieldPCode( HB_P_PUSHFIELD, szVarName ); - } - else - { /* database alias */ - PushSymbol( yy_strdup( pAliasId->alias.szAlias ), 0 ); - FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); - } - } - } - } - else if( pAliasId->type == ALIAS_NUMBER ) - { - PushInteger( pAliasId->alias.iAlias ); - FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); - } - else - /* Alias is already placed on stack */ - FieldPCode( HB_P_PUSHALIASEDFIELD, szVarName ); - } -} - -void PushIdByRef( char * szVarName ) /* generates the pcode to push a variable by reference to the virtual machine stack */ -{ - USHORT iVar; - - if( iVarScope == VS_STATIC && functions.pLast->szName ) - { - /* Reffering to any variable is not allowed during initialization - * of static variable - */ - _pInitFunc->bFlags |= FUN_ILLEGAL_INIT; - } - - iVar = GetLocalVarPos( szVarName ); - if( iVar ) - GenPCode3( HB_P_PUSHLOCALREF, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); - else - { - iVar = GetStaticVarPos( szVarName ); - if( iVar ) - { - GenPCode3( HB_P_PUSHSTATICREF, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); - functions.pLast->bFlags |= FUN_USES_STATICS; - } - else - { - /* if undeclared variable is passed by reference then a memvar - * variable is assumed because fields cannot be passed by - * a reference - */ - VariablePCode( HB_P_PUSHMEMVARREF, szVarName ); - } - } -} - -void PushLogical( int iTrueFalse ) /* pushes a logical value on the virtual machine stack */ -{ - if( iTrueFalse ) - GenPCode1( HB_P_TRUE ); - else - GenPCode1( HB_P_FALSE ); - - ValTypePush( 'L' ); -} - -void PushNil( void ) -{ - GenPCode1( HB_P_PUSHNIL ); - - ValTypePush( ' ' ); /*TODO maybe 'U'*/ -} - -/* generates the pcode to push a double number on the virtual machine stack */ -void PushDouble( double dNumber, BYTE bDec ) -{ - GenPCode1( HB_P_PUSHDOUBLE ); - GenPCodeN( ( BYTE * ) &dNumber, sizeof( double ) ); - GenPCode1( bDec ); - - ValTypePush( 'N' ); -} - -void PushFunCall( char * szFunName ) -{ - char * szFunction; - - szFunction = RESERVED_FUNC( szFunName ); - if( szFunction ) - { - /* Abbreviated function name was used - change it for whole name - */ - PushSymbol( yy_strdup( szFunction ), 1 ); - } - else - PushSymbol( szFunName, 1 ); - - GenPCode1( HB_P_PUSHNIL ); -} - -/* generates the pcode to push a integer number on the virtual machine stack */ -void PushInteger( int iNumber ) -{ - if( iNumber ) - GenPCode3( HB_P_PUSHINT, HB_LOBYTE( ( USHORT ) iNumber ), HB_HIBYTE( ( USHORT ) iNumber ) ); - else - GenPCode1( HB_P_ZERO ); -} - -/* generates the pcode to push a long number on the virtual machine stack */ -void PushLong( long lNumber ) -{ - if( lNumber ) - { - GenPCode1( HB_P_PUSHLONG ); - GenPCode1( ( ( char * ) &lNumber )[ 0 ] ); - GenPCode1( ( ( char * ) &lNumber )[ 1 ] ); - GenPCode1( ( ( char * ) &lNumber )[ 2 ] ); - GenPCode1( ( ( char * ) &lNumber )[ 3 ] ); - } - else - GenPCode1( HB_P_ZERO ); - - ValTypePush( 'N' ); -} - -/* generates the pcode to push a string on the virtual machine stack */ -void PushString( char * szText ) -{ - int iStrLen = strlen( szText ); - - GenPCode3( HB_P_PUSHSTR, HB_LOBYTE( iStrLen ), HB_HIBYTE( iStrLen ) ); - GenPCodeN( ( BYTE * ) szText, iStrLen ); - - ValTypePush( 'C' ); -} - -/* generates the pcode to push a symbol on the virtual machine stack */ -void PushSymbol( char * szSymbolName, int iIsFunction ) -{ - USHORT wSym; - PCOMSYMBOL pSym; - - if( iIsFunction ) - { - char * pName = RESERVED_FUNC( szSymbolName ); - /* If it is reserved function name then we should truncate - * the requested name. - * We have to use passed szSymbolName so we can latter deallocate it - * (pName points to static data) - */ - if( pName ) - szSymbolName[ strlen( pName ) ] ='\0'; - } - - pSym = GetSymbol( szSymbolName, &wSym ); - if( ! pSym ) /* the symbol was not found on the symbol table */ - { - pSym = AddSymbol( szSymbolName, &wSym ); - if( iIsFunction ) - AddFunCall( szSymbolName ); - } - else - { - if( iIsFunction && ! GetFuncall( szSymbolName ) ) - AddFunCall( szSymbolName ); - } - GenPCode3( HB_P_PUSHSYM, HB_LOBYTE( wSym ), HB_HIBYTE( wSym ) ); - - ValTypePush( iIsFunction ? pSym->cType : _cVarType ); -} - - -void CheckDuplVars( PVAR pVar, char * szVarName, int iVarScope ) -{ - while( pVar ) - { - if( ! strcmp( pVar->szName, szVarName ) ) - { - if( ! ( iVarScope & VS_PARAMETER ) ) - --iLine; - GenError( _szCErrors, 'E', ERR_VAR_DUPL, szVarName, NULL ); - } - else - pVar = pVar->pNext; - } -} - -void Dec( void ) -{ - GenPCode1( HB_P_DEC ); - - ValTypeCheck( 'N', WARN_NUMERIC_TYPE, WARN_NUMERIC_SUSPECT ); -} - -void ArrayDim( int iDimensions ) -{ - GenPCode3( HB_P_ARRAYDIM, HB_LOBYTE( iDimensions ), HB_HIBYTE( iDimensions ) ); -} - -void Do( BYTE bParams ) -{ - GenPCode3( HB_P_DO, bParams, 0 ); - - ValTypePop( bParams + 1 ); /* pop all arguments and symbol type */ -} - -void FixElseIfs( void * pFixElseIfs ) -{ - PELSEIF pFix = ( PELSEIF ) pFixElseIfs; - - while( pFix ) - { - JumpHere( pFix->ulOffset ); - pFix = pFix->pNext; - } -} - -void FixReturns( void ) /* fixes all last defined function returns jumps offsets */ -{ - if( _iWarnings && functions.pLast ) - { - PVAR pVar; - - pVar = functions.pLast->pLocals; - while( pVar ) - { - if( pVar->szName && functions.pLast->szName && functions.pLast->szName[0] && ! pVar->iUsed ) - GenWarning( _szCWarnings, 'W', WARN_VAR_NOT_USED, pVar->szName, functions.pLast->szName ); - - pVar = pVar->pNext; - } - - pVar = functions.pLast->pStatics; - while( pVar ) - { - if( pVar->szName && functions.pLast->szName && functions.pLast->szName[0] && ! pVar->iUsed ) - GenWarning( _szCWarnings, 'W', WARN_VAR_NOT_USED, pVar->szName, functions.pLast->szName ); - - pVar = pVar->pNext; - } - - ValTypeReset( ); - - /* Check if the function returned some value - */ - if( (functions.pLast->bFlags & FUN_WITH_RETURN) == 0 && - (functions.pLast->bFlags & FUN_PROCEDURE) == 0 ) - GenWarning( _szCWarnings, 'W', WARN_FUN_WITH_NO_RETURN, - functions.pLast->szName, NULL ); - } - -/* TODO: check why it triggers this error in keywords.prg - if( pLoops ) - { - PTR_LOOPEXIT pLoop = pLoops; - char cLine[ 64 ]; - - while( pLoop->pNext ) - pLoop = pLoop->pNext; - - itoa( pLoop->iLine, cLine, 10 ); - GenError( _szCErrors, 'E', ERR_UNCLOSED_STRU, cLine, NULL ); - } -*/ -} - -void Function( BYTE bParams ) -{ - GenPCode3( HB_P_FUNCTION, bParams, 0 ); - - ValTypePop( bParams + 1 ); /* pop all arguments and symbol type */ -} - -void GenArray( int iElements ) -{ - GenPCode3( HB_P_ARRAYGEN, HB_LOBYTE( iElements ), HB_HIBYTE( iElements ) ); - - ValTypePop( iElements ); /* pop all items of the array */ - ValTypePush( 'A' ); -} - -static void GenPlusPCode( BYTE opcode ) -{ - GenPCode1( opcode ); - ValTypePlus(); -} - -static void GenNumPCode( BYTE opcode ) -{ - GenPCode1( opcode ); - ValTypeCheck2( 'N', WARN_NUMERIC_TYPE, WARN_NUMERIC_SUSPECT ); - ValTypePop( 2 ); - ValTypePush( 'N' ); -} - -static void GenRelPCode( BYTE opcode ) -{ - GenPCode1( opcode ); - ValTypeRelational(); -} - -static void GenNotPCode( void ) -{ - GenPCode1( HB_P_NOT ); - ValTypeCheck( 'L', WARN_LOGICAL_TYPE, WARN_LOGICAL_SUSPECT ); - /* Leave the original type on the stack */ -} - -static void GenNegatePCode( void ) -{ - GenPCode1( HB_P_NEGATE ); - ValTypeCheck( 'N', WARN_NUMERIC_TYPE, WARN_NUMERIC_SUSPECT ); - /* Leave the original type on the stack */ -} - -static void SetLastPushPos( void ) -{ - functions.pLast->lLastPushPos = functions.pLast->lPCodePos; -} - -static void RemoveExtraPush( void ) -{ - if( functions.pLast->lLastPushPos > -1 && functions.pLast->lPCodePos > functions.pLast->lLastPushPos ) - { - functions.pLast->lPCodePos = functions.pLast->lLastPushPos; - functions.pLast->lLastPushPos = -1; - } - else - GenPCode1( HB_P_POP ); - - ValTypePop( 1 ); -} - -static void GenPopPCode( void ) -{ - GenPCode1( HB_P_POP ); - ValTypePop( 1 ); -} - -static void GenPCode1( BYTE byte ) -{ - PFUNCTION pFunc = functions.pLast; /* get the currently defined Clipper function */ - - if( ! pFunc->pCode ) /* has been created the memory block to hold the pcode ? */ - { - pFunc->pCode = ( BYTE * ) hb_xgrab( PCODE_CHUNK ); - pFunc->lPCodeSize = PCODE_CHUNK; - pFunc->lPCodePos = 0; - } - else - if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 1 ) - pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += PCODE_CHUNK ); - - pFunc->pCode[ pFunc->lPCodePos++ ] = byte; -} - -static void GenPCode3( BYTE byte1, BYTE byte2, BYTE byte3 ) -{ - PFUNCTION pFunc = functions.pLast; /* get the currently defined Clipper function */ - - if( ! pFunc->pCode ) /* has been created the memory block to hold the pcode ? */ - { - pFunc->pCode = ( BYTE * ) hb_xgrab( PCODE_CHUNK ); - pFunc->lPCodeSize = PCODE_CHUNK; - pFunc->lPCodePos = 0; - } - else - if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 3 ) - pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += PCODE_CHUNK ); - - pFunc->pCode[ pFunc->lPCodePos++ ] = byte1; - pFunc->pCode[ pFunc->lPCodePos++ ] = byte2; - pFunc->pCode[ pFunc->lPCodePos++ ] = byte3; -} - -static void GenPCodeN( BYTE * pBuffer, ULONG ulSize ) -{ - PFUNCTION pFunc = functions.pLast; /* get the currently defined Clipper function */ - - if( ! pFunc->pCode ) /* has been created the memory block to hold the pcode ? */ - { - pFunc->lPCodeSize = ( ( ulSize / PCODE_CHUNK ) + 1 ) * PCODE_CHUNK; - pFunc->pCode = ( BYTE * ) hb_xgrab( pFunc->lPCodeSize ); - pFunc->lPCodePos = 0; - } - else if( pFunc->lPCodePos + ulSize > pFunc->lPCodeSize ) - { - /* not enough free space in pcode buffer - increase it */ - pFunc->lPCodeSize += ( ( ( ulSize / PCODE_CHUNK ) + 1 ) * PCODE_CHUNK ); - pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize ); - } - - memcpy( pFunc->pCode + pFunc->lPCodePos, pBuffer, ulSize ); - pFunc->lPCodePos += ulSize; -} - -char * SetData( char * szMsg ) /* generates an underscore-symbol name for a data assignment */ -{ - char * szResult = ( char * ) hb_xgrab( strlen( szMsg ) + 2 ); - - strcpy( szResult, "_" ); - strcat( szResult, szMsg ); - - return szResult; -} - -/* Generate the opcode to open BEGIN/END sequence - * This code is simmilar to JUMP opcode - the offset will be filled with - * - either the address of HB_P_SEQEND opcode if there is no RECOVER clause - * - or the address of RECOVER code - */ -ULONG SequenceBegin( void ) -{ - GenPCode3( HB_P_SEQBEGIN, 0, 0 ); - - return functions.pLast->lPCodePos - 2; -} - -/* Generate the opcode to close BEGIN/END sequence - * This code is simmilar to JUMP opcode - the offset will be filled with - * the address of first line after END SEQUENCE - * This opcode will be executed if recover code was not requested (as the - * last statement in code beetwen BEGIN ... RECOVER) or if BREAK was requested - * and there was no matching RECOVER clause. - */ -ULONG SequenceEnd( void ) -{ - GenPCode3( HB_P_SEQEND, 0, 0 ); - - return functions.pLast->lPCodePos - 2; -} - -/* Remove unnecessary opcodes in case there were no executable statements - * beetwen BEGIN and RECOVER sequence - */ -void SequenceFinish( ULONG ulStartPos, int bUsualStmts ) -{ - if( ! _bDebugInfo ) /* only if no debugger info is required */ - { - if( ! bUsualStmts ) - { - functions.pLast->lPCodePos = ulStartPos - 1; /* remove also HB_P_SEQBEGIN */ - _ulLastLinePos = ulStartPos - 4; - } - } -} - - -/* - * Start a new fake-function that will hold pcodes for a codeblock -*/ -void CodeBlockStart() -{ - PFUNCTION pFunc = FunctionNew( NULL, FS_STATIC ); - - pFunc->pOwner = functions.pLast; - pFunc->iStaticsBase = functions.pLast->iStaticsBase; - - functions.pLast = pFunc; - LineDebug(); -} - -void CodeBlockEnd() -{ - PFUNCTION pCodeblock; /* pointer to the current codeblock */ - PFUNCTION pFunc; /* pointer to a function that owns a codeblock */ - USHORT wSize; - USHORT wLocals = 0; /* number of referenced local variables */ - USHORT wPos; - PVAR pVar, pFree; - - pCodeblock = functions.pLast; - - /* return to pcode buffer of function/codeblock in which the current - * codeblock was defined - */ - functions.pLast = pCodeblock->pOwner; - - /* find the function that owns the codeblock */ - pFunc = pCodeblock->pOwner; - while( pFunc->pOwner ) - pFunc = pFunc->pOwner; - pFunc->bFlags |= ( pCodeblock->bFlags & FUN_USES_STATICS ); - - /* generate a proper codeblock frame with a codeblock size and with - * a number of expected parameters - */ - /*QUESTION: would be 64kB enough for a codeblock size? - * we are assuming now a USHORT for a size of codeblock - */ - - /* Count the number of referenced local variables */ - pVar = pCodeblock->pStatics; - while( pVar ) - { - pVar = pVar->pNext; - ++wLocals; - } - - /*NOTE: 8 = HB_P_PUSHBLOCK + USHORT( size ) + USHORT( wParams ) + USHORT( wLocals ) + _ENDBLOCK */ - wSize = ( USHORT ) pCodeblock->lPCodePos + 8 + wLocals * 2; - - GenPCode3( HB_P_PUSHBLOCK, HB_LOBYTE( wSize ), HB_HIBYTE( wSize ) ); - GenPCode1( HB_LOBYTE( pCodeblock->wParamCount ) ); - GenPCode1( HB_HIBYTE( pCodeblock->wParamCount ) ); - GenPCode1( HB_LOBYTE( wLocals ) ); - GenPCode1( HB_HIBYTE( wLocals ) ); - - /* generate the table of referenced local variables */ - pVar = pCodeblock->pStatics; - while( wLocals-- ) - { - wPos = GetVarPos( pFunc->pLocals, pVar->szName ); - GenPCode1( HB_LOBYTE( wPos ) ); - GenPCode1( HB_HIBYTE( wPos ) ); - - pFree = pVar; - hb_xfree( ( void * ) pFree->szName ); - pVar = pVar->pNext; - hb_xfree( ( void * ) pFree ); - } - - GenPCodeN( pCodeblock->pCode, pCodeblock->lPCodePos ); - GenPCode1( HB_P_ENDBLOCK ); /* finish the codeblock */ - - /* this fake-function is no longer needed */ - hb_xfree( ( void * ) pCodeblock->pCode ); - pVar = pCodeblock->pLocals; - while( pVar ) - { - if( _iWarnings && pFunc->szName && pVar->szName && ! pVar->iUsed ) - GenWarning( _szCWarnings, 'W', WARN_BLOCKVAR_NOT_USED, pVar->szName, pFunc->szName ); - - /* free used variables */ - pFree = pVar; - hb_xfree( ( void * ) pFree->szName ); - pVar = pVar->pNext; - hb_xfree( ( void * ) pFree ); - } - hb_xfree( ( void * ) pCodeblock ); - - ValTypePut( 'B' ); -} - -/* Set the name of an alias for the list of previously declared FIELDs - * - * szAlias -> name of the alias - * iField -> position of the first FIELD name to change - */ -void FieldsSetAlias( char * szAlias, int iField ) -{ - PVAR pVar; - - pVar = functions.pLast->pFields; - while( iField-- && pVar ) - pVar = pVar->pNext; - - while( pVar ) - { - pVar->szAlias = szAlias; - pVar = pVar->pNext; - } -} - -/* This functions counts the number of FIELD declaration in a function - * We will required this information in FieldsSetAlias function - */ -int FieldsCount() -{ - int iFields = 0; - PVAR pVar = functions.pLast->pFields; - - while( pVar ) - { - ++iFields; - pVar = pVar->pNext; - } - - return iFields; -} - -/* - * Start of definition of static variable - * We are using here the special function _pInitFunc which will store - * pcode needed to initialize all static variables declared in PRG module. - * pOwner member will point to a function where the static variable is - * declared: - * TODO: support for static variables in codeblock - */ -void StaticDefStart( void ) -{ - iVarScope = VS_STATIC; - Line(); - - functions.pLast->bFlags |= FUN_USES_STATICS; - if( ! _pInitFunc ) - { - BYTE pBuffer[ 5 ]; - - _pInitFunc = FunctionNew( yy_strdup("(_INITSTATICS)"), FS_INIT ); - _pInitFunc->pOwner = functions.pLast; - _pInitFunc->bFlags = FUN_USES_STATICS | FUN_PROCEDURE; - _pInitFunc->cScope = FS_INIT | FS_EXIT; - functions.pLast = _pInitFunc; - - pBuffer[ 0 ] = HB_P_STATICS; - pBuffer[ 1 ] = 0; - pBuffer[ 2 ] = 0; - pBuffer[ 3 ] = 1; /* the number of static variables is unknown now */ - pBuffer[ 4 ] = 0; - GenPCodeN( pBuffer, 5 ); - GenPCode3( HB_P_SFRAME, 0, 0 ); /* frame for statics variables */ - } - else - { - _pInitFunc->pOwner = functions.pLast; - functions.pLast = _pInitFunc; - } -} - -/* - * End of definition of static variable - * Return to previously pcoded function. - */ -void StaticDefEnd( int iCount ) -{ - functions.pLast = _pInitFunc->pOwner; - _pInitFunc->pOwner = NULL; - _iStatics += iCount; - iVarScope = VS_LOCAL; -} - -/* - * This function checks if we are initializing a static variable. - * It should be called only in case when the parser have recognized any - * function or method invocation. - */ -void StaticAssign( void ) -{ - if( iVarScope == VS_STATIC && functions.pLast->szName ) - /* function call is allowed if it is inside a codeblock - */ - _pInitFunc->bFlags |= FUN_ILLEGAL_INIT; -} +/* ************************************************************************* */ /* * This function stores the position in pcode buffer where the FOR/WHILE @@ -4371,23 +1295,23 @@ static void LoopStart( void ) { PTR_LOOPEXIT pLoop = ( PTR_LOOPEXIT ) hb_xgrab( sizeof( LOOPEXIT ) ); - if( pLoops ) + if( hb_comp_pLoops ) { - PTR_LOOPEXIT pLast = pLoops; + PTR_LOOPEXIT pLast = hb_comp_pLoops; while( pLast->pNext ) pLast = pLast->pNext; pLast->pNext = pLoop; } else - pLoops = pLoop; + hb_comp_pLoops = pLoop; pLoop->pNext = NULL; pLoop->pExitList = NULL; pLoop->pLoopList = NULL; - pLoop->ulOffset = functions.pLast->lPCodePos; /* store the start position */ + pLoop->ulOffset = hb_comp_functions.pLast->lPCodePos; /* store the start position */ pLoop->iLine = iLine; - pLoop->wSeqCounter = _wSeqCounter; /* store current SEQUENCE counter */ + pLoop->wSeqCounter = hb_comp_wSeqCounter; /* store current SEQUENCE counter */ } /* @@ -4400,19 +1324,19 @@ static void LoopLoop( void ) pLoop = ( PTR_LOOPEXIT ) hb_xgrab( sizeof( LOOPEXIT ) ); pLoop->pLoopList = NULL; - pLoop->ulOffset = functions.pLast->lPCodePos; /* store the position to fix */ + pLoop->ulOffset = hb_comp_functions.pLast->lPCodePos; /* store the position to fix */ - pLast = pLoops; + pLast = hb_comp_pLoops; while( pLast->pNext ) pLast = pLast->pNext; - if( pLast->wSeqCounter != _wSeqCounter ) + if( pLast->wSeqCounter != hb_comp_wSeqCounter ) { /* Attempt to LOOP from BEGIN/END sequence * Current SEQUENCE counter is different then at the beginning of loop * Notice that LOOP is allowed in RECOVER code. */ - GenError( _szCErrors, 'E', ERR_EXIT_IN_SEQUENCE, "LOOP", NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_EXIT_IN_SEQUENCE, "LOOP", NULL ); } while( pLast->pLoopList ) @@ -4420,7 +1344,7 @@ static void LoopLoop( void ) pLast->pLoopList = pLoop; - Jump( 0 ); + hb_compGenJump( 0 ); } /* @@ -4433,19 +1357,19 @@ static void LoopExit( void ) pLoop = ( PTR_LOOPEXIT ) hb_xgrab( sizeof( LOOPEXIT ) ); pLoop->pExitList = NULL; - pLoop->ulOffset = functions.pLast->lPCodePos; /* store the position to fix */ + pLoop->ulOffset = hb_comp_functions.pLast->lPCodePos; /* store the position to fix */ - pLast = pLoops; + pLast = hb_comp_pLoops; while( pLast->pNext ) pLast = pLast->pNext; - if( pLast->wSeqCounter != _wSeqCounter ) + if( pLast->wSeqCounter != hb_comp_wSeqCounter ) { /* Attempt to LOOP from BEGIN/END sequence * Current SEQUENCE counter is different then at the beginning of loop * Notice that LOOP is allowed in RECOVER code. */ - GenError( _szCErrors, 'E', ERR_EXIT_IN_SEQUENCE, "EXIT", NULL ); + hb_compGenError( hb_comp_szCErrors, 'E', ERR_EXIT_IN_SEQUENCE, "EXIT", NULL ); } while( pLast->pExitList ) @@ -4453,7 +1377,7 @@ static void LoopExit( void ) pLast->pExitList = pLoop; - Jump( 0 ); + hb_compGenJump( 0 ); } /* @@ -4461,7 +1385,7 @@ static void LoopExit( void ) */ static void LoopHere( void ) { - PTR_LOOPEXIT pLoop = pLoops, pFree; + PTR_LOOPEXIT pLoop = hb_comp_pLoops, pFree; while( pLoop->pNext ) pLoop = pLoop->pNext; @@ -4469,7 +1393,7 @@ static void LoopHere( void ) pLoop = pLoop->pLoopList; while( pLoop ) { - JumpHere( pLoop->ulOffset + 1 ); + hb_compGenJumpHere( pLoop->ulOffset + 1 ); pFree = pLoop; pLoop = pLoop->pLoopList; hb_xfree( ( void * ) pFree ); @@ -4481,7 +1405,7 @@ static void LoopHere( void ) */ static void LoopEnd( void ) { - PTR_LOOPEXIT pExit, pLoop = pLoops, pLast = pLoops, pFree; + PTR_LOOPEXIT pExit, pLoop = hb_comp_pLoops, pLast = hb_comp_pLoops, pFree; while( pLoop->pNext ) { @@ -4492,437 +1416,15 @@ static void LoopEnd( void ) pExit = pLoop->pExitList; while( pExit ) { - JumpHere( pExit->ulOffset + 1 ); + hb_compGenJumpHere( pExit->ulOffset + 1 ); pFree = pExit; pExit = pExit->pExitList; hb_xfree( ( void * ) pFree ); } pLast->pNext = NULL; - if( pLoop == pLoops ) - pLoops = NULL; + if( pLoop == hb_comp_pLoops ) + hb_comp_pLoops = NULL; hb_xfree( ( void * ) pLoop ); } -#define IS_PATH_SEP( c ) ( strchr( OS_PATH_DELIMITER_LIST, ( c ) ) != NULL ) - -/* Split given filename into path, name and extension */ -PHB_FNAME hb_fsFNameSplit( char * szFileName ) -{ - PHB_FNAME pFileName = ( PHB_FNAME ) hb_xgrab( sizeof( HB_FNAME ) ); - - int iLen = strlen( szFileName ); - int iSlashPos; - int iDotPos; - int iPos; - - pFileName->szPath = - pFileName->szName = - pFileName->szExtension = NULL; - - iSlashPos = iLen - 1; - iPos = 0; - - while( iSlashPos >= 0 && !IS_PATH_SEP( szFileName[ iSlashPos ] ) ) - --iSlashPos; - - if( iSlashPos == 0 ) - { - /* root path -> \filename */ - pFileName->szBuffer[ 0 ] = OS_PATH_DELIMITER; - pFileName->szBuffer[ 1 ] = '\0'; - pFileName->szPath = pFileName->szBuffer; - iPos = 2; /* first free position after the slash */ - } - else if( iSlashPos > 0 ) - { - /* If we are after a drive letter let's keep the following backslash */ - if( IS_PATH_SEP( ':' ) && - ( szFileName[ iSlashPos ] == ':' || szFileName[ iSlashPos - 1 ] == ':' ) ) - { - /* path with separator -> d:\path\filename or d:path\filename */ - memcpy( pFileName->szBuffer, szFileName, iSlashPos + 1 ); - pFileName->szBuffer[ iSlashPos + 1 ] = '\0'; - iPos = iSlashPos + 2; /* first free position after the slash */ - } - else - { - /* path with separator -> path\filename */ - memcpy( pFileName->szBuffer, szFileName, iSlashPos ); - pFileName->szBuffer[ iSlashPos ] = '\0'; - iPos = iSlashPos + 1; /* first free position after the slash */ - } - - pFileName->szPath = pFileName->szBuffer; - } - - iDotPos = iLen - 1; - while( iDotPos > iSlashPos && szFileName[ iDotPos ] != '.' ) - --iDotPos; - - if( ( iDotPos - iSlashPos ) > 1 ) - { - /* the dot was found - * and there is at least one character between a slash and a dot - */ - if( iDotPos == iLen - 1 ) - { - /* the dot is the last character - use it as extension name */ - pFileName->szExtension = pFileName->szBuffer + iPos; - pFileName->szBuffer[ iPos++ ] = '.'; - pFileName->szBuffer[ iPos++ ] = '\0'; - } - else - { - pFileName->szExtension = pFileName->szBuffer + iPos; - /* copy rest of the string with terminating ZERO character */ - memcpy( pFileName->szExtension, szFileName + iDotPos + 1, iLen - iDotPos ); - iPos += iLen - iDotPos; - } - } - else - /* there is no dot in the filename or it is '.filename' */ - iDotPos = iLen; - - if( ( iDotPos - iSlashPos - 1 ) > 0 ) - { - pFileName->szName = pFileName->szBuffer + iPos; - memcpy( pFileName->szName, szFileName + iSlashPos + 1, iDotPos - iSlashPos - 1 ); - pFileName->szName[ iDotPos - iSlashPos - 1 ] = '\0'; - } - -/* DEBUG - printf( "\nFilename: %s\n", szFileName ); - printf( "\n szPath: %s\n", pFileName->szPath ); - printf( "\n szName: %s\n", pFileName->szName ); - printf( "\n szExt: %s\n", pFileName->szExtension ); -*/ - - return pFileName; -} - -/* This function joins path, name and extension into a string with a filename */ -char * hb_fsFNameMerge( char * szFileName, PHB_FNAME pFileName ) -{ - if( pFileName->szPath && pFileName->szPath[ 0 ] ) - { - /* we have not empty path specified */ - int iLen = strlen( pFileName->szPath ); - - strcpy( szFileName, pFileName->szPath ); - - /* if the path is a root directory then we don't need to add path separator */ - if( !( IS_PATH_SEP( pFileName->szPath[ 0 ] ) && pFileName->szPath[ 0 ] == '\0' ) ) - { - /* add the path separator only in cases: - * when a name doesn't start with it - * when the path doesn't end with it - */ - if( !( IS_PATH_SEP( pFileName->szName[ 0 ] ) || IS_PATH_SEP( pFileName->szPath[ iLen-1 ] ) ) ) - { - szFileName[ iLen++ ] = OS_PATH_DELIMITER; - szFileName[ iLen ] = '\0'; - } - } - if( pFileName->szName ) - strcpy( szFileName + iLen, pFileName->szName ); - } - else - { - if( pFileName->szName ) - strcpy( szFileName, pFileName->szName ); - } - - if( pFileName->szExtension ) - { - int iLen = strlen( szFileName ); - - if( !( pFileName->szExtension[ 0 ] == '.' || szFileName[ iLen - 1 ] == '.') ) - { - /* add extension separator only when extansion doesn't contain it */ - szFileName[ iLen++ ] = '.'; - szFileName[ iLen ] = '\0'; - } - strcpy( szFileName + iLen, pFileName->szExtension ); - } - -/* DEBUG - printf( "\nMERGE:\n" ); - printf( "\n szPath: %s\n", pFileName->szPath ); - printf( "\n szName: %s\n", pFileName->szName ); - printf( "\n szExt: %s\n", pFileName->szExtension ); - printf( "\nFilename result: %s\n", szFileName ); -*/ - - return szFileName; -} - -void * hb_xgrab( ULONG ulSize ) /* allocates fixed memory, exits on failure */ -{ - void * pMem = malloc( ulSize ); - - if( ! pMem ) - GenError( _szCErrors, 'E', ERR_MEMALLOC, NULL, NULL ); - - return pMem; -} - -void * hb_xrealloc( void * pMem, ULONG ulSize ) /* reallocates memory */ -{ - void * pResult = realloc( pMem, ulSize ); - - if( ! pResult ) - GenError( _szCErrors, 'E', ERR_MEMREALLOC, NULL, NULL ); - - return pResult; -} - -void hb_xfree( void * pMem ) /* frees fixed memory */ -{ - if( pMem ) - free( pMem ); - else - GenError( _szCErrors, 'E', ERR_MEMFREE, NULL, NULL ); -} - -char * yy_strupr( char * p ) -{ - char * p1; - - for( p1 = p; * p1; p1++ ) - * p1 = toupper( * p1 ); - - return p; -} - -char * yy_strdup( char * p ) -{ - char * pDup; - int iLen; - - iLen = strlen( p ) + 1; - pDup = ( char * ) hb_xgrab( iLen ); - memcpy( pDup, p, iLen ); - - return pDup; -} - -/* checks if passed string is a reserved function name - */ -static char * reserved_name( char * szName ) -{ - USHORT wNum = 0; - int iFound = 1; - - while( wNum < RESERVED_FUNCTIONS && iFound ) - { - /* Compare first 4 characters - * If they are the same then compare the whole name - * SECO() is not allowed because of Clipper function SECONDS() - * however SECO32() is a valid name. - */ - iFound = strncmp( szName, _szReservedFun[ wNum ], 4 ); - if( iFound == 0 ) - iFound = strncmp( szName, _szReservedFun[ wNum ], strlen( szName ) ); - ++wNum; - } - if( iFound ) - return NULL; - else - return (char *) _szReservedFun[ wNum - 1 ]; -} - -/* NOTE: iMinParam = -1, means no checking */ -/* iMaxParam = -1, means no upper limit */ - -typedef struct -{ - char * cFuncName; /* function name */ - int iMinParam; /* min no of parms it needs */ - int iMaxParam; /* max no of parms need */ -} FUNCINFO, * PFUNCINFO; - -static FUNCINFO _StdFun[] = -{ - { "AADD" , 2, 2 }, - { "ABS" , 1, 1 }, - { "ASC" , 1, 1 }, - { "AT" , 2, 2 }, - { "BOF" , 0, 0 }, - { "BREAK" , 0, 1 }, - { "CDOW" , 1, 1 }, - { "CHR" , 1, 1 }, - { "CMONTH" , 1, 1 }, - { "COL" , 0, 0 }, - { "CTOD" , 1, 1 }, - { "DATE" , 0, 0 }, - { "DAY" , 1, 1 }, - { "DELETED" , 0, 0 }, - { "DEVPOS" , 2, 2 }, - { "DOW" , 1, 1 }, - { "DTOC" , 1, 1 }, - { "DTOS" , 1, 1 }, - { "EMPTY" , 1, 1 }, - { "EOF" , 0, 0 }, - { "EVAL" , 1, -1 }, - { "EXP" , 1, 1 }, - { "FCOUNT" , 0, 0 }, - { "FIELDNAME" , 1, 1 }, - { "FILE" , 1, 1 }, - { "FLOCK" , 0, 0 }, - { "FOUND" , 0, 0 }, - { "INKEY" , 0, 2 }, - { "INT" , 1, 1 }, - { "LASTREC" , 0, 0 }, - { "LEFT" , 2, 2 }, - { "LEN" , 1, 1 }, - { "LOCK" , 0, 0 }, - { "LOG" , 1, 1 }, - { "LOWER" , 1, 1 }, - { "LTRIM" , 1, 1 }, - { "MAX" , 2, 2 }, - { "MIN" , 2, 2 }, - { "MONTH" , 1, 1 }, - { "PCOL" , 0, 0 }, - { "PCOUNT" , 0, 0 }, - { "PROW" , 0, 0 }, - { "RECCOUNT" , 0, 0 }, - { "RECNO" , 0, 0 }, - { "REPLICATE" , 2, 2 }, - { "RLOCK" , 0, 0 }, - { "ROUND" , 2, 2 }, - { "ROW" , 0, 0 }, - { "RTRIM" , 1, 2 }, /* Second parameter is a Harbour extension */ - { "SECONDS" , 0, 0 }, - { "SELECT" , 0, 1 }, - { "SETPOS" , 2, 2 }, - { "SETPOSBS" , 0, 0 }, - { "SPACE" , 1, 1 }, - { "SQRT" , 1, 1 }, - { "STR" , 1, 3 }, - { "SUBSTR" , 2, 3 }, - { "TIME" , 0, 0 }, - { "TRANSFORM" , 2, 2 }, - { "TRIM" , 1, 2 }, /* Second parameter is a Harbour extension */ - { "TYPE" , 1, 1 }, - { "UPPER" , 1, 1 }, - { "VAL" , 1, 1 }, - { "VALTYPE" , 1, 1 }, - { "WORD" , 1, 1 }, - { "YEAR" , 1, 1 }, - { 0 , 0, 0 } -}; - -void CheckArgs( char * szFuncCall, int iArgs ) -{ - FUNCINFO * f = _StdFun; - int i = 0; - int iPos = -1; - int iCmp; - - while( f[ i ].cFuncName ) - { - iCmp = strncmp( szFuncCall, f[ i ].cFuncName, 4 ); - if( iCmp == 0 ) - iCmp = strncmp( szFuncCall, f[ i ].cFuncName, strlen( szFuncCall ) ); - if( iCmp == 0 ) - { - iPos = i; - break; - } - else - ++i; - } - - if( iPos >= 0 && ( f[ iPos ].iMinParam != -1 ) ) - { - if( iArgs < f[ iPos ].iMinParam || ( f[ iPos ].iMaxParam != -1 && iArgs > f[ iPos ].iMaxParam ) ) - { - char szMsg[ 40 ]; - - if( f[ iPos ].iMaxParam == -1 ) - sprintf( szMsg, "\nPassed: %i, expected: at least %i", iArgs, f[ iPos ].iMinParam ); - else if( f[ iPos ].iMinParam == f[ iPos ].iMaxParam ) - sprintf( szMsg, "\nPassed: %i, expected: %i", iArgs, f[ iPos ].iMinParam ); - else - sprintf( szMsg, "\nPassed: %i, expected: %i - %i", iArgs, f[ iPos ].iMinParam, f[ iPos ].iMaxParam ); - - GenError( _szCErrors, 'E', ERR_CHECKING_ARGS, szFuncCall, szMsg ); - - /* Clipper way */ - /* GenError( _szCErrors, 'E', ERR_CHECKING_ARGS, szFuncCall, NULL ); */ - } - } -} - -/* NOTE: Making the date and time info to fit into 32 bits can only be done - in a "lossy" way, in practice that means it's not possible to unpack - the exact date/time info from the resulting ULONG. Since the year - is only stored in 6 bits, 1980 will result in the same bit pattern - as 2044. The purpose of this value is only used to *differenciate* - between the dates ( the exact dates are not significant ), so this can - be used here without problems. */ - -/* 76543210765432107654321076543210 - |.......|.......|.......|....... - |____| Year 6 bits - |__| Month 4 bits - |___| Day 5 bits - |___| Hour 5 bits - |____| Minute 6 bits - |____| Second 6 bits */ - -static ULONG PackDateTime( void ) -{ - BYTE szString[ 4 ]; - BYTE nValue; - - time_t t; - struct tm * oTime; - - time( &t ); - oTime = localtime( &t ); - - nValue = ( BYTE ) ( ( ( oTime->tm_year + 1900 ) - 1980 ) & ( 2 ^ 6 ) ) ; /* 6 bits */ - szString[ 0 ] = nValue << 2; - nValue = ( BYTE ) ( oTime->tm_mon + 1 ); /* 4 bits */ - szString[ 0 ] |= nValue >> 2; - szString[ 1 ] = nValue << 6; - nValue = ( BYTE ) ( oTime->tm_mday ); /* 5 bits */ - szString[ 1 ] |= nValue << 1; - - nValue = ( BYTE ) oTime->tm_hour; /* 5 bits */ - szString[ 1 ] = nValue >> 4; - szString[ 2 ] = nValue << 4; - nValue = ( BYTE ) oTime->tm_min; /* 6 bits */ - szString[ 2 ] |= nValue >> 2; - szString[ 3 ] = nValue << 6; - nValue = ( BYTE ) oTime->tm_sec; /* 6 bits */ - szString[ 3 ] |= nValue; - - return HB_MKLONG( szString[ 3 ], szString[ 2 ], szString[ 1 ], szString[ 0 ] ); -} - -static BOOL SwitchCmp( char * szString, char * szSwitch ) -{ - if( IS_OPT_SEP( *szString ) ) - { - szString++; - - if( strlen( szString ) == strlen( szSwitch ) ) - { - while( *szString != '\0' ) - { - if( toupper( *szString ) != *szSwitch ) - return FALSE; - - szString++; - szSwitch++; - } - - return TRUE; - } - } - - return FALSE; -} diff --git a/harbour/source/debug/debugger.prg b/harbour/source/debug/debugger.prg index f8d1c4e6f4..02c77fecf9 100644 --- a/harbour/source/debug/debugger.prg +++ b/harbour/source/debug/debugger.prg @@ -793,7 +793,7 @@ METHOD ClosePopup( nPopup ) CLASS TDbMenu DispOutAt( 0, ::aItems[ nPopup ]:nCol,; StrTran( ::aItems[ nPopup ]:cPrompt, "~", "" ), ::cClrPopup ) - DispOutAt( 0, ::aItems[ nPopup ]:nCol + nAt := At( "~", ::aItems[ nPopup ]:cPrompt ) - 1,; + DispOutAt( 0, ::aItems[ nPopup ]:nCol + ( nAt := At( "~", ::aItems[ nPopup ]:cPrompt ) ) - 1,; SubStr( ::aItems[ nPopup ]:cPrompt, nAt + 2, 1 ), ::cClrHotKey ) endif // dispend() @@ -832,8 +832,8 @@ METHOD Display() CLASS TDbMenu DispOutAt( ::aItems[ n ]:nRow, ::aItems[ n ]:nCol,; StrTran( ::aItems[ n ]:cPrompt, "~", "" ) ) - DispOutAt( ::aItems[ n ]:nRow, ::aItems[ n ]:nCol + nAt := ; - At( "~", ::aItems[ n ]:cPrompt ) - 1 ,; + DispOutAt( ::aItems[ n ]:nRow, ::aItems[ n ]:nCol + ; + ( nAt := At( "~", ::aItems[ n ]:cPrompt ) ) - 1 ,; SubStr( ::aItems[ n ]:cPrompt, nAt + 2, 1 ), ::cClrHotKey ) endif next @@ -896,8 +896,8 @@ METHOD GoLeft() CLASS TDbMenu DispOutAt( oMenuItem:nRow, oMenuItem:nCol,; StrTran( oMenuItem:cPrompt, "~", "" ) ) - DispOutAt( oMenuItem:nRow, oMenuItem:nCol + nAt := ; - At( "~", oMenuItem:cPrompt ) - 1 ,; + DispOutAt( oMenuItem:nRow, oMenuItem:nCol + ; + ( nAt := At( "~", oMenuItem:cPrompt ) ) - 1 ,; SubStr( oMenuItem:cPrompt, nAt + 2, 1 ), ::cClrHotKey ) endif if ::nOpenPopup > 1 @@ -929,8 +929,8 @@ METHOD GoRight() CLASS TDbMenu DispOutAt( oMenuItem:nRow, oMenuItem:nCol ,; StrTran( oMenuItem:cPrompt, "~", "" ) ) - DispOutAt( oMenuItem:nRow, oMenuItem:nCol + nAt := ; - At( "~", oMenuItem:cPrompt ) - 1 ,; + DispOutAt( oMenuItem:nRow, oMenuItem:nCol + ; + ( nAt := At( "~", oMenuItem:cPrompt ) ) - 1 ,; SubStr( oMenuItem:cPrompt, nAt + 2, 1 ), ::cClrHotKey ) endif if ::nOpenPopup < Len( ::aItems ) @@ -968,15 +968,16 @@ METHOD ShowPopup( nPopup ) CLASS TDbMenu DispOutAt( 0, ::aItems[ nPopup ]:nCol ,; StrTran( ::aItems[ nPopup ]:cPrompt, "~", "" ), ::cClrHilite ) - DispOutAt( 0, ::aItems[ nPopup ]:nCol + nAt := At( "~", ::aItems[ nPopup ]:cPrompt ) - 1 ,; + DispOutAt( 0, ::aItems[ nPopup ]:nCol + ; + ( nAt := At( "~", ::aItems[ nPopup ]:cPrompt ) ) - 1 ,; SubStr( ::aItems[ nPopup ]:cPrompt, nAt + 2, 1 ), ::cClrHotFocus ) else oMenuItem = ::aItems[ nPopup ] DispOutAt( oMenuItem:nRow, oMenuItem:nCol ,; StrTran( oMenuItem:cPrompt, "~", "" ), ::cClrHilite ) - DispOutAt( oMenuItem:nRow, oMenuItem:nCol + nAt := ; - At( "~", oMenuItem:cPrompt ) - 1 ,; + DispOutAt( oMenuItem:nRow, oMenuItem:nCol + ; + ( nAt := At( "~", oMenuItem:cPrompt ) ) - 1 ,; SubStr( oMenuItem:cPrompt, nAt + 2, 1 ), ::cClrHotFocus ) endif @@ -1052,8 +1053,8 @@ METHOD Display( cClrText, cClrHotKey ) CLASS TDbMenuItem DispOutAt( ::nRow, ::nCol ,; StrTran( ::cPrompt, "~", "" ), cClrText ) - DispOutAt( ::nRow, ::nCol + nAt := ; - At( "~", ::cPrompt ) - 1 ,; + DispOutAt( ::nRow, ::nCol + ; + ( nAt := At( "~", ::cPrompt ) ) - 1 ,; SubStr( ::cPrompt, nAt + 2, 1 ), cClrHotKey ) return nil diff --git a/harbour/source/pp/hbpp.c b/harbour/source/pp/hbpp.c index 7eb0db2c7c..7c1b7ae588 100644 --- a/harbour/source/pp/hbpp.c +++ b/harbour/source/pp/hbpp.c @@ -184,7 +184,7 @@ int ParseDirective( char* sLine ) if ( i == 4 && memcmp ( sDirective, "ELSE", 4 ) == 0 ) { /* --- #else --- */ if ( nCondCompile == 0 ) - GenError( _szPErrors, 'P', ERR_DIRECTIVE_ELSE, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_DIRECTIVE_ELSE, NULL, NULL ); else if ( nCondCompile == 1 || aCondCompile[nCondCompile-2] ) aCondCompile[nCondCompile-1] = 1 - aCondCompile[nCondCompile-1]; } @@ -192,7 +192,7 @@ int ParseDirective( char* sLine ) else if ( i == 5 && memcmp ( sDirective, "ENDIF", 5 ) == 0 ) { /* --- #endif --- */ if ( nCondCompile == 0 ) - GenError( _szPErrors, 'P', ERR_DIRECTIVE_ENDIF, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_DIRECTIVE_ENDIF, NULL, NULL ); else nCondCompile--; } @@ -209,7 +209,7 @@ int ParseDirective( char* sLine ) char cDelimChar; if ( *sLine != '\"' && *sLine != '\'' && *sLine != '<' ) - GenError( _szPErrors, 'P', ERR_WRONG_NAME, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_WRONG_NAME, NULL, NULL ); cDelimChar = *sLine; if (cDelimChar == '<') @@ -218,12 +218,12 @@ int ParseDirective( char* sLine ) sLine++; i = 0; while ( *(sLine+i) != '\0' && *(sLine+i) != cDelimChar ) i++; if ( *(sLine+i) != cDelimChar ) - GenError( _szPErrors, 'P', ERR_WRONG_NAME, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_WRONG_NAME, NULL, NULL ); *(sLine+i) = '\0'; /* if ((handl_i = fopen(sLine, "r")) == NULL) */ - if ( !OpenInclude( sLine, _pIncludePath, &handl_i, (cDelimChar == '>'), szInclude ) ) - GenError( _szPErrors, 'P', ERR_CANNOT_OPEN, sLine, NULL ); + if ( !OpenInclude( sLine, hb_comp_pIncludePath, &handl_i, (cDelimChar == '>'), szInclude ) ) + hb_compGenError( _szPErrors, 'P', ERR_CANNOT_OPEN, sLine, NULL ); lInclude++; Hp_Parse(handl_i, 0, szInclude ); lInclude--; @@ -251,12 +251,12 @@ int ParseDirective( char* sLine ) else if ( i == 5 && memcmp ( sDirective, "ERROR", 5 ) == 0 ) /* --- #error --- */ - GenError( _szPErrors, 'P', ERR_EXPLICIT, sLine, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_EXPLICIT, sLine, NULL ); else if ( i == 4 && memcmp ( sDirective, "LINE", 4 ) == 0 ) return -1; else - GenError( _szPErrors, 'P', ERR_WRONG_DIRECTIVE, sDirective, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_WRONG_DIRECTIVE, sDirective, NULL ); } return 0; } @@ -295,7 +295,7 @@ int ParseDefine( char* sLine) lastdef->pars = ( npars <= 0 )? NULL : strodup ( pars ); } else - GenError( _szPErrors, 'P', ERR_DEFINE_ABSENT, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_DEFINE_ABSENT, NULL, NULL ); return 0; } @@ -360,7 +360,7 @@ int ParseIfdef( char* sLine, int usl) { NextWord( &sLine, defname, FALSE ); if ( *defname == '\0' ) - GenError( _szPErrors, 'P', ERR_DEFINE_ABSENT, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_DEFINE_ABSENT, NULL, NULL ); } if ( nCondCompile == maxCondCompile ) { @@ -463,7 +463,7 @@ void ParseCommand( char* sLine, int com_or_xcom, int com_or_tra ) if ( (ipos = pp_strAt( "=>", 2, sLine, strolen(sLine) )) > 0 ) stroncpy( mpatt, sLine, ipos-1 ); else - GenError( _szPErrors, 'P', ERR_COMMAND_DEFINITION, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_COMMAND_DEFINITION, NULL, NULL ); RemoveSlash( mpatt ); mlen = strotrim( mpatt ); @@ -530,13 +530,13 @@ void ConvertPatterns ( char *mpatt, int mlen, char *rpatt, int rlen ) { if ( *(exppatt+explen-1) == '*' ) explen--; else - GenError( _szPErrors, 'P', ERR_PATTERN_DEFINITION, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_PATTERN_DEFINITION, NULL, NULL ); } else if ( exptype == '4' ) { if ( *(exppatt+explen-1) == ')' ) explen--; else - GenError( _szPErrors, 'P', ERR_PATTERN_DEFINITION, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_PATTERN_DEFINITION, NULL, NULL ); } rmlen = i - ipos + 1; /* Convert match marker into inner format */ @@ -751,7 +751,7 @@ int ParseExpression( char* sLine, char* sOutLine ) while ( ipos != 0 ); kolpass++; if( kolpass > 20 && rezDef ) - GenError( _szPErrors, 'P', ERR_RECURSE, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_RECURSE, NULL, NULL ); } while ( rezDef || rezTra || rezCom ); @@ -2291,7 +2291,7 @@ BOOL OpenInclude( char * szFileName, PATHNAMES *pSearch, FILE** fptr, BOOL bStan else { pFileName = hb_fsFNameSplit( szFileName ); - pFileName->szPath = _pFileName->szPath; + pFileName->szPath = hb_comp_pFileName->szPath; hb_fsFNameMerge( szInclude, pFileName ); *fptr = fopen( szInclude, "r" ); hb_xfree( pFileName ); diff --git a/harbour/source/pp/hbppint.c b/harbour/source/pp/hbppint.c index ef9cb3a974..9bd8726895 100644 --- a/harbour/source/pp/hbppint.c +++ b/harbour/source/pp/hbppint.c @@ -195,7 +195,7 @@ int Hp_Parse( FILE * handl_i, FILE * handl_o, char * szSource ) else { sprintf( szLine, "%d", iLine ); - GenWarning( _szPWarnings, 'I', WARN_NONDIRECTIVE, szSource, szLine ); + hb_compGenWarning( _szPWarnings, 'I', WARN_NONDIRECTIVE, szSource, szLine ); } } } diff --git a/harbour/source/pp/hbpplib.c b/harbour/source/pp/hbpplib.c index f32ae96ec0..358a7a769c 100644 --- a/harbour/source/pp/hbpplib.c +++ b/harbour/source/pp/hbpplib.c @@ -50,8 +50,8 @@ #include "itemapi.h" #include "hberrors.h" -PATHNAMES * _pIncludePath = NULL; -PHB_FNAME _pFileName = NULL; +PATHNAMES * hb_comp_pIncludePath = NULL; +PHB_FNAME hb_comp_pFileName = NULL; jmp_buf s_env; @@ -103,7 +103,7 @@ HARBOUR HB___PREPROCESS( void ) hb_retc( "" ); } -void GenError( char * _szErrors[], char cPrefix, int iError, char * szError1, char * szError2 ) +void hb_compGenError( char * _szErrors[], char cPrefix, int iError, char * szError1, char * szError2 ) { HB_TRACE(HB_TR_DEBUG, ("GenError(%p, %c, %d, %s, %s)", _szErrors, cPrefix, iError, szError1, szError2)); @@ -118,7 +118,7 @@ void GenError( char * _szErrors[], char cPrefix, int iError, char * szError1, ch longjmp( s_env, iError ); } -void GenWarning( char* _szWarnings[], char cPrefix, int iWarning, char * szWarning1, char * szWarning2) +void hb_compGenWarning( char* _szWarnings[], char cPrefix, int iWarning, char * szWarning1, char * szWarning2) { HB_TRACE(HB_TR_DEBUG, ("GenWarning(%p, %c, %d, %s, %s)", _szWarnings, cPrefix, iWarning, szWarning1, szWarning2)); diff --git a/harbour/source/pp/stdalone/hbpp.c b/harbour/source/pp/stdalone/hbpp.c index c57c8eb00f..831fa5cfd8 100644 --- a/harbour/source/pp/stdalone/hbpp.c +++ b/harbour/source/pp/stdalone/hbpp.c @@ -68,8 +68,8 @@ void AddSearchPath( char *, PATHNAMES * * ); /* add pathname to a search list */ char sLine[ STR_SIZE ], sOutLine[ STR_SIZE ]; -PATHNAMES *_pIncludePath = NULL; -PHB_FNAME _pFileName = NULL; +PATHNAMES *hb_comp_pIncludePath = NULL; +PHB_FNAME hb_comp_pFileName = NULL; int _iWarnings = 0; int main( int argc, char * argv[] ) @@ -115,7 +115,7 @@ int main( int argc, char * argv[] ) break; case 'i': case 'I': - AddSearchPath( argv[ iArg ]+2, &_pIncludePath ); + AddSearchPath( argv[ iArg ]+2, &hb_comp_pIncludePath ); break; case 'o': case 'O': @@ -140,15 +140,15 @@ int main( int argc, char * argv[] ) break; } } - else _pFileName = hb_fsFNameSplit( argv[ iArg ] ); + else hb_comp_pFileName = hb_fsFNameSplit( argv[ iArg ] ); iArg++; } - if( _pFileName ) + if( hb_comp_pFileName ) { - if( ! _pFileName->szExtension ) - _pFileName->szExtension =".prg"; + if( ! hb_comp_pFileName->szExtension ) + hb_comp_pFileName->szExtension =".prg"; - hb_fsFNameMerge( szFileName, _pFileName ); + hb_fsFNameMerge( szFileName, hb_comp_pFileName ); if( ( handl_i = fopen( szFileName, "r" ) ) == NULL ) { @@ -176,8 +176,8 @@ int main( int argc, char * argv[] ) return 1; } - _pFileName->szExtension = ".ppo"; - hb_fsFNameMerge( szFileName, _pFileName ); + hb_comp_pFileName->szExtension = ".ppo"; + hb_fsFNameMerge( szFileName, hb_comp_pFileName ); if( ( handl_o = fopen( szFileName, "wt" ) ) == NULL ) { @@ -197,10 +197,10 @@ int main( int argc, char * argv[] ) while( ( pDelim = strchr( pPath, OS_PATH_LIST_SEPARATOR ) ) != NULL ) { *pDelim = '\0'; - AddSearchPath( pPath, &_pIncludePath ); + AddSearchPath( pPath, &hb_comp_pIncludePath ); pPath = pDelim + 1; } - AddSearchPath( pPath, &_pIncludePath ); + AddSearchPath( pPath, &hb_comp_pIncludePath ); } } @@ -460,9 +460,9 @@ void AddSearchPath( char * szPath, PATHNAMES * * pSearchList ) pPath->szPath = szPath; } -void GenError( char * _szErrors[], char cPrefix, int iError, char * szError1, char * szError2 ) +void hb_compGenError( char * _szErrors[], char cPrefix, int iError, char * szError1, char * szError2 ) { - HB_TRACE(HB_TR_DEBUG, ("GenError(%p, %c, %d, %s, %s)", _szErrors, cPrefix, iError, szError1, szError2)); + HB_TRACE(HB_TR_DEBUG, ("hb_compGenError(%p, %c, %d, %s, %s)", _szErrors, cPrefix, iError, szError1, szError2)); printf( "\r(%i) ", nline ); printf( "Error %c%04i ", cPrefix, iError ); @@ -472,9 +472,9 @@ void GenError( char * _szErrors[], char cPrefix, int iError, char * szError1, ch exit( EXIT_FAILURE ); } -void GenWarning( char* _szWarnings[], char cPrefix, int iWarning, char * szWarning1, char * szWarning2) +void hb_compGenWarning( char* _szWarnings[], char cPrefix, int iWarning, char * szWarning1, char * szWarning2) { - HB_TRACE(HB_TR_DEBUG, ("GenWarning(%p, %c, %d, %s, %s)", _szWarnings, cPrefix, iWarning, szWarning1, szWarning2)); + HB_TRACE(HB_TR_DEBUG, ("hb_compGenWarning(%p, %c, %d, %s, %s)", _szWarnings, cPrefix, iWarning, szWarning1, szWarning2)); if( _iWarnings ) { @@ -654,7 +654,7 @@ void * hb_xgrab( ULONG ulSize ) /* allocates fixed memory, exits on fail HB_TRACE(HB_TR_DEBUG, ("hb_xgrab(%lu)", ulSize)); if( ! pMem ) - GenError( _szPErrors, 'P', ERR_PPMEMALLOC, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_PPMEMALLOC, NULL, NULL ); return pMem; } @@ -666,7 +666,7 @@ void * hb_xrealloc( void * pMem, ULONG ulSize ) /* reallocates memory */ HB_TRACE(HB_TR_DEBUG, ("hb_xrealloc(%p, %lu)", pMem, ulSize)); if( ! pResult ) - GenError( _szPErrors, 'P', ERR_PPMEMREALLOC, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_PPMEMREALLOC, NULL, NULL ); return pResult; } @@ -678,5 +678,5 @@ void hb_xfree( void * pMem ) /* frees fixed memory */ if( pMem ) free( pMem ); else - GenError( _szPErrors, 'P', ERR_PPMEMFREE, NULL, NULL ); + hb_compGenError( _szPErrors, 'P', ERR_PPMEMFREE, NULL, NULL ); } diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 6f238498b9..d8db6b2f54 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -106,8 +106,8 @@ static void hb_vmAnd( void ); /* performs the logical AND on the static void hb_vmOr( void ); /* performs the logical OR on the latest two values, removes them and leaves result on the stack */ /* Array */ -static void hb_vmArrayAt( void ); /* pushes an array element to the stack, removing the array and the index from the stack */ -static void hb_vmArrayPut( void ); /* sets an array value and pushes the value on to the stack */ +static void hb_vmArrayPush( void ); /* pushes an array element to the stack, removing the array and the index from the stack */ +static void hb_vmArrayPop( void ); /* pops a value from the stack */ static void hb_vmArrayDim( USHORT uiDimensions ); /* generates an uiDimensions Array and initialize those dimensions from the stack values */ static void hb_vmArrayGen( ULONG ulElements ); /* generates an ulElements Array and fills it from the stack values */ static void hb_vmArrayNew( HB_ITEM_PTR, USHORT ); /* creates array */ @@ -479,13 +479,13 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) /* Array */ - case HB_P_ARRAYAT: - hb_vmArrayAt(); + case HB_P_ARRAYPUSH: + hb_vmArrayPush(); w++; break; - case HB_P_ARRAYPUT: - hb_vmArrayPut(); + case HB_P_ARRAYPOP: + hb_vmArrayPop(); w++; break; @@ -1816,41 +1816,41 @@ static void hb_vmInstring( void ) } } +/* At this moment the eval stack should store: + * -3 -> + * -2 -> + * -1 -> + */ static void hb_vmForTest( void ) /* Test to check the end point of the FOR */ { - int iDec; - double dStep; - BOOL bEqual; - HB_TRACE(HB_TR_DEBUG, ("hb_vmForTest()")); - - while( ! IS_NUMERIC( hb_stack.pPos - 1 ) ) + + if( IS_NUMERIC( hb_stack.pPos - 1 ) ) { - PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1073, NULL, "<" ); + int iDec; + double dCurrent, dEnd, dStep; - if( pResult ) + dEnd = hb_vmPopDouble( &iDec ); + if( IS_NUMERIC( hb_stack.pPos - 1 ) ) { - hb_stackPop(); - hb_vmPush( pResult ); - hb_itemRelease( pResult ); + dCurrent = hb_vmPopDouble( &iDec ); + if( IS_NUMERIC( hb_stack.pPos - 1 ) ) + { + dStep = hb_vmPopDouble( &iDec ); + + if( dStep > 0 ) /* Positive loop. Use LESS */ + hb_vmPushLogical( dCurrent <= dEnd ); + else if( dStep < 0 ) /* Negative loop. Use GREATER */ + hb_vmPushLogical( dCurrent >= dEnd ); + } + else + hb_errRT_BASE( EG_ARG, 1073, NULL, "<" ); } else - /* NOTE: Return from the inside. */ - return; + hb_errRT_BASE( EG_ARG, 1073, NULL, "<" ); } - - dStep = hb_vmPopDouble( &iDec ); - - /* NOTE: step of zero will cause endless loop, as in Clipper */ - - if( dStep > 0 ) /* Positive loop. Use LESS */ - hb_vmLess(); - else if( dStep < 0 ) /* Negative loop. Use GREATER */ - hb_vmGreater(); - - bEqual = hb_vmPopLogical(); /* Logical should be on top of stack */ - hb_vmPushNumber( dStep, iDec ); /* Push the step expression back on the stack */ - hb_vmPushLogical( bEqual ); + else + hb_errRT_BASE( EG_ARG, 1073, NULL, "<" ); } /* ------------------------------- */ @@ -1958,7 +1958,7 @@ static void hb_vmOr( void ) /* Array */ /* ------------------------------- */ -static void hb_vmArrayAt( void ) +static void hb_vmArrayPush( void ) { PHB_ITEM pIndex; PHB_ITEM pArray; @@ -2006,7 +2006,7 @@ static void hb_vmArrayAt( void ) } } -static void hb_vmArrayPut( void ) +static void hb_vmArrayPop( void ) { PHB_ITEM pValue; PHB_ITEM pIndex; @@ -2015,9 +2015,9 @@ static void hb_vmArrayPut( void ) HB_TRACE(HB_TR_DEBUG, ("hb_vmArrayPut()")); - pValue = hb_stack.pPos - 1; - pIndex = hb_stack.pPos - 2; - pArray = hb_stack.pPos - 3; + pValue = hb_stack.pPos - 3; + pArray = hb_stack.pPos - 2; + pIndex = hb_stack.pPos - 1; if( IS_INTEGER( pIndex ) ) ulIndex = pIndex->item.asInteger.value; @@ -2040,6 +2040,7 @@ static void hb_vmArrayPut( void ) hb_itemCopy( pArray, pValue ); /* places pValue at pArray position */ hb_stackPop(); hb_stackPop(); + hb_stackPop(); /* remove the value from the stack just like other POP operations */ } } @@ -2346,7 +2347,7 @@ void hb_vmDo( USHORT uiParams ) if( pSelfBase->uiPrevCls ) /* Is is a Super cast ? */ { pSelfBase->uiClass = pSelfBase->uiPrevCls; - pSelfBase->uiPrevCls = NULL; + pSelfBase->uiPrevCls = 0; } } }