From 7a9444924f10af35797a069a2ca2eaa558c479e7 Mon Sep 17 00:00:00 2001 From: Ryszard Glab Date: Thu, 9 Dec 1999 16:15:00 +0000 Subject: [PATCH] ChangeLog 19991209-17:10 --- harbour/ChangeLog | 98 ++++ harbour/config/rules.cf | 4 +- harbour/include/compiler.h | 198 ++----- harbour/include/ctoharb.h | 1 + harbour/include/expropt.h | 218 +++++++ harbour/include/extend.h | 7 + harbour/include/hberrors.h | 2 + harbour/include/macro.h | 105 ++++ harbour/include/pcode.h | 19 + harbour/samples/cccppc/Makefile | 2 + harbour/samples/guestbk/Makefile | 2 + harbour/samples/hscript/Makefile | 2 + harbour/samples/misc/Makefile | 2 + harbour/samples/pe/Makefile | 2 + harbour/source/Makefile | 1 + harbour/source/common/Makefile | 1 + harbour/source/compiler/cmdcheck.c | 2 +- harbour/source/compiler/expropt.c | 686 ++++++++++++++++++---- harbour/source/compiler/genc.c | 30 + harbour/source/compiler/genhrb.c | 6 + harbour/source/compiler/genjava.c | 6 + harbour/source/compiler/harbour.c | 627 +++++++++++---------- harbour/source/compiler/harbour.l | 61 +- harbour/source/compiler/harbour.y | 136 ++--- harbour/source/compiler/hbgenerr.c | 2 + harbour/source/macro/Makefile | 40 ++ harbour/source/macro/macro.c | 669 ++++++++++++++++++++++ harbour/source/macro/macro.l | 496 ++++++++++++++++ harbour/source/macro/macro.y | 721 ++++++++++++++++++++++++ harbour/source/runner/stdalone/Makefile | 1 + harbour/source/vm/hvm.c | 219 +++++-- harbour/tests/Makefile | 11 +- harbour/tests/regress/Makefile | 1 + harbour/tests/tstmacro.prg | 2 +- 34 files changed, 3721 insertions(+), 659 deletions(-) create mode 100644 harbour/include/expropt.h create mode 100644 harbour/include/macro.h create mode 100644 harbour/source/macro/Makefile create mode 100644 harbour/source/macro/macro.c create mode 100644 harbour/source/macro/macro.l create mode 100644 harbour/source/macro/macro.y diff --git a/harbour/ChangeLog b/harbour/ChangeLog index f03b69020a..fe040a509e 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,101 @@ +19991209-17:10 GMT+1 Ryszard Glab + + *config/rules.cf + * YACC_FLAGS and LEX_FLAGS can be set in local Makefile - this + local settings will be added to the global ones + + * include/compiler.h + * include/expropt.h + * moved declarations related to expression optimizer into expropt.h + which is used also at runtime library + * added support for macro generation + + *source/compiler/harbour.c + * removed some functions that were no longer used + * fixed recognition of static and memvar variables for which + function-wide declaration owerwrites file-wide declaration + e.g. + STATIC myvar + FUNCTION MyTest() + MEMVAR myvar + + *source/compiler/genc.c + *source/compiler/genhrb.c + *source/compiler/genjava.c + * updated to support new macro related opcodes + + * include/hberrors.h + * source/compiler/hbgenerr.c + * added new errors + ERR_BAD_MACRO (declared variable in macro) + ERR_INVALID_SEND (macro operator with send operator) + + *source/compiler/harbour.l + * '.' character is correctly passed to grammar analyzer + * moved here all rules for a macro variable use recognition + + *source/common/Makefile + *source/common/reserved.c + * file with function and date used to check for reserved + functions name + +NOTE: All non GNU-Make scripts should be updated! + + * include/ctoharb.h + * added declaration of hb_stackPop() function + + *source/vm/hvm.c + * changed visibility of hb_stackPop() function (static -> global) + * added code related to macro generation and evaluation + + *source/macro/ + *source/macro/macro.c + *source/macro/macro.l + *source/macro/macro.y + *source/macro/Makefile + *include/macro.h + * new files used for macro generation and evaluation + * macro compiler supports now: + + macro variables: &var1 := &var2 + * not supported yet (there is a proper pcode generated only - + there are no actions in the virtual machine) + - text substitution: "text ¯o" + - function calls: ¯o() + - aliased macro variables: ¯o->var and alias->&var + - macro-compiled codeblocks + +NOTE: All non GNU-Make scripts should be updated! + +NOTE: source/macro/macro.c file includes source/compiler/expropt.c + I didn't found other method of reusing the expropt.c. Unfortunately + the code in expropt.c differs a little if used from macro compiler + (it uses a local variable that holds the compilation state instead + of global variables) + + *source/compiler/expropt.c + * added support for macro pcode generation and macro compilation + NOTE: this file is included by macro.c + + *include/pcode.h + * added pcodes used in macro generation and macro evaluation + + *source/runner/stdalone/Makefile + *tests/Makefile + *tests/regress/Makefile + *samples/cccppc/Makefile + *samples/guestbk/Makefile + *samples/hscript/Makefile + *samples/misc/Makefile + *samples/pe/Makefile + * 'macro' library added + + *source/compiler/cmdcheck.c + * replaced strupr with hb_strupr + +NOTE: All PRG sources HAVE TO be recompiled!!! + +NOTE: Add macro.lib to all non-GNU make scripts or batch files. + 19991209-01:05 GMT+1 Victor Szel * source/compiler/* include/compiler.h diff --git a/harbour/config/rules.cf b/harbour/config/rules.cf index 7897922bff..ef07b5ea6a 100644 --- a/harbour/config/rules.cf +++ b/harbour/config/rules.cf @@ -4,11 +4,11 @@ # How to run yacc. YACC = bison -YACC_FLAGS = -d +YACC_FLAGS := -d $(YACC_FLAGS) # How to run lex. LEX = flex -LEX_FLAGS = -i -8 +LEX_FLAGS := -i -8 $(LEX_FLAGS) # # How to run Harbour. diff --git a/harbour/include/compiler.h b/harbour/include/compiler.h index 77160fd3e3..91c595f0ab 100644 --- a/harbour/include/compiler.h +++ b/harbour/include/compiler.h @@ -48,6 +48,7 @@ #include "hberrors.h" #include "hbpp.h" #include "hbver.h" +#include "expropt.h" /* compiler related declarations */ @@ -138,60 +139,6 @@ typedef struct int iCount; /* number of defined symbols */ } SYMBOLS; -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; - - #define VS_LOCAL 1 #define VS_STATIC 2 #define VS_FIELD 4 @@ -210,7 +157,6 @@ typedef struct HB_EXPR_ #define FUN_USES_LOCAL_PARAMS 16 /* parameters are declared using () */ #define FUN_WITH_RETURN 32 /* there was RETURN statement in previous line */ - extern void hb_compFunctionAdd( char * szFunName, HB_SYMBOLSCOPE cScope, int iType ); /* starts a new Clipper language function definition */ extern PFUNCTION hb_compFunctionFind( char * szFunName ); /* locates a previously defined function */ extern USHORT hb_compFunctionGetPos( char * szSymbolName ); /* returns the index + 1 of a function on the functions defined list */ @@ -234,11 +180,57 @@ extern void hb_compGenBreak( void ); /* generate code for BREAK statement */ extern void hb_compExternGen( void ); /* generates the symbols for the EXTERN names */ extern void hb_compExternAdd( char * szExternName ); /* defines a new extern name */ -extern ULONG hb_compGenJump( LONG lOffset ); /* generates the pcode to jump to a specific offset */ -extern ULONG hb_compGenJumpFalse( LONG lOffset ); /* generates the pcode to jump if false */ -extern ULONG hb_compGenJumpTrue( LONG lOffset ); /* generates the pcode to jump if true */ -extern void hb_compGenJumpHere( ULONG ulOffset ); /* returns the pcode pos where to set a jump offset */ -extern void hb_compGenJumpThere( ULONG ulFrom, ULONG ulTo ); /* sets a jump offset */ +#ifdef HB_MACRO_SUPPORT + +extern BOOL hb_compVariableMacroCheck( char *, HB_MACRO_DECL ); /* checks if passed variable can be used in macro */ + +extern ULONG hb_compGenJump( LONG, HB_MACRO_DECL ); /* generates the pcode to jump to a specific offset */ +extern ULONG hb_compGenJumpFalse( LONG, HB_MACRO_DECL ); /* generates the pcode to jump if false */ +extern ULONG hb_compGenJumpTrue( LONG, HB_MACRO_DECL ); /* generates the pcode to jump if true */ +extern void hb_compGenJumpHere( ULONG, HB_MACRO_DECL ); /* returns the pcode pos where to set a jump offset */ +extern void hb_compGenJumpThere( ULONG, ULONG, HB_MACRO_DECL ); /* sets a jump offset */ + +extern void hb_compGenMessage( char *, HB_MACRO_DECL ); /* sends a message to an object */ +extern void hb_compGenMessageData( char *, HB_MACRO_DECL ); /* generates an underscore-symbol name for a data assignment */ +extern void hb_compGenPopVar( char *, HB_MACRO_DECL ); /* generates the pcode to pop a value from the virtual machine stack onto a variable */ +extern void hb_compGenPushDouble( double , BYTE, HB_MACRO_DECL ); /* Pushes a number on the virtual machine stack */ +extern void hb_compGenPushFunCall( char *, HB_MACRO_DECL ); /* generates the pcode to push function's call */ +extern void hb_compGenPushVar( char *, HB_MACRO_DECL ); /* generates the pcode to push a variable value to the virtual machine stack */ +extern void hb_compGenPushVarRef( char *, HB_MACRO_DECL ); /* generates the pcode to push a variable by reference to the virtual machine stack */ +extern void hb_compGenPushLogical( int, HB_MACRO_DECL ); /* pushes a logical value on the virtual machine stack */ +extern void hb_compGenPushLong( long, HB_MACRO_DECL ); /* Pushes a long number on the virtual machine stack */ +extern void hb_compGenPushNil( HB_MACRO_DECL ); /* Pushes nil on the virtual machine stack */ +extern void hb_compGenPushString( char *, ULONG, HB_MACRO_DECL ); /* Pushes a string on the virtual machine stack */ +extern void hb_compGenPushSymbol( char *, int, HB_MACRO_DECL ); /* Pushes a symbol on to the Virtual machine stack */ +extern void hb_compGenPushAliasedVar( char *, BOOL, char *, long, HB_MACRO_DECL ); +extern void hb_compGenPopAliasedVar( char *, BOOL, char *, long, HB_MACRO_DECL ); +extern void hb_compGenPushFunRef( char *, HB_MACRO_DECL ); +extern void hb_compGenPCode1( BYTE, HB_MACRO_DECL ); /* generates 1 byte of pcode */ +extern void hb_compGenPCode3( BYTE, BYTE, BYTE, HB_MACRO_DECL ); /* generates 3 bytes of pcode */ +extern void hb_compGenPCodeN( BYTE * pBuffer, ULONG ulSize, HB_MACRO_DECL ); /* copy bytes to a pcode buffer */ + +/* Codeblocks */ +void hb_compCodeBlockStart( HB_MACRO_DECL ); /* starts a codeblock creation */ +void hb_compCodeBlockEnd( HB_MACRO_DECL ); /* end of codeblock creation */ + +#define hb_compErrorType( p ) hb_macroError( EG_ARG, HB_MACRO_PARAM ) +#define hb_compErrorIndex( p ) hb_macroError( EG_BOUND, HB_MACRO_PARAM ) +#define hb_compErrorSyntax( p ) hb_macroError( EG_SYNTAX, HB_MACRO_PARAM ) +#define hb_compErrorLValue( p ) hb_macroError( EG_SYNTAX, HB_MACRO_PARAM ) +#define hb_compErrorBound( p ) hb_macroError( EG_BOUND, HB_MACRO_PARAM ) +#define hb_compErrorAlias( p ) hb_macroError( EG_NOALIAS, HB_MACRO_PARAM ) +#define hb_compErrorDuplVar( c ) hb_macroError( EG_SYNTAX, HB_MACRO_PARAM ) +#define hb_compWarnMeaningless( p ) + +#else /* HB_MACRO_SUPPORT */ + +extern BOOL hb_compVariableMacroCheck( char * ); /* checks if passed variable can be used in macro */ + +extern ULONG hb_compGenJump( LONG ); /* generates the pcode to jump to a specific offset */ +extern ULONG hb_compGenJumpFalse( LONG ); /* generates the pcode to jump if false */ +extern ULONG hb_compGenJumpTrue( LONG ); /* generates the pcode to jump if true */ +extern void hb_compGenJumpHere( ULONG ); /* returns the pcode pos where to set a jump offset */ +extern void hb_compGenJumpThere( ULONG, ULONG ); /* sets a jump offset */ extern void hb_compLinePush( void ); /* generates the pcode with the currently compiled source code line */ @@ -265,14 +257,14 @@ extern void hb_compGenPCode1( BYTE ); /* generates 1 byte of pcode * extern void hb_compGenPCode3( BYTE, BYTE, BYTE ); /* generates 3 bytes of pcode */ extern void hb_compGenPCodeN( BYTE * pBuffer, ULONG ulSize ); /* copy bytes to a pcode buffer */ -/* Codeblocks */ -extern void hb_compCodeBlockStart( void ); /* starts a codeblock creation */ -extern void hb_compCodeBlockEnd( void ); /* end of codeblock creation */ - extern ULONG hb_compSequenceBegin( void ); extern ULONG hb_compSequenceEnd( void ); extern void hb_compSequenceFinish( ULONG, int ); +/* Codeblocks */ +void hb_compCodeBlockStart( void ); /* starts a codeblock creation */ +void hb_compCodeBlockEnd( void ); /* end of codeblock creation */ + /* support for FIELD declaration */ extern void hb_compFieldSetAlias( char *, int ); extern int hb_compFieldsCount( void ); @@ -291,9 +283,6 @@ HB_EXPR_PTR hb_compErrorAlias( HB_EXPR_PTR ); extern void hb_compErrorDuplVar( char * ); HB_EXPR_PTR hb_compWarnMeaningless( HB_EXPR_PTR ); -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); - extern void hb_compChkCompilerSwitch( int, char * Args[] ); extern void hb_compChkEnvironVar( char * ); extern void hb_compChkCompileFileName( int, char * Args[] ); @@ -303,6 +292,11 @@ extern void hb_compPrintUsage( char * ); extern void hb_compPrintCredits( void ); extern void hb_compPrintLogo( void ); +#endif /* HB_MACRO_SUPPORT */ + +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); + /* variable used by compiler */ extern int hb_comp_iLine; @@ -355,75 +349,5 @@ extern char * hb_comp_szWarnings[]; #define HB_EXITLEVEL_SETEXIT 1 #define HB_EXITLEVEL_DELTARGET 2 - -HB_EXPR_PTR hb_compExprNewEmpty( void ); -HB_EXPR_PTR hb_compExprNewNil( void ); -HB_EXPR_PTR hb_compExprNewDouble( double, BYTE ); -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_compExprEqual( 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 ); -extern ULONG hb_compExprListLen( HB_EXPR_PTR ); -extern void hb_compExprDelete( HB_EXPR_PTR ); -extern void hb_compExprClear( HB_EXPR_PTR ); -extern 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/ctoharb.h b/harbour/include/ctoharb.h index c4a140aa56..51a330ab8d 100644 --- a/harbour/include/ctoharb.h +++ b/harbour/include/ctoharb.h @@ -81,5 +81,6 @@ extern void hb_vmPushSymbol( PHB_SYMB pSym ); /* pushes a function pointer on /* stack management functions */ extern void hb_stackDispCall( void ); +extern void hb_stackPop( void ); /* pops an item from the stack */ #endif /* HB_CTOHARB_H_ */ diff --git a/harbour/include/expropt.h b/harbour/include/expropt.h new file mode 100644 index 0000000000..b42f6be3c6 --- /dev/null +++ b/harbour/include/expropt.h @@ -0,0 +1,218 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Header file for the Harbour Compiler + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +#ifndef HB_EXPROPT_H_ +#define HB_EXPROPT_H_ + +/* This structure holds local variables declared in a codeblock + */ +typedef struct HB_CBVAR_ +{ + char * szName; + BYTE bType; + struct HB_CBVAR_ * pNext; +} HB_CBVAR, *HB_CBVAR_PTR; + + +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 + { + unsigned char cMacroOp; /* macro operator */ + unsigned char SubType; /* context in which macro is used */ + char * szMacro; /* identifier after the macro operator */ + struct HB_EXPR_ *pExprList; /* list elements if &(...) was used */ + } asMacro; + struct + { + struct HB_EXPR_ *pExprList; /* list elements */ + struct HB_EXPR_ *pIndex; /* array index, others */ + } asList; + struct + { + struct HB_EXPR_ *pAlias; /* alias expression */ + struct HB_EXPR_ *pVar; /* aliased variable or macro */ + struct HB_EXPR_ *pExpList; /* aliased expression list */ + } asAlias; + struct + { + struct HB_EXPR_ *pFunName; /* 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; + +/* Definitions of function templates used in expression's message + * handling + */ + +#ifdef HB_MACRO_SUPPORT +/* Compilation for macro compiler + */ +#define HB_EXPR_FUNC( proc ) HB_EXPR_PTR proc( HB_EXPR_PTR pSelf, int iMessage, void * pMacro ) +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), pMacro ) + +typedef HB_EXPR_PTR HB_EXPR_ACTION( HB_EXPR_PTR pSelf, int iMessage, void * pMacro ); + +#else + +#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 ); + +#endif + + +HB_EXPR_PTR hb_compExprNewEmpty( void ); +HB_EXPR_PTR hb_compExprNewNil( void ); +HB_EXPR_PTR hb_compExprNewDouble( double, BYTE ); +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_compExprNewVar( char * ); +HB_EXPR_PTR hb_compExprNewAliasVar( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewAliasExpr( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprNewMacro( HB_EXPR_PTR, unsigned char, char * ); +HB_EXPR_PTR hb_compExprNewSymbol( char * ); +HB_EXPR_PTR hb_compExprNewAlias( 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_compExprNewVarRef( char * ); +HB_EXPR_PTR hb_compExprNewFunRef( char * ); +HB_EXPR_PTR hb_compExprNewCodeblockExpr( HB_EXPR_PTR, 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_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_compExprEqual( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprAssignStatic( HB_EXPR_PTR, HB_EXPR_PTR ); +ULONG hb_compExprListLen( HB_EXPR_PTR ); +void hb_compExprClear( HB_EXPR_PTR ); +char * hb_compExprDescription( HB_EXPR_PTR ); + +#ifdef HB_MACRO_SUPPORT + +HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR, HB_EXPR_PTR, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR, HB_EXPR_PTR, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR, HB_EXPR_PTR, HB_MACRO_DECL ); +void hb_compExprDelete( HB_EXPR_PTR, HB_MACRO_DECL ); +HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR, char *, HB_MACRO_DECL ); + +#else + +HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR, HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprSetOperand( 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 ); +HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR, HB_EXPR_PTR ); +void hb_compExprDelete( HB_EXPR_PTR ); +HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR, char *, BYTE ); + +#endif + +#endif /* HB_EXPROPT_H_ */ diff --git a/harbour/include/extend.h b/harbour/include/extend.h index a521e5b159..66e3f10637 100644 --- a/harbour/include/extend.h +++ b/harbour/include/extend.h @@ -412,6 +412,13 @@ extern USHORT hb_setCursor( BOOL bSetCursor, USHORT usNewCursor ); extern void hb_tone( double dFrequency, double dDuration ); extern char * hb_setColor( char * ); +/* compiler and macro compiler */ +extern char * hb_compReservedName( char * ); + +/* macro compiler */ +extern void hb_macroGetValue( HB_ITEM_PTR, PHB_SYMB ); +extern void hb_macroSetValue( HB_ITEM_PTR, PHB_SYMB ); + /* misc */ extern char * hb_version( USHORT uiMode ); diff --git a/harbour/include/hberrors.h b/harbour/include/hberrors.h index 55aad66d8d..88293f99fb 100644 --- a/harbour/include/hberrors.h +++ b/harbour/include/hberrors.h @@ -80,6 +80,8 @@ #define ERR_INVALID_ALIAS 39 #define ERR_INVALID_INDEX 40 #define ERR_INVALID_BOUND 41 +#define ERR_BAD_MACRO 42 +#define ERR_INVALID_SEND 43 #define WARN_AMBIGUOUS_VAR 1 #define WARN_MEMVAR_ASSUMED 2 diff --git a/harbour/include/macro.h b/harbour/include/macro.h new file mode 100644 index 0000000000..cb85fa0428 --- /dev/null +++ b/harbour/include/macro.h @@ -0,0 +1,105 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Header file for the Macro compiler + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +#ifndef HB_MACRO_H_ +#define HB_MACRO_H_ + +#include +#include +#include +#include +#include +#include + +/* Standard parameters passed to macro aware functions + */ +#define HB_MACRO_DECL void * pMacro +#define HB_MACRO_PARAM pMacro + +#include "hbsetup.h" +#include "extend.h" +#include "ctoharb.h" +#include "pcode.h" /* pcode values */ +#include "itemapi.h" +#include "errorapi.h" +#include "expropt.h" + +typedef struct HB_PCODE_INFO_ +{ + BYTE * pCode; /* pointer to a memory block where pcode is stored */ + ULONG lPCodeSize; /* total memory size for pcode */ + ULONG lPCodePos; /* actual pcode offset */ + struct HB_PCODE_INFO_ *pPrev; + HB_CBVAR_PTR pLocals; +} HB_PCODE_INFO, * HB_PCODE_INFO_PTR; + +typedef struct HB_MACRO_ +{ + char * string; /* compiled string */ + ULONG length; /* length of the string */ + ULONG pos; /* current position inside of compiled string */ + int Flags; /* some flags we may need */ + int status; /* status of compilation */ + HB_PCODE_INFO_PTR pCodeInfo; /* pointer to pcode buffer and info */ + void * pParseInfo; /* data needed by the parser - it should be 'void *' to allow different implementation of macr compiler */ + BOOL bName10; /* are we limiting identifier names to 10 chars ? */ + BOOL bShortCuts; /* are we using logical shorcuts (in OR/AND) */ + PHB_SYMB pSymbols; /* local symbol table */ +} HB_MACRO, * HB_MACRO_PTR; + +#define HB_MACRO_OK 0 /* macro compiled successfully */ +#define HB_MACRO_FAILURE 1 /* syntax error */ +#define HB_MACRO_TOO_COMPLEX 2 /* compiled expression is too complex */ + + +/* Global functions + */ +void hb_macroError( int, HB_MACRO_DECL ); +int hb_compParse( HB_MACRO_PTR ); + +void hb_compGenPCode1( BYTE, HB_MACRO_DECL ); +void hb_compGenPCode3( BYTE, BYTE, BYTE, HB_MACRO_DECL ); +void hb_compGenPCodeN( BYTE * pBuffer, ULONG ulSize, HB_MACRO_DECL ); + +/* Size of pcode buffer incrementation + */ +#define HB_PCODE_SIZE 512 + +/* Bison requires (void *) pointer - some code needs HB_MACRO_PTR pointer + */ +#define HB_MACRO_DATA ( (HB_MACRO_PTR) HB_MACRO_PARAM ) +#define HB_PCODE_DATA ( HB_MACRO_DATA->pCodeInfo ) + +#endif diff --git a/harbour/include/pcode.h b/harbour/include/pcode.h index 3d6e64e968..d930a4bf72 100644 --- a/harbour/include/pcode.h +++ b/harbour/include/pcode.h @@ -68,10 +68,29 @@ typedef enum HB_P_LESS, /* checks if the second latest value on the stack is less that the lastest one */ HB_P_LINE, /* currently compiled source code line number */ HB_P_LOCALNAME, /* sets the name of local variable */ + HB_P_MACROPOP, /* compile and run - pop a value from the stack */ + HB_P_MACROPOPALIASED, /* compile and run - pop a field value from the stack */ + HB_P_MACROPUSH, /* compile and run - leave the result on the stack */ + HB_P_MACROPUSHALIASED, /* compile and run - leave the field value on the stack */ + HB_P_MACROSYMBOL, /* compile into a symbol name (used in function calls) */ + HB_P_MACROTEXT, /* macro text substitution */ HB_P_MESSAGE, /* sends a message to an object */ HB_P_MINUS, /* subs the latest two values on the stack, removing them and leaving there the result */ HB_P_MODULUS, /* calculates the modulus of the two values on the stack, removing them and leaving there the result */ HB_P_MODULENAME, /* sets the name of debugged module */ +/* start: pcodes generated by the macro compiler - the symbol address is used */ + HB_P_MMESSAGE, + HB_P_MPOPALIASEDFIELD, + HB_P_MPOPFIELD, + HB_P_MPOPMEMVAR, + HB_P_MPUSHALIASEDFIELD, + HB_P_MPUSHBLOCK, + HB_P_MPUSHFIELD, + HB_P_MPUSHMEMVAR, + HB_P_MPUSHMEMVARREF, + HB_P_MPUSHSYM, + HB_P_MPUSHVARIABLE, +/* end: */ HB_P_MULT, /* multiplies the latest two values on the stack, removing them and leaving there the result */ HB_P_NEGATE, /* numerically negates the latest value on the stack */ HB_P_NOOP, /* no operation */ diff --git a/harbour/samples/cccppc/Makefile b/harbour/samples/cccppc/Makefile index c2a2b614ee..ac072e5825 100644 --- a/harbour/samples/cccppc/Makefile +++ b/harbour/samples/cccppc/Makefile @@ -60,5 +60,7 @@ LIBS=\ rdd \ rtl \ pp \ + common \ + macro \ include $(TOP)$(ROOT)config/bin.cf diff --git a/harbour/samples/guestbk/Makefile b/harbour/samples/guestbk/Makefile index dab036be6a..43672f7c7d 100644 --- a/harbour/samples/guestbk/Makefile +++ b/harbour/samples/guestbk/Makefile @@ -20,5 +20,7 @@ LIBS=\ rdd \ rtl \ pp \ + common \ + macro \ include $(TOP)$(ROOT)config/bin.cf diff --git a/harbour/samples/hscript/Makefile b/harbour/samples/hscript/Makefile index b8284caa9f..41e491322e 100644 --- a/harbour/samples/hscript/Makefile +++ b/harbour/samples/hscript/Makefile @@ -18,5 +18,7 @@ LIBS=\ rdd \ rtl \ pp \ + common \ + macro \ include $(TOP)$(ROOT)config/bin.cf diff --git a/harbour/samples/misc/Makefile b/harbour/samples/misc/Makefile index e5056456d1..6f1da559ce 100644 --- a/harbour/samples/misc/Makefile +++ b/harbour/samples/misc/Makefile @@ -14,6 +14,8 @@ LIBS=\ rtl \ pp \ runner \ + common \ + macro \ ifeq ($(PM),) PM := $(pm) diff --git a/harbour/samples/pe/Makefile b/harbour/samples/pe/Makefile index ba9282a736..4648f13d83 100644 --- a/harbour/samples/pe/Makefile +++ b/harbour/samples/pe/Makefile @@ -21,5 +21,7 @@ LIBS=\ rdd \ rtl \ pp \ + common \ + macro \ include $(TOP)$(ROOT)config/bin.cf diff --git a/harbour/source/Makefile b/harbour/source/Makefile index 8a4c04666c..7fe7a41a0a 100644 --- a/harbour/source/Makefile +++ b/harbour/source/Makefile @@ -11,6 +11,7 @@ DIRS=\ rtl \ vm \ rdd \ + macro \ debug \ tools \ runner \ diff --git a/harbour/source/common/Makefile b/harbour/source/common/Makefile index 6dadb34c7d..9276e8b344 100644 --- a/harbour/source/common/Makefile +++ b/harbour/source/common/Makefile @@ -8,6 +8,7 @@ C_SOURCES=\ hbfsapi.c \ hbstr.c \ hbtrace.c \ + reserved.c \ PRG_SOURCES=\ diff --git a/harbour/source/compiler/cmdcheck.c b/harbour/source/compiler/cmdcheck.c index 5a70e860ab..a3101b558b 100644 --- a/harbour/source/compiler/cmdcheck.c +++ b/harbour/source/compiler/cmdcheck.c @@ -479,7 +479,7 @@ void hb_compChkCompileFileName( int iArg, char * Args[] ) */ if( n > 1 ) /* GenWarning() */ - printf( "Warning: File %s will be ignored\n", strupr( Args[ i ] ) ); + printf( "Warning: File %s will be ignored\n", hb_strupr( Args[ i ] ) ); else { hb_comp_pFileName = hb_fsFNameSplit( Args[ i ] ); diff --git a/harbour/source/compiler/expropt.c b/harbour/source/compiler/expropt.c index b2e994a4fd..9a700a655b 100644 --- a/harbour/source/compiler/expropt.c +++ b/harbour/source/compiler/expropt.c @@ -49,26 +49,42 @@ #define HB_XGRAB( size ) hb_xgrab( (size) ) #define HB_XFREE( pPtr ) hb_xfree( (void *)(pPtr) ) - -/* Definitions of function templates used in expression's message - * handling +/* NOTE: We need to pass additional parameter if compilation for macro + * compiler support. This parameter is a pointer to an internal macro + * structure used to store all data needed for re-entrant compilation */ -#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) ) +#ifdef HB_MACRO_SUPPORT -typedef HB_EXPR_PTR HB_EXPR_ACTION( HB_EXPR_PTR pSelf, int iMessage ); +#define hb_compGenPCode1( p1 ) hb_compGenPCode1( p1, HB_MACRO_PARAM ) +#define hb_compGenPCode3( p1, p2, p3 ) hb_compGenPCode3( p1, p2, p3, HB_MACRO_PARAM ) +#define hb_compGenPCodeN( p1, p2 ) hb_compGenPCodeN( p1, p2, HB_MACRO_PARAM ) -/* This structure holds local variables declared in a codeblock - */ -typedef struct HB_CBVAR_ -{ - char * szName; - BYTE bType; - struct HB_CBVAR_ * pNext; -} HB_CBVAR, *HB_CBVAR_PTR; +#define hb_compCodeBlockStart( ) hb_compCodeBlockStart( HB_MACRO_PARAM ) +#define hb_compCodeBlockEnd( ) hb_compCodeBlockEnd( HB_MACRO_PARAM ) + +#define hb_compGenJump( p1 ) hb_compGenJump( p1, HB_MACRO_PARAM ) +#define hb_compGenJumpFalse( p1 ) hb_compGenJumpFalse( p1, HB_MACRO_PARAM ) +#define hb_compGenJumpTrue( p1 ) hb_compGenJumpTrue( p1, HB_MACRO_PARAM ) +#define hb_compGenJumpHere( p1 ) hb_compGenJumpHere( p1, HB_MACRO_PARAM ) +#define hb_compGenJumpThere( p1, p2 ) hb_compGenJumpThere( p1, p2, HB_MACRO_PARAM ) + +#define hb_compGenMessage( p1 ) hb_compGenMessage( p1, HB_MACRO_PARAM ) +#define hb_compGenMessageData( p1 ) hb_compGenMessageData( p1, HB_MACRO_PARAM ) +#define hb_compGenPopVar( p1 ) hb_compGenPopVar( p1, HB_MACRO_PARAM ) +#define hb_compGenPushDouble( p1, p2 ) hb_compGenPushDouble( p1, p2, HB_MACRO_PARAM ) +#define hb_compGenPushFunCall( p1 ) hb_compGenPushFunCall( p1, HB_MACRO_PARAM ) +#define hb_compGenPushVar( p1 ) hb_compGenPushVar( p1, HB_MACRO_PARAM ) +#define hb_compGenPushVarRef( p1 ) hb_compGenPushVarRef( p1, HB_MACRO_PARAM ) +#define hb_compGenPushLogical( p1 ) hb_compGenPushLogical( p1, HB_MACRO_PARAM ) +#define hb_compGenPushLong( p1 ) hb_compGenPushLong( p1, HB_MACRO_PARAM ) +#define hb_compGenPushNil( ) hb_compGenPushNil( p1, HB_MACRO_PARAM ) +#define hb_compGenPushString( p1, p2 ) hb_compGenPushString( p1, p2, HB_MACRO_PARAM ) +#define hb_compGenPushSymbol( p1, p2 ) hb_compGenPushSymbol( p1, p2, HB_MACRO_PARAM ) +#define hb_compGenPushAliasedVar( p1, p2, p3, p4 ) hb_compGenPushAliasedVar( p1, p2, p3, p4, HB_MACRO_PARAM ) +#define hb_compGenPopAliasedVar( p1, p2 , p3, p4 ) hb_compGenPopAliasedVar( p1, p2, p3, p4, HB_MACRO_PARAM ) +#define hb_compGenPushFunRef( p1 ) hb_compGenPushFunRef( p1, HB_MACRO_PARAM ) + +#endif /* ifdef HB_MACRO_SUPPORT */ /* value types seen at language level */ @@ -104,6 +120,12 @@ typedef enum #define HB_ET_LONG 1 #define HB_ET_DOUBLE 2 +/* additional definitions used to distinguish macro expressions + */ +#define HB_ET_MACRO_VAR 0 /* &variable */ +#define HB_ET_MACRO_FUNCALL 1 /* &fimcall() */ +#define HB_ET_MACRO_ALIASED 2 /* &alias->&variable */ + /* types of expressions * NOTE: the order of these definition is important - change it carefully * All types <= HB_ET_FUNREF are constant values @@ -132,6 +154,7 @@ typedef enum HB_ET_ALIASEXPR, HB_ET_SEND, HB_ET_SYMBOL, + HB_ET_ALIAS, HB_ET_VARIABLE, HB_EO_POSTINC, /* post-operators -> lowest precedence */ HB_EO_POSTDEC, @@ -186,6 +209,7 @@ 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_compExprUseAlias ); static HB_EXPR_FUNC( hb_compExprUseVariable ); static HB_EXPR_FUNC( hb_compExprUseAssign ); static HB_EXPR_FUNC( hb_compExprUseEqual ); @@ -238,6 +262,7 @@ static HB_EXPR_FUNC_PTR s_ExprTable[] = { hb_compExprUseAliasExpr, hb_compExprUseSend, hb_compExprUseSymbol, + hb_compExprUseAlias, hb_compExprUseVariable, hb_compExprUsePostInc, /* post-operators -> lowest precedence */ hb_compExprUsePostDec, @@ -296,6 +321,7 @@ static BYTE s_PrecedTable[] = { HB_ET_NIL, /* HB_ET_ALIASEXPR, */ HB_ET_NIL, /* HB_ET_SEND, */ HB_ET_NIL, /* HB_ET_SYMBOL, */ + HB_ET_NIL, /* HB_ET_ALIAS, */ HB_ET_NIL, /* HB_ET_VARIABLE, */ HB_ET_NIL, /* HB_EO_POSTINC, post-operators */ HB_ET_NIL, /* HB_EO_POSTDEC, */ @@ -348,8 +374,9 @@ static char * s_OperTable[] = { "->", "->", ":", - "", - "", + "", /* symbol */ + "", /* alias */ + "", /* variable */ "++", /* post-operators -> lowest precedence */ "--", ":=", /* assigments */ @@ -383,8 +410,34 @@ static char * s_OperTable[] = { /* Forward declarations */ -static void hb_compExprDelOperator( HB_EXPR_PTR ); +#ifdef HB_MACRO_SUPPORT + +static void hb_compExprDelOperatorMC( HB_EXPR_PTR, HB_MACRO_DECL ); +static ULONG hb_compExprListReduceMC( HB_EXPR_PTR, HB_MACRO_DECL ); +static HB_EXPR_PTR hb_compExprListStripMC( HB_EXPR_PTR, HB_MACRO_DECL ); +static void hb_compExprPushOperEqMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); +static void hb_compExprUseOperEqMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); +static void hb_compExprPushPreOpMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); +static void hb_compExprPushPostOpMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); +static void hb_compExprUsePreOpMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); +static void hb_compExprUseAliasMacroMC( HB_EXPR_PTR, BYTE, HB_MACRO_DECL ); + +#define hb_compExprDelOperator( p ) hb_compExprDelOperatorMC( p, HB_MACRO_PARAM ) +#define hb_compExprListReduce( pSelf ) hb_compExprListReduceMC( pSelf, HB_MACRO_PARAM ) +#define hb_compExprListStrip( p ) hb_compExprListStripMC( p, HB_MACRO_PARAM ) +#define hb_compExprPushOperEq( p, b ) hb_compExprPushOperEqMC( p, b, HB_MACRO_PARAM ) +#define hb_compExprUseOperEq( p, b ) hb_compExprUseOperEqMC( p, b, HB_MACRO_PARAM ) +#define hb_compExprPushPreOp( p, b ) hb_compExprPushPreOpMC( p, b, HB_MACRO_PARAM ) +#define hb_compExprPushPostOp( p, b ) hb_compExprPushPostOpMC( p, b, HB_MACRO_PARAM ) +#define hb_compExprUsePreOp( p, b ) hb_compExprUsePreOpMC( p, b, HB_MACRO_PARAM ) +#define hb_compExprUseAliasMacro( p, b ) hb_compExprUseAliasMacroMC( p, b, HB_MACRO_PARAM ) + +#define hb_comp_bShortCuts ( HB_MACRO_DATA->bShortCuts ) + +#else + +static void hb_compExprDelOperator( HB_EXPR_PTR ); static ULONG hb_compExprListReduce( HB_EXPR_PTR ); static HB_EXPR_PTR hb_compExprListStrip( HB_EXPR_PTR ); static void hb_compExprPushOperEq( HB_EXPR_PTR, BYTE ); @@ -392,7 +445,11 @@ 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 void hb_compExprUseAliasMacro( HB_EXPR_PTR, BYTE ); +#endif + +static BOOL hb_compExprCheckMacroVar( char * ); static HB_CBVAR_PTR hb_compExprCBVarNew( char *, BYTE ); static void hb_compExprCBVarDel( HB_CBVAR_PTR ); @@ -411,11 +468,22 @@ HB_EXPR_PTR hb_compExprNew( int iType ) /* Delete all components and delete self */ +#ifdef HB_MACRO_SUPPORT +void hb_compExprDelete( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +{ + HB_EXPR_USE( pExpr, HB_EA_DELETE ); + HB_XFREE( pExpr ); +} + +#define hb_compExprDelete( pParms ) hb_compExprDelete( pParms, HB_MACRO_PARAM ) + +#else void hb_compExprDelete( HB_EXPR_PTR pExpr ) { HB_EXPR_USE( pExpr, HB_EA_DELETE ); HB_XFREE( pExpr ); } +#endif /* Delete self - all components will be deleted somewhere else */ @@ -485,7 +553,11 @@ HB_EXPR_PTR hb_compExprNewCodeBlock( void ) /* Add a new local variable declaration */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, HB_MACRO_DECL ) +#else HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, BYTE bType ) +#endif { HB_CBVAR_PTR pVar; @@ -503,13 +575,21 @@ HB_EXPR_PTR hb_compExprCBVarAdd( HB_EXPR_PTR pCB, char * szVarName, BYTE bType ) pVar = pVar->pNext; else { +#ifdef HB_MACRO_SUPPORT + pVar->pNext = hb_compExprCBVarNew( szVarName, ' ' ); +#else pVar->pNext = hb_compExprCBVarNew( szVarName, bType ); +#endif pVar = NULL; } } } else +#ifdef HB_MACRO_SUPPORT + pCB->value.asList.pIndex = ( HB_EXPR_PTR ) hb_compExprCBVarNew( szVarName, ' ' ); +#else pCB->value.asList.pIndex = ( HB_EXPR_PTR ) hb_compExprCBVarNew( szVarName, bType ); +#endif return pCB; } @@ -565,6 +645,7 @@ HB_EXPR_PTR hb_compExprNewFunRef( char * szFunName ) */ HB_EXPR_PTR hb_compExprNewIIF( HB_EXPR_PTR pExpr ) { +#ifndef HB_MACRO_SUPPORT HB_EXPR_PTR pTmp; pExpr->ExprType = HB_ET_IIF; @@ -576,82 +657,111 @@ HB_EXPR_PTR hb_compExprNewIIF( HB_EXPR_PTR pExpr ) */ hb_compErrorSyntax( pExpr ); } +#else + pExpr->ExprType = HB_ET_IIF; +#endif + return pExpr; } /* Create function call */ -HB_EXPR_PTR hb_compExprNewFunCall( char *szFunName, HB_EXPR_PTR pParms ) +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms, HB_MACRO_DECL ) +#else +HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) +#endif { HB_EXPR_PTR pExpr = NULL; - int iCount; - if( pParms ) + if( pName->ExprType == HB_ET_SYMBOL ) { - 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; - } - else - iCount = 0; + /* The name of a function is specified at compile time + * e.g. MyFunc() + * + * NOTE: 'pName' can be a macro expression that will be resolved + * at runtime - in this case pName is an expression of HB_ET_MACRO type + * e.g. &MyVar() + */ + int iCount; - hb_compFunCallCheck( szFunName, iCount ); - - /* TODO: AT() (also done by Clipper, already mentioned) - LEN() (also done by Clipper) - ASC() (not done by Clipper) - EMPTY() (not done by Clipper) */ - - 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 ) + if( pParms ) { - /* NOTE: CA-Cl*pper's compiler optimizer will be wrong for those - CHR() cases where the passed parameter is a constant which - can be divided by 256 but it's not zero, in this case it - will return an empty string instead of a Chr(0). [vszel] */ + 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; + } + else + iCount = 0; - pExpr = hb_compExprNew( HB_ET_STRING ); - pExpr->ValType = HB_EV_STRING; - if( pArg->value.asNum.NumType == HB_ET_LONG ) +#ifndef HB_MACRO_SUPPORT + hb_compFunCallCheck( pName->value.asSymbol, iCount ); +#endif + + /* TODO: AT() (also done by Clipper, already mentioned) + LEN() (also done by Clipper) + ASC() (not done by Clipper) + EMPTY() (not done by Clipper) */ + + if( ( strcmp( "CHR", pName->value.asSymbol ) == 0 ) && iCount ) + { + /* try to change it into a string */ + HB_EXPR_PTR pArg = pParms->value.asList.pExprList; + + if( pArg->ExprType == HB_ET_NUMERIC ) { - if( ( pArg->value.asNum.lVal % 256 ) == 0 && pArg->value.asNum.lVal != 0 ) + /* NOTE: CA-Cl*pper's compiler optimizer will be wrong for those + CHR() cases where the passed parameter is a constant which + can be divided by 256 but it's not zero, in this case it + will return an empty string instead of a Chr(0). [vszel] */ + + pExpr = hb_compExprNew( HB_ET_STRING ); + pExpr->ValType = HB_EV_STRING; + if( pArg->value.asNum.NumType == HB_ET_LONG ) { - pExpr->value.asString = ( char * ) HB_XGRAB( 1 ); - pExpr->value.asString[ 0 ] = '\0'; - pExpr->ulLength = 0; + if( ( pArg->value.asNum.lVal % 256 ) == 0 && pArg->value.asNum.lVal != 0 ) + { + pExpr->value.asString = ( char * ) HB_XGRAB( 1 ); + pExpr->value.asString[ 0 ] = '\0'; + pExpr->ulLength = 0; + } + else + { + pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); + pExpr->value.asString[ 0 ] = ( pArg->value.asNum.lVal % 256 ); + pExpr->value.asString[ 1 ] = '\0'; + pExpr->ulLength = 1; + } } else { pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); - pExpr->value.asString[ 0 ] = ( pArg->value.asNum.lVal % 256 ); + pExpr->value.asString[ 0 ] = ( ( long ) pArg->value.asNum.dVal % 256 ); pExpr->value.asString[ 1 ] = '\0'; pExpr->ulLength = 1; } + hb_compExprDelete( pParms ); + hb_compExprDelete( pName ); } - else - { - pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); - pExpr->value.asString[ 0 ] = ( ( long ) pArg->value.asNum.dVal % 256 ); - pExpr->value.asString[ 1 ] = '\0'; - pExpr->ulLength = 1; - } - hb_compExprDelete( pParms ); } } + else if( pName->ExprType == HB_ET_MACRO ) + { + /* Signal that macro compiler have to generate a pcode that will + * return function name as symbol instead of usual value + */ + pName->value.asMacro.SubType = HB_ET_MACRO_FUNCALL; + } if( pExpr == NULL ) { pExpr = hb_compExprNew( HB_ET_FUNCALL ); pExpr->value.asFunCall.pParms = pParms; - pExpr->value.asFunCall.szFunName = szFunName; + pExpr->value.asFunCall.pFunName = pName; } return pExpr; @@ -675,7 +785,6 @@ HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR pArrList ) */ if( pExpr->ExprType == HB_ET_NONE && pExpr->pNext == NULL ) { - hb_compExprDelete( pExpr ); /* delete EO_NONE expresssion */ pArrList->value.asList.pExprList = NULL; } else @@ -700,7 +809,11 @@ HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR pArrList ) * NOTE: In case of multiple indexes it is called recursively * array[ idx1, idx2 ] => ( array[ idx1 ] )[ idx2 ] */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex, HB_MACRO_DECL ) +#else HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex ) +#endif { HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_ARRAYAT ); @@ -715,16 +828,51 @@ HB_EXPR_PTR hb_compExprNewArrayAt( HB_EXPR_PTR pArray, HB_EXPR_PTR pIndex ) } /* 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 hb_compExprNewMacro( HB_EXPR_PTR pMacroExpr, unsigned char cMacroOp, char * szName ) { - HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_MACRO ); + HB_EXPR_PTR pExpr; - pExpr->value.asMacro.pVar = pVariable; - pExpr->value.asMacro.szNameExt = szNameExt; + if( szName ) + { + /* Macro variable is used: &identifier + * or macro text: [text]&variable[more_macro_text] + */ + /* + * NOTE: Clipper assumes that all variables used in macro expressions + * are memvar variables + * NOTE: Clipper pushes the complete macro expression converted + * to string in case complex expression is used, e.g. + * My&var.1 + * is pushed as: + * "MY&VAR.1" + */ + pExpr = hb_compExprNew( HB_ET_MACRO ); + pExpr->value.asMacro.cMacroOp = cMacroOp; /* '&' if variable or 0 if text */ + pExpr->value.asMacro.szMacro = szName; /* variable name or macro text */ + pExpr->value.asMacro.pExprList = NULL; /* this is not a parenthesized expressions */ + pExpr->value.asMacro.SubType = HB_ET_MACRO_VAR; + + if( cMacroOp == 0 ) + { + /* check if variable with valid scope is used in macro text + * (local, static and field variables are not allowed) + * e.g. + * LOCAL var + * ? &var // this is OK + * ? &var.ext // this is invalid + */ + hb_compExprCheckMacroVar( szName ); + } + } + else + { + /* Macro expression: &( expression_list ) + */ + pExpr = hb_compExprNew( HB_ET_MACRO ); + pExpr->value.asMacro.pExprList = pMacroExpr; + pExpr->value.asMacro.szMacro = NULL; /* this is used to distinguish &(...) from &ident */ + } return pExpr; } @@ -732,14 +880,21 @@ HB_EXPR_PTR hb_compExprNewMacro( HB_EXPR_PTR pVariable, char * szNameExt ) /* Creates new aliased variable * aliasexpr -> identifier */ -HB_EXPR_PTR hb_compExprNewAliasVar( HB_EXPR_PTR pAlias, char * szVarName ) +HB_EXPR_PTR hb_compExprNewAliasVar( HB_EXPR_PTR pAlias, HB_EXPR_PTR pVariable ) { HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_ALIASVAR ); pExpr->value.asAlias.pAlias = pAlias; - pExpr->value.asAlias.szVarName = szVarName; + pExpr->value.asAlias.pVar = pVariable; pExpr->value.asAlias.pExpList = NULL; + /* macro expressions in alias context require a special handling + */ + if( pAlias->ExprType == HB_ET_MACRO ) + pAlias->value.asMacro.SubType = HB_ET_MACRO_ALIASED; + if( pVariable->ExprType == HB_ET_MACRO ) + pVariable->value.asMacro.SubType = HB_ET_MACRO_ALIASED; + return pExpr; } @@ -752,7 +907,7 @@ HB_EXPR_PTR hb_compExprNewAliasExpr( HB_EXPR_PTR pAlias, HB_EXPR_PTR pExpList ) pExpr->value.asAlias.pAlias = pAlias; pExpr->value.asAlias.pExpList = pExpList; - pExpr->value.asAlias.szVarName = NULL; + pExpr->value.asAlias.pVar = NULL; return pExpr; } @@ -831,6 +986,8 @@ HB_EXPR_PTR hb_compExprNewVar( char * szName ) return pExpr; } +/* Create a new symbol used in function calls + */ HB_EXPR_PTR hb_compExprNewSymbol( char * szName ) { HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_SYMBOL ); @@ -838,6 +995,15 @@ HB_EXPR_PTR hb_compExprNewSymbol( char * szName ) return pExpr; } +/* Create a new symbol used in an alias expressions + */ +HB_EXPR_PTR hb_compExprNewAlias( char * szName ) +{ + HB_EXPR_PTR pExpr = hb_compExprNew( HB_ET_ALIAS ); + pExpr->value.asSymbol = szName; + return pExpr; +} + /* ************************************************************************* */ @@ -1108,6 +1274,7 @@ HB_EXPR_PTR hb_compExprAssign( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) * It is called in the following context: * STATIC sVar := expression */ +#ifndef HB_MACRO_SUPPORT HB_EXPR_PTR hb_compExprAssignStatic( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightExpr ) { HB_EXPR_PTR pExpr = hb_compExprNew( HB_EO_ASSIGN ); @@ -1135,12 +1302,16 @@ HB_EXPR_PTR hb_compExprAssignStatic( HB_EXPR_PTR pLeftExpr, HB_EXPR_PTR pRightEx return pExpr; } - +#endif /* Sets the argument of an operation found previously */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem, HB_MACRO_DECL ) +#else HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem ) +#endif { BYTE ucRight; @@ -1181,7 +1352,11 @@ HB_EXPR_PTR hb_compExprSetOperand( HB_EXPR_PTR pExpr, HB_EXPR_PTR pItem ) * Right := R * Oper := O */ +#ifdef HB_MACRO_SUPPORT + pItem->value.asOperator.pLeft = hb_compExprSetOperand( pExpr, pItem->value.asOperator.pLeft, HB_MACRO_PARAM ); +#else pItem->value.asOperator.pLeft = hb_compExprSetOperand( pExpr, pItem->value.asOperator.pLeft ); +#endif pExpr = pItem; } else @@ -1219,18 +1394,16 @@ ULONG hb_compExprListLen( HB_EXPR_PTR pExpr ) 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 */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr ) +#endif { pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); HB_EXPR_USE( pExpr, HB_EA_STATEMENT ); @@ -1240,7 +1413,11 @@ HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr ) /* Generates pcode to push an expressions * NOTE: It pushes a value on the stack and leaves this value on the stack */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr ) +#endif { pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); @@ -1249,7 +1426,11 @@ HB_EXPR_PTR hb_compExprGenPush( HB_EXPR_PTR pExpr ) /* Generates pcode to pop an expressions */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else HB_EXPR_PTR hb_compExprGenPop( HB_EXPR_PTR pExpr ) +#endif { return HB_EXPR_USE( pExpr, HB_EA_POP_PCODE ); } @@ -1264,7 +1445,7 @@ static HB_EXPR_FUNC( hb_compExprUseDummy ) case HB_EA_REDUCE: break; case HB_EA_ARRAY_AT: - hb_compErrorType( pSelf ); + hb_compErrorType( pSelf); case HB_EA_ARRAY_INDEX: break; case HB_EA_LVALUE: @@ -1365,7 +1546,16 @@ static HB_EXPR_FUNC( hb_compExprUseString ) hb_compErrorLValue( pSelf ); break; case HB_EA_PUSH_PCODE: - hb_compGenPushString( pSelf->value.asString, pSelf->ulLength ); + { + hb_compGenPushString( pSelf->value.asString, pSelf->ulLength ); +#ifndef HB_MACRO_SUPPORT +/* only memvar variables are allowed in macro compilation - there is no + * need to check for locals or static variables + */ + if( hb_compExprCheckMacroVar( pSelf->value.asString ) ) + hb_compGenPCode1( HB_P_MACROTEXT ); +#endif + } break; case HB_EA_POP_PCODE: break; @@ -1399,19 +1589,25 @@ static HB_EXPR_FUNC( hb_compExprUseCodeblock ) break; case HB_EA_PUSH_PCODE: { - HB_CBVAR_PTR pVar; HB_EXPR_PTR pExpr, pNext; HB_EXPR_PTR * pPrev; +#ifndef HB_MACRO_SUPPORT + HB_CBVAR_PTR pVar; +#endif hb_compCodeBlockStart(); /* Define requested local variables */ +#ifdef HB_MACRO_SUPPORT + HB_PCODE_DATA->pLocals = ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex; +#else pVar = ( HB_CBVAR_PTR ) pSelf->value.asList.pIndex; while( pVar ) { hb_compVariableAdd( pVar->szName, pVar->bType ); pVar =pVar->pNext; } +#endif pExpr = pSelf->value.asList.pExprList; pPrev = &pSelf->value.asList.pExprList; while( pExpr ) @@ -1583,10 +1779,12 @@ static HB_EXPR_FUNC( hb_compExprUseArray ) HB_EXPR_PTR pElem = pSelf->value.asList.pExprList; /* Delete all elements of the array */ + HB_EXPR_PTR pNext; while( pElem ) { - HB_EXPR_USE( pElem, HB_EA_DELETE ); - pElem = pElem->pNext; + pNext = pElem->pNext; + hb_compExprDelete( pElem ); + pElem = pNext; } } break; @@ -1826,10 +2024,11 @@ static HB_EXPR_FUNC( hb_compExprUseList ) while( pExpr ) { - HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); + if( pExpr->pNext ) + HB_EXPR_USE( pExpr, HB_EA_PUSH_POP ); + else + HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE ); /* the last expression */ pExpr = pExpr->pNext; - if( pExpr ) - hb_compGenPCode1( HB_P_POP ); } } break; @@ -2039,12 +2238,94 @@ static HB_EXPR_FUNC( hb_compExprUseMacro ) case HB_EA_ARRAY_AT: case HB_EA_ARRAY_INDEX: case HB_EA_LVALUE: + break; case HB_EA_PUSH_PCODE: + { + if( pSelf->value.asMacro.pExprList ) + { + /* macro expression: &( expressions_list ) + * NOTE: only the last expression will be macro-compiled + */ + HB_EXPR_USE( pSelf->value.asMacro.pExprList, HB_EA_PUSH_PCODE ); + } + else + { + if( pSelf->value.asMacro.cMacroOp ) + { + /* simple macro variable expansion: &variable + * 'szMacro' is a variable name + */ + hb_compGenPushVar( pSelf->value.asMacro.szMacro ); + } + else + { + /* complex macro expression: prefix&var.suffix + * all components should be placed as a string that will + * be compiled after text susbstitution + */ + hb_compGenPushString( pSelf->value.asMacro.szMacro, strlen(pSelf->value.asMacro.szMacro) ); + } + } + /* compile & run - leave a result on the eval stack + */ + if( pSelf->value.asMacro.SubType == HB_ET_MACRO_VAR ) + hb_compGenPCode1( HB_P_MACROPUSH ); + else if( pSelf->value.asMacro.SubType == HB_ET_MACRO_FUNCALL ) + hb_compGenPCode1( HB_P_MACROSYMBOL ); + /* NOTE: pcode for alias context requires is generated in + * hb_compExprUseAliasVar() + */ + } + break; + case HB_EA_POP_PCODE: + { + if( pSelf->value.asMacro.pExprList ) + { + /* macro expression: &( expressions_list ) + * NOTE: only the last expression will be macro-compiled + */ + HB_EXPR_USE( pSelf->value.asMacro.pExprList, HB_EA_PUSH_PCODE ); + } + else + { + if( pSelf->value.asMacro.cMacroOp ) + { + /* simple macro variable expansion: &variable + * 'szMacro' is a variable name + */ + hb_compGenPushVar( pSelf->value.asMacro.szMacro ); + } + else + { + /* complex macro expression: prefix&var.suffix + * all components should be placed as a string that will + * be compiled after text susbstitution + */ + hb_compGenPushString( pSelf->value.asMacro.szMacro, strlen(pSelf->value.asMacro.szMacro) ); + } + } + /* compile & run - macro compiler will generate pcode to pop a value + * from the eval stack + */ + hb_compGenPCode1( HB_P_MACROPOP ); + } + break; + case HB_EA_PUSH_POP: case HB_EA_STATEMENT: - hb_compWarnMeaningless( pSelf ); + HB_EXPR_USE( pSelf, HB_EA_PUSH_PCODE ); + hb_compGenPCode1( HB_P_POP ); + break; + case HB_EA_DELETE: + if( pSelf->value.asMacro.pExprList ) + hb_compExprDelete( pSelf->value.asMacro.pExprList ); +/* NOTE: This will be released during releasing of symbols' table + * + * if( pSelf->value.asMacro.szMacro ); + * HB_XFREE( pSelf->value.asMacro.szMacro ); + */ break; } return pSelf; @@ -2075,7 +2356,7 @@ static HB_EXPR_FUNC( hb_compExprUseFunCall ) { USHORT usCount; - hb_compGenPushFunCall( pSelf->value.asFunCall.szFunName ); + HB_EXPR_USE( pSelf->value.asFunCall.pFunName, HB_EA_PUSH_PCODE ); hb_compGenPCode1( HB_P_PUSHNIL ); if( pSelf->value.asFunCall.pParms ) @@ -2103,7 +2384,7 @@ static HB_EXPR_FUNC( hb_compExprUseFunCall ) { USHORT usCount; - hb_compGenPushFunCall( pSelf->value.asFunCall.szFunName ); + HB_EXPR_USE( pSelf->value.asFunCall.pFunName, HB_EA_PUSH_PCODE ); hb_compGenPCode1( HB_P_PUSHNIL ); if( pSelf->value.asFunCall.pParms ) @@ -2123,7 +2404,7 @@ static HB_EXPR_FUNC( hb_compExprUseFunCall ) case HB_EA_DELETE: if( pSelf->value.asFunCall.pParms ) hb_compExprDelete( pSelf->value.asFunCall.pParms ); - /* NOTE: function name will be released after pcode generation */ + hb_compExprDelete( pSelf->value.asFunCall.pFunName ); break; } return pSelf; @@ -2152,7 +2433,14 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) bReduced = TRUE; } - if( pAlias->ExprType == HB_ET_SYMBOL ) + if( pAlias->ExprType == HB_ET_MACRO || pSelf->value.asAlias.pVar->ExprType == HB_ET_MACRO ) + { + /* Macro operator is used on the left or right side of an alias + * operator - handle it with a special care + */ + hb_compExprUseAliasMacro( pSelf, HB_EA_PUSH_PCODE ); + } + else if( pAlias->ExprType == HB_ET_ALIAS ) { /* * myalias->var @@ -2161,7 +2449,7 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) * * NOTE: TRUE = push also alias */ - hb_compGenPushAliasedVar( pSelf->value.asAlias.szVarName, TRUE, pAlias->value.asSymbol, 0 ); + hb_compGenPushAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, TRUE, pAlias->value.asSymbol, 0 ); } else if( pAlias->ExprType == HB_ET_NUMERIC ) { @@ -2171,7 +2459,7 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) * NOTE: only integer (long) values are allowed */ if( pAlias->value.asNum.NumType == HB_ET_LONG ) - hb_compGenPushAliasedVar( pSelf->value.asAlias.szVarName, TRUE, NULL, pAlias->value.asNum.lVal ); + hb_compGenPushAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, TRUE, NULL, pAlias->value.asNum.lVal ); else hb_compErrorAlias( pAlias ); } @@ -2183,7 +2471,7 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) * NOTE: FALSE = don't push alias value */ HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); - hb_compGenPushAliasedVar( pSelf->value.asAlias.szVarName, FALSE, NULL, 0 ); + hb_compGenPushAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, FALSE, NULL, 0 ); } else hb_compErrorAlias( pAlias ); @@ -2201,14 +2489,21 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) bReduced = TRUE; } - if( pAlias->ExprType == HB_ET_SYMBOL ) + if( pAlias->ExprType == HB_ET_MACRO || pSelf->value.asAlias.pVar->ExprType == HB_ET_MACRO ) + { + /* Macro operator is used on the left or right side of an alias + * operator - handle it with a special care + */ + hb_compExprUseAliasMacro( pAlias, HB_EA_POP_PCODE ); + } + if( pAlias->ExprType == HB_ET_ALIAS ) { /* * myalias->var * FIELD->var * MEMVAR->var */ - hb_compGenPopAliasedVar( pSelf->value.asAlias.szVarName, TRUE, pAlias->value.asSymbol, 0 ); + hb_compGenPopAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, TRUE, pAlias->value.asSymbol, 0 ); } else if( pAlias->ExprType == HB_ET_NUMERIC ) { @@ -2218,7 +2513,7 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) * NOTE: only integer (long) values are allowed */ if( pAlias->value.asNum.NumType == HB_ET_LONG ) - hb_compGenPopAliasedVar( pSelf->value.asAlias.szVarName, TRUE, NULL, pAlias->value.asNum.lVal ); + hb_compGenPopAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, TRUE, NULL, pAlias->value.asNum.lVal ); else hb_compErrorAlias( pAlias ); } @@ -2230,7 +2525,7 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) * NOTE: FALSE = don't push alias value */ HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); - hb_compGenPopAliasedVar( pSelf->value.asAlias.szVarName, FALSE, NULL, 0 ); + hb_compGenPopAliasedVar( pSelf->value.asAlias.pVar->value.asSymbol, FALSE, NULL, 0 ); } else hb_compErrorAlias( pAlias ); @@ -2321,7 +2616,7 @@ static HB_EXPR_FUNC( hb_compExprUseAliasExpr ) return pSelf; } -static HB_EXPR_FUNC( hb_compExprUseSymbol ) +static HB_EXPR_FUNC( hb_compExprUseAlias ) { switch( iMessage ) { @@ -2342,6 +2637,30 @@ static HB_EXPR_FUNC( hb_compExprUseSymbol ) 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: + break; + case HB_EA_PUSH_PCODE: + hb_compGenPushFunCall( pSelf->value.asSymbol ); + break; + case HB_EA_POP_PCODE: + case HB_EA_PUSH_POP: + case HB_EA_STATEMENT: + case HB_EA_DELETE: +#ifdef HB_MACRO_SUPPORT + HB_XFREE( pSelf->value.asSymbol ); +#endif + break; + } + return pSelf; +} + static HB_EXPR_FUNC( hb_compExprUseVariable ) { switch( iMessage ) @@ -2365,7 +2684,11 @@ static HB_EXPR_FUNC( hb_compExprUseVariable ) break; case HB_EA_DELETE: +#ifdef HB_MACRO_SUPPORT + HB_XFREE( pSelf->value.asSymbol ); +#else /* NOTE: variable name will be released after pcode generation */ +#endif break; } return pSelf; @@ -2863,7 +3186,7 @@ static HB_EXPR_FUNC( hb_compExprUseOr ) pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } - else if( pLeft->ExprType == HB_ET_LOGICAL ) + else if( pLeft->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) { if( pLeft->value.asLogical ) { @@ -2885,7 +3208,7 @@ static HB_EXPR_FUNC( hb_compExprUseOr ) pSelf = pRight; } } - else if( pRight->ExprType == HB_ET_LOGICAL ) + else if( pRight->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) { if( pRight->value.asLogical ) { @@ -2995,7 +3318,7 @@ static HB_EXPR_FUNC( hb_compExprUseAnd ) pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } - else if( pLeft->ExprType == HB_ET_LOGICAL ) + else if( pLeft->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) { if( pLeft->value.asLogical ) { @@ -3017,7 +3340,7 @@ static HB_EXPR_FUNC( hb_compExprUseAnd ) pSelf->value.asLogical = FALSE; } } - else if( pRight->ExprType == HB_ET_LOGICAL ) + else if( pRight->ExprType == HB_ET_LOGICAL && hb_comp_bShortCuts ) { if( pRight->value.asLogical ) { @@ -4855,7 +5178,7 @@ static HB_EXPR_FUNC( hb_compExprUseNegate ) case HB_EA_DELETE: if( pSelf->value.asOperator.pLeft ) - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_DELETE ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); break; } return pSelf; @@ -4895,7 +5218,7 @@ static HB_EXPR_FUNC( hb_compExprUsePreInc ) case HB_EA_DELETE: if( pSelf->value.asOperator.pLeft ) - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_DELETE ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); break; } return pSelf; @@ -4935,7 +5258,7 @@ static HB_EXPR_FUNC( hb_compExprUsePreDec ) case HB_EA_DELETE: if( pSelf->value.asOperator.pLeft ) - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_DELETE ); + hb_compExprDelete( pSelf->value.asOperator.pLeft ); break; } return pSelf; @@ -4943,19 +5266,27 @@ static HB_EXPR_FUNC( hb_compExprUsePreDec ) /* ************************************************************************* */ +#ifdef HB_MACRO_SUPPORT +static void hb_compExprDelOperatorMC( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else static void hb_compExprDelOperator( HB_EXPR_PTR pExpr ) +#endif { if( pExpr->value.asOperator.pLeft ) - HB_EXPR_USE( pExpr->value.asOperator.pLeft, HB_EA_DELETE ); + hb_compExprDelete( pExpr->value.asOperator.pLeft ); if( pExpr->value.asOperator.pRight ) - HB_EXPR_USE( pExpr->value.asOperator.pRight, HB_EA_DELETE ); + hb_compExprDelete( pExpr->value.asOperator.pRight ); } /* Reduces the list of expressions * * pExpr is the first expression on the list */ +#ifdef HB_MACRO_SUPPORT +static ULONG hb_compExprListReduceMC( HB_EXPR_PTR pExpr, HB_MACRO_DECL ) +#else static ULONG hb_compExprListReduce( HB_EXPR_PTR pExpr ) +#endif { HB_EXPR_PTR pNext; HB_EXPR_PTR * pPrev; @@ -4980,7 +5311,11 @@ static ULONG hb_compExprListReduce( HB_EXPR_PTR pExpr ) return ulCnt; } +#ifdef HB_MACRO_SUPPORT +static HB_EXPR_PTR hb_compExprListStripMC( HB_EXPR_PTR pSelf, HB_MACRO_DECL ) +#else static HB_EXPR_PTR hb_compExprListStrip( HB_EXPR_PTR pSelf ) +#endif { if( pSelf->ExprType == HB_ET_LIST ) @@ -5007,7 +5342,11 @@ static HB_EXPR_PTR hb_compExprListStrip( HB_EXPR_PTR pSelf ) * * pExpr is an expression created by hb_compExprNewEq functions */ +#ifdef HB_MACRO_SUPPORT +static void hb_compExprPushOperEqMC( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_MACRO_DECL ) +#else static void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) +#endif { /* NOTE: an object instance variable needs special handling */ @@ -5087,7 +5426,11 @@ static void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) /* Generates pcodes for = syntax * used standalone as a statement (it cannot leave the value on the stack) */ +#ifdef HB_MACRO_SUPPORT +static void hb_compExprUseOperEqMC( HB_EXPR_PTR pSelf, BYTE bOpEq, HB_MACRO_DECL ) +#else static void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) +#endif { /* NOTE: an object instance variable needs special handling */ @@ -5137,7 +5480,11 @@ static void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) /* Generates the pcodes for pre- increment/decrement expressions */ +#ifdef HB_MACRO_SUPPORT +static void hb_compExprPushPreOpMC( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL ) +#else static void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper ) +#endif { /* NOTE: an object instance variable needs special handling */ @@ -5183,7 +5530,11 @@ static void hb_compExprPushPreOp( HB_EXPR_PTR pSelf, BYTE bOper ) /* Generates the pcodes for post- increment/decrement expressions */ +#ifdef HB_MACRO_SUPPORT +static void hb_compExprPushPostOpMC( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL ) +#else static void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper ) +#endif { /* NOTE: an object instance variable needs special handling */ @@ -5212,7 +5563,11 @@ static void hb_compExprPushPostOp( HB_EXPR_PTR pSelf, BYTE bOper ) /* Generates the pcodes for increment/decrement operations * used standalone as a statement */ +#ifdef HB_MACRO_SUPPORT +static void hb_compExprUsePreOpMC( HB_EXPR_PTR pSelf, BYTE bOper, HB_MACRO_DECL ) +#else static void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper ) +#endif { /* NOTE: an object instance variable needs special handling */ @@ -5233,6 +5588,107 @@ static void hb_compExprUsePreOp( HB_EXPR_PTR pSelf, BYTE bOper ) } } +/* Generate pcode for aliased expression which contains macro operator on + * the left or right side of the alias operator + * expression->¯o or ¯o->expression or ¯o->¯o + */ +#ifdef HB_MACRO_SUPPORT +static void hb_compExprUseAliasMacroMC( HB_EXPR_PTR pAliasedVar, BYTE bAction, HB_MACRO_DECL ) +#else +static void hb_compExprUseAliasMacro( HB_EXPR_PTR pAliasedVar, BYTE bAction ) +#endif +{ + HB_EXPR_PTR pAlias, pVar; + + pAlias = pAliasedVar->value.asAlias.pAlias; + pVar = pAliasedVar->value.asAlias.pVar; + if( pAlias->ExprType == HB_ET_ALIAS ) + { + /* database alias */ + /* Push alias identifier as string so it can be joined with + * variable at runtime + * NOTE: + * ALIAS->&var is the same as &( "ALIAS->" + var ) + * + */ + hb_compGenPushString( pAlias->value.asSymbol, strlen(pAlias->value.asSymbol) ); + HB_EXPR_USE( pVar, HB_EA_PUSH_PCODE ); + if( bAction == HB_EA_PUSH_PCODE ) + hb_compGenPCode1( HB_P_MACROPUSHALIASED ); + else + hb_compGenPCode1( HB_P_MACROPOPALIASED ); + } + else if( pVar->ExprType == HB_ET_VARIABLE ) + { + /* NOTE: + * ¯o->var is the same as: &( macro + "->var" ) + */ + HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); + hb_compGenPushString( pVar->value.asSymbol, strlen(pVar->value.asSymbol) ); + if( bAction == HB_EA_PUSH_PCODE ) + hb_compGenPCode1( HB_P_MACROPUSHALIASED ); + else + hb_compGenPCode1( HB_P_MACROPOPALIASED ); + } + else + { + HB_EXPR_USE( pAlias, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pVar, HB_EA_PUSH_PCODE ); + if( bAction == HB_EA_PUSH_PCODE ) + hb_compGenPCode1( HB_P_MACROPUSHALIASED ); + else + hb_compGenPCode1( HB_P_MACROPOPALIASED ); + } + +} + +static BOOL hb_compExprCheckMacroVar( char * szText ) +{ + char * pTmp = szText; + BOOL bTextSubst = FALSE; + + while( ( pTmp = strchr( pTmp, '&' ) ) ) + { + /* Check if macro operator is used inside a string + * Macro operator is ignored if it is the last char or + * next char is '(' e.g. "this is &(ignored)" + * + * NOTE: This uses _a-zA-Z pattern to check for + * variable name beginning + */ + + ++pTmp; + bTextSubst = ( *pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') ); +#ifndef HB_MACRO_SUPPORT + /* NOTE: All variables are assumed memvars in macro compiler - + * there is no need to check for a valid name + */ + if( bTextSubst ) + { + /* There is a valid character after '&' that can be used in + * variable name - check if the whole variable name is valid + * (local, static and field variable names are invalid because + * they are not visible at runtime) + */ + char * pStart = pTmp; + char cSave; + + /* NOTE: This uses _a-zA-Z0-9 pattern to check for + * variable name + */ + while( *pTmp && (*pTmp == '_' || (*pTmp >= 'A' && *pTmp <= 'Z') || (*pTmp >= 'a' && *pTmp <= 'z') || (*pTmp >= '0' && *pTmp <= '9')) ) + ++pTmp; + + cSave = *pTmp; + *pTmp = '\0'; + hb_compVariableMacroCheck( pStart ); + *pTmp = cSave; + } +#endif + } + return bTextSubst; +} + /* ************************************************************************* */ /* Create a new declaration for codeblock local variable diff --git a/harbour/source/compiler/genc.c b/harbour/source/compiler/genc.c index 88c9104eb5..b354f31572 100644 --- a/harbour/source/compiler/genc.c +++ b/harbour/source/compiler/genc.c @@ -411,6 +411,36 @@ void hb_compGenCCode( PHB_FNAME pFileName ) /* generates the C language ou lPCodePos++; break; + case HB_P_MACROPOP: + fprintf( yyc, "\tHB_P_MACROPOP,\n" ); + lPCodePos++; + break; + + case HB_P_MACROPOPALIASED: + fprintf( yyc, "\tHB_P_MACROPOPALIASED,\n" ); + lPCodePos++; + break; + + case HB_P_MACROPUSH: + fprintf( yyc, "\tHB_P_MACROPUSH,\n" ); + lPCodePos++; + break; + + case HB_P_MACROPUSHALIASED: + fprintf( yyc, "\tHB_P_MACROPUSHALIASED,\n" ); + lPCodePos++; + break; + + case HB_P_MACROSYMBOL: + fprintf( yyc, "\tHB_P_MACROSYMBOL,\n" ); + lPCodePos++; + break; + + case HB_P_MACROTEXT: + fprintf( yyc, "\tHB_P_MACROTEXT,\n" ); + lPCodePos++; + break; + case HB_P_MESSAGE: { USHORT wFixPos; diff --git a/harbour/source/compiler/genhrb.c b/harbour/source/compiler/genhrb.c index 19405a2e13..911922cd43 100644 --- a/harbour/source/compiler/genhrb.c +++ b/harbour/source/compiler/genhrb.c @@ -181,6 +181,12 @@ void hb_compGenPortObj( PHB_FNAME pFileName ) case HB_P_INSTRING: case HB_P_LESS: case HB_P_LESSEQUAL: + case HB_P_MACROPOP: + case HB_P_MACROPOPALIASED: + case HB_P_MACROPUSH: + case HB_P_MACROPUSHALIASED: + case HB_P_MACROSYMBOL: + case HB_P_MACROTEXT: case HB_P_MINUS: case HB_P_MODULUS: case HB_P_MULT: diff --git a/harbour/source/compiler/genjava.c b/harbour/source/compiler/genjava.c index ee3701e9be..b6595afa36 100644 --- a/harbour/source/compiler/genjava.c +++ b/harbour/source/compiler/genjava.c @@ -203,6 +203,12 @@ void hb_compGenJava( PHB_FNAME pFileName ) case HB_P_INSTRING: case HB_P_LESS: case HB_P_LESSEQUAL: + case HB_P_MACROPOP: + case HB_P_MACROPOPALIASED: + case HB_P_MACROPUSH: + case HB_P_MACROPUSHALIASED: + case HB_P_MACROSYMBOL: + case HB_P_MACROTEXT: case HB_P_MINUS: case HB_P_MODULUS: case HB_P_MULT: diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index 644cd091bd..98977b8493 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -59,17 +59,20 @@ static void hb_compInitVars( void ); static void hb_compGenOutput( int ); static void hb_compOutputFile( void ); -static char * RESERVED_FUNC( char * ); -static void hb_compCheckDuplVars( PVAR pVars, char * szVarName, int iVarScope ); /*checks for duplicate variables definitions */ -static void hb_compFieldGenPCode( BYTE , char * ); /* generates the pcode for database field */ -static int hb_compFieldGetVarPos( char *, PFUNCTION ); /* return if passed name is a field variable */ +static int hb_compFieldGetPos( char *, PFUNCTION ); /* return if passed name is a field variable */ +static int hb_compLocalGetPos( char * szVarName ); /* returns the order + 1 of a local variable */ +static int hb_compMemvarGetPos( char *, PFUNCTION ); /* return if passed name is a memvar variable */ +static int hb_compStaticGetPos( char *, PFUNCTION ); /* return if passed name is a static variable */ +static USHORT hb_compVariableGetPos( PVAR pVars, char * szVarName ); /* returns the order + 1 of a variable if defined or zero */ + +static void hb_compGenFieldPCode( BYTE , int, char *, PFUNCTION ); /* generates the pcode for database field */ +static void hb_compGenVariablePCode( BYTE , char * ); /* generates the pcode for undeclared variable */ +static void hb_compGenVarPCode( BYTE , char * ); /* generates the pcode for undeclared variable */ + static void hb_compFixReturns( void ); /* fixes all last defined function returns jumps offsets */ static PFUNCTION hb_compFunctionNew( char *, char ); /* creates and initialises the _FUNC structure */ -static int hb_compLocalVarGetPos( char * szVarName ); /* returns the order + 1 of a local variable */ -static int hb_compMemvarGetPos( char *, PFUNCTION ); /* return if passed name is a memvar variable */ -static void hb_compMemvarGenPCode( BYTE , char * ); /* generates the pcode for memvar variable */ -static USHORT hb_compVariableGetPos( PVAR pVars, char * szVarName ); /* returns the order + 1 of a variable if defined or zero */ -static void hb_compVariableGenPCode( BYTE , char * ); /* generates the pcode for undeclared variable */ +static void hb_compCheckDuplVars( PVAR pVars, char * szVarName, int iVarScope ); /*checks for duplicate variables definitions */ + void EXTERNAL_LINKAGE close_on_exit( void ); @@ -127,77 +130,7 @@ static BOOL hb_comp_bExternal = FALSE; */ static PEXTERN hb_comp_pExterns = NULL; -/* Table with parse warnings */ - -/* Table with reserved functions names - * NOTE: THIS TABLE MUST BE SORTED ALPHABETICALLY - */ -static const char * s_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" -}; +/* ************************************************************************* */ int main( int argc, char * argv[] ) { @@ -370,32 +303,6 @@ void hb_xfree( void * pMem ) /* frees fixed memory */ hb_compGenError( hb_comp_szErrors, 'F', ERR_MEMFREE, NULL, NULL ); } -/* ------------------------------------------------------------------------- */ - -/* checks if passed string is a reserved function name - */ -static char * RESERVED_FUNC( char * szName ) -{ - USHORT uiNum = 0; - int iFound = 1; - - while( uiNum < ( ( sizeof( s_szReservedFun ) / sizeof( char * ) ) ) && iFound != 0 ) - { - /* 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, s_szReservedFun[ uiNum ], 4 ); - if( iFound == 0 ) - iFound = strncmp( szName, s_szReservedFun[ uiNum ], strlen( szName ) ); - - ++uiNum; - } - - return iFound == 0 ? ( char * ) s_szReservedFun[ uiNum - 1 ] : NULL; -} - /* ------------------------------------------------------------------------- */ /** ACTIONS **/ /* ------------------------------------------------------------------------- */ @@ -655,6 +562,42 @@ void hb_compVariableAdd( char * szVarName, char cValueType ) } } +/* Generate an error if passed variable name cannot be used in macro + * expression. + * Only MEMVAR or undeclared (memvar will be assumed) variables can be used. + */ +BOOL hb_compVariableMacroCheck( char * szVarName ) +{ + BOOL bValid = FALSE; + + if( hb_compLocalGetPos( szVarName ) > 0 ) + hb_compGenError( hb_comp_szErrors, 'E', ERR_BAD_MACRO, szVarName, NULL ); + else if( hb_compStaticGetPos( szVarName, hb_comp_functions.pLast ) > 0 ) + hb_compGenError( hb_comp_szErrors, 'E', ERR_BAD_MACRO, szVarName, NULL ); + else if( hb_compFieldGetPos( szVarName, hb_comp_functions.pLast ) > 0 ) + hb_compGenError( hb_comp_szErrors, 'E', ERR_BAD_MACRO, szVarName, NULL ); + else if( ! hb_comp_bStartProc ) + { + if( hb_compMemvarGetPos( szVarName, hb_comp_functions.pLast ) == 0 ) + { + /* This is not a local MEMVAR + */ + if( hb_compFieldGetPos( szVarName, hb_comp_functions.pFirst ) > 0 ) + hb_compGenError( hb_comp_szErrors, 'E', ERR_BAD_MACRO, szVarName, NULL ); + else if( hb_compStaticGetPos( szVarName, hb_comp_functions.pFirst ) > 0 ) + hb_compGenError( hb_comp_szErrors, 'E', ERR_BAD_MACRO, szVarName, NULL ); + else + bValid = TRUE; /* undeclared variable */ + } + else + bValid = TRUE; + } + else + bValid = TRUE; /* undeclared variable */ + return bValid; +} + + PCOMSYMBOL hb_compSymbolAdd( char * szSymbolName, USHORT * pwPos ) { PCOMSYMBOL pSym = ( PCOMSYMBOL ) hb_xgrab( sizeof( COMSYMBOL ) ); @@ -683,21 +626,6 @@ PCOMSYMBOL hb_compSymbolAdd( char * szSymbolName, USHORT * pwPos ) return pSym; } -/* - * Function generates passed pcode for passed database field - */ -void hb_compFieldGenPCode( BYTE bPCode, char * szVarName ) -{ - USHORT wVar; - PCOMSYMBOL pVar; - - pVar = hb_compSymbolFind( szVarName, &wVar ); - if( ! pVar ) - pVar = hb_compSymbolAdd( szVarName, &wVar ); - pVar->cScope |= VS_MEMVAR; - hb_compGenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ) ); -} - /* * This function creates and initialises the _FUNC structure */ @@ -748,7 +676,7 @@ void hb_compFunctionAdd( char * szFunName, HB_SYMBOLSCOPE cScope, int iType ) hb_compGenError( hb_comp_szErrors, 'F', ERR_FUNC_DUPL, szFunName, NULL ); } - szFunction = RESERVED_FUNC( szFunName ); + szFunction = hb_compReservedName( 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 @@ -799,11 +727,6 @@ void hb_compFunctionAdd( char * szFunName, HB_SYMBOLSCOPE cScope, int iType ) } } -void hb_compGenPushFunRef( char * szName ) -{ - HB_SYMBOL_UNUSED( szName ); /* TODO: */ -} - PFUNCTION hb_compFunctionKill( PFUNCTION pFunc ) { @@ -979,7 +902,7 @@ USHORT hb_compVariableGetPos( PVAR pVars, char * szVarName ) /* returns the orde return 0; } -static int hb_compLocalVarGetPos( char * szVarName ) /* returns the order + 1 of a variable if defined or zero */ +static int hb_compLocalGetPos( char * szVarName ) /* returns the order + 1 of a variable if defined or zero */ { int iVar = 0; PFUNCTION pFunc = hb_comp_functions.pLast; @@ -1073,42 +996,41 @@ static int hb_compLocalVarGetPos( char * szVarName ) /* returns the order + 1 of return iVar; } -/* - * Gets position of passed static variables. +/* Checks if passed variable name is declared as STATIC + * Returns 0 if not found in STATIC list or its position in this list if found + * * All static variables are hold in a single array at runtime then positions * are numbered for whole PRG module. */ -int GetStaticVarPos( char * szVarName ) +static int hb_compStaticGetPos( char * szVarName, PFUNCTION pFunc ) { - int iPos; - PFUNCTION pFunc = hb_comp_functions.pLast; + int iVar; - /* 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 = hb_compVariableGetPos( pFunc->pStatics, szVarName ); - if( iPos ) - return iPos + pFunc->iStaticsBase; + while( pFunc->pOwner ) /* pOwner is not NULL if STATIC var := value is used */ + pFunc = pFunc->pOwner; - /* 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 ) + if( pFunc->szName ) + /* we are in a function/procedure -we don't need any tricks */ + iVar = hb_compVariableGetPos( pFunc->pStatics, szVarName ); + else { - iPos = hb_compVariableGetPos( hb_comp_functions.pFirst->pStatics, szVarName ); - if( iPos ) - return iPos; + /* 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 = hb_compVariableGetPos( pFunc->pStatics, szVarName ); } - return 0; + if( iVar ) + iVar += pFunc->iStaticsBase; + + return iVar; } /* 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 */ -static int hb_compFieldGetVarPos( char * szVarName, PFUNCTION pFunc ) +static int hb_compFieldGetPos( char * szVarName, PFUNCTION pFunc ) { int iVar; @@ -1339,126 +1261,63 @@ void hb_compLinePushIfInside( void ) /* generates the pcode with the currently c } /* - * Function generates passed pcode for passed variable name + * Function generates pcode for undeclared variable */ -static void hb_compVariableGenPCode( BYTE bPCode, char * szVarName ) +static void hb_compGenVariablePCode( 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 = hb_compFieldGetVarPos( szVarName, hb_comp_functions.pLast ); - if( wVar == 0 ) - { - /* Check if it is a MEMVAR declared in current function - */ - wVar = hb_compMemvarGetPos( 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 = hb_compFieldGetVarPos( szVarName, hb_comp_functions.pFirst ); - if( wVar == 0 ) - { - wVar = hb_compMemvarGetPos( 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). - * - */ + /* + * 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 ) + if( hb_comp_bForceMemvars || bPCode == HB_P_POPVARIABLE ) #else - if( hb_comp_bForceMemvars ) + if( hb_comp_bForceMemvars ) #endif - { - /* -v switch was used -> assume it is a memvar variable - */ - iType = VS_MEMVAR; - hb_compGenWarning( hb_comp_szWarnings, 'W', WARN_MEMVAR_ASSUMED, szVarName, NULL ); - } - else - hb_compGenWarning( hb_comp_szWarnings, 'W', WARN_AMBIGUOUS_VAR, szVarName, NULL ); - } - - if( iType == VS_FIELD ) - { /* variable is declared using FIELD statement */ - PVAR pField = hb_compVariableFind( 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_szErrors, 'E', ERR_INVALID_REFER, szVarName, NULL ); - /* - * Push alias symbol before the field symbol - */ - hb_compGenPushSymbol( hb_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_szErrors, 'E', ERR_INVALID_REFER, szVarName, NULL ); - } - } - else if( iType == VS_MEMVAR ) { - /* variable is declared or assumed MEMVAR */ + /* -v switch was used -> assume it is a memvar variable + */ + hb_compGenWarning( hb_comp_szWarnings, 'W', WARN_MEMVAR_ASSUMED, szVarName, NULL ); + if( bPCode == HB_P_POPVARIABLE ) bPCode = HB_P_POPMEMVAR; else if( bPCode == HB_P_PUSHVARIABLE ) bPCode = HB_P_PUSHMEMVAR; + else + bPCode = HB_P_PUSHMEMVARREF; } + else + hb_compGenWarning( hb_comp_szWarnings, 'W', WARN_AMBIGUOUS_VAR, szVarName, NULL ); - /* Check if this variable name is placed into the symbol table - */ - pSym = hb_compSymbolFind( szVarName, &wVar ); - if( ! pSym ) - pSym = hb_compSymbolAdd( szVarName, &wVar ); - pSym->cScope |= VS_MEMVAR; - hb_compGenPCode3( bPCode, HB_LOBYTE( wVar ), HB_HIBYTE( wVar ) ); + hb_compGenVarPCode( bPCode, szVarName ); +} + +/* Generate a pcode for a field variable + */ +void hb_compGenFieldPCode( BYTE bPCode, int wVar, char * szVarName, PFUNCTION pFunc ) +{ + PVAR pField = hb_compVariableFind( pFunc->pFields, wVar ); + + if( pField->szAlias ) + { /* the alias was specified in FIELD declaration + * Push alias symbol before the field symbol + */ + if( bPCode == HB_P_POPFIELD ) + bPCode = HB_P_POPALIASEDFIELD; + else if( bPCode == HB_P_PUSHFIELD ) + bPCode = HB_P_PUSHALIASEDFIELD; + + hb_compGenPushSymbol( hb_strdup( pField->szAlias ), 0 ); + } + hb_compGenVarPCode( bPCode, szVarName ); } /* - * Function generates passed pcode for passed memvar name + * Function generates passed pcode for passed runtime variable + * (field or memvar) */ -void hb_compMemvarGenPCode( BYTE bPCode, char * szVarName ) +void hb_compGenVarPCode( BYTE bPCode, char * szVarName ) { USHORT wVar; PCOMSYMBOL pSym; @@ -1493,24 +1352,96 @@ void hb_compGenMessageData( char * szMsg ) /* generates an underscore-symbol nam hb_compGenMessage( szResult ); } +/* Check variable in the following order: + * LOCAL variable + * local STATIC variable + * local FIELD variable + * local MEMVAR variable + * global STATIC variable + * global FIELD variable + * global MEMVAR variable + * (if not found - it is an undeclared variable) + */ void hb_compGenPopVar( char * szVarName ) /* generates the pcode to pop a value from the virtual machine stack onto a variable */ { int iVar; - iVar = hb_compLocalVarGetPos( szVarName ); + iVar = hb_compLocalGetPos( szVarName ); if( iVar ) + { + /* local variable + */ hb_compGenPCode3( HB_P_POPLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + } else { - iVar = GetStaticVarPos( szVarName ); + iVar = hb_compStaticGetPos( szVarName, hb_comp_functions.pLast ); if( iVar ) { + /* Static variable declared in current function + */ hb_compGenPCode3( HB_P_POPSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; } else { - hb_compVariableGenPCode( HB_P_POPVARIABLE, szVarName ); + iVar = hb_compFieldGetPos( szVarName, hb_comp_functions.pLast ); + if( iVar ) + { + /* field declared in current function + */ + hb_compGenFieldPCode( HB_P_POPFIELD, iVar, szVarName, hb_comp_functions.pLast ); + } + else + { + iVar = hb_compMemvarGetPos( szVarName, hb_comp_functions.pLast ); + if( iVar ) + { + /* Memvar variable declared in current functions + */ + hb_compGenVarPCode( HB_P_POPMEMVAR, szVarName ); + } + else + { + if( ! hb_comp_bStartProc ) + iVar = hb_compStaticGetPos( szVarName, hb_comp_functions.pFirst ); + if( iVar ) + { + /* Global static variable + */ + hb_compGenPCode3( HB_P_POPSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; + } + else + { + if( ! hb_comp_bStartProc ) + iVar = hb_compFieldGetPos( szVarName, hb_comp_functions.pFirst ); + if( iVar ) + { + /* Global field declaration + */ + hb_compGenFieldPCode( HB_P_POPFIELD, iVar, szVarName, hb_comp_functions.pFirst ); + } + else + { + if( ! hb_comp_bStartProc ) + iVar = hb_compMemvarGetPos( szVarName, hb_comp_functions.pFirst ); + if( iVar ) + { + /* Global Memvar variable declaration + */ + hb_compGenVarPCode( HB_P_POPMEMVAR, szVarName ); + } + else + { + /* undeclared variable + */ + hb_compGenVariablePCode( HB_P_POPVARIABLE, szVarName ); + } + } + } + } + } } } } @@ -1529,7 +1460,7 @@ void hb_compGenPopAliasedVar( char * szVarName, { if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) { /* M->variable */ - hb_compMemvarGenPCode( HB_P_POPMEMVAR, szVarName ); + hb_compGenVarPCode( HB_P_POPMEMVAR, szVarName ); } else { @@ -1538,7 +1469,7 @@ void hb_compGenPopAliasedVar( char * szVarName, iCmp = strncmp( szAlias, "MEMVAR", strlen( szAlias ) ); if( iCmp == 0 ) { /* MEMVAR-> or MEMVA-> or MEMV-> */ - hb_compMemvarGenPCode( HB_P_POPMEMVAR, szVarName ); + hb_compGenVarPCode( HB_P_POPMEMVAR, szVarName ); } else { /* field variable */ @@ -1547,12 +1478,12 @@ void hb_compGenPopAliasedVar( char * szVarName, iCmp = strncmp( szAlias, "FIELD", strlen( szAlias ) ); if( iCmp == 0 ) { /* FIELD-> */ - hb_compFieldGenPCode( HB_P_POPFIELD, szVarName ); + hb_compGenVarPCode( HB_P_POPFIELD, szVarName ); } else { /* database alias */ hb_compGenPushSymbol( hb_strdup( szAlias ), 0 ); - hb_compFieldGenPCode( HB_P_POPALIASEDFIELD, szVarName ); + hb_compGenVarPCode( HB_P_POPALIASEDFIELD, szVarName ); } } } @@ -1560,12 +1491,12 @@ void hb_compGenPopAliasedVar( char * szVarName, else { hb_compGenPushLong( lWorkarea ); - hb_compFieldGenPCode( HB_P_POPALIASEDFIELD, szVarName ); + hb_compGenVarPCode( HB_P_POPALIASEDFIELD, szVarName ); } } else /* Alias is already placed on stack */ - hb_compFieldGenPCode( HB_P_POPALIASEDFIELD, szVarName ); + hb_compGenVarPCode( HB_P_POPALIASEDFIELD, szVarName ); } /* generates the pcode to push a nonaliased variable value to the virtual @@ -1575,46 +1506,165 @@ void hb_compGenPushVar( char * szVarName ) { int iVar; - iVar = hb_compLocalVarGetPos( szVarName ); + iVar = hb_compLocalGetPos( szVarName ); if( iVar ) + { + /* local variable + */ hb_compGenPCode3( HB_P_PUSHLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + } else { - iVar = GetStaticVarPos( szVarName ); + iVar = hb_compStaticGetPos( szVarName, hb_comp_functions.pLast ); if( iVar ) { + /* Static variable declared in current function + */ hb_compGenPCode3( HB_P_PUSHSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; } else { - hb_compVariableGenPCode( HB_P_PUSHVARIABLE, szVarName ); + iVar = hb_compFieldGetPos( szVarName, hb_comp_functions.pLast ); + if( iVar ) + { + /* field declared in current function + */ + hb_compGenFieldPCode( HB_P_PUSHFIELD, iVar, szVarName, hb_comp_functions.pLast ); + } + else + { + iVar = hb_compMemvarGetPos( szVarName, hb_comp_functions.pLast ); + if( iVar ) + { + /* Memvar variable declared in current functions + */ + hb_compGenVarPCode( HB_P_PUSHMEMVAR, szVarName ); + } + else + { + if( ! hb_comp_bStartProc ) + iVar = hb_compStaticGetPos( szVarName, hb_comp_functions.pFirst ); + if( iVar ) + { + /* Global static variable + */ + hb_compGenPCode3( HB_P_PUSHSTATIC, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; + } + else + { + if( ! hb_comp_bStartProc ) + iVar = hb_compFieldGetPos( szVarName, hb_comp_functions.pFirst ); + if( iVar ) + { + /* Global field declaration + */ + hb_compGenFieldPCode( HB_P_PUSHFIELD, iVar, szVarName, hb_comp_functions.pFirst ); + } + else + { + if( ! hb_comp_bStartProc ) + iVar = hb_compMemvarGetPos( szVarName, hb_comp_functions.pFirst ); + if( iVar ) + { + /* Global Memvar variable declaration + */ + hb_compGenVarPCode( HB_P_PUSHMEMVAR, szVarName ); + } + else + { + /* undeclared variable + */ + hb_compGenVariablePCode( HB_P_PUSHVARIABLE, szVarName ); + } + } + } + } + } } } } void hb_compGenPushVarRef( char * szVarName ) /* generates the pcode to push a variable by reference to the virtual machine stack */ { - USHORT iVar; + int iVar; - iVar = hb_compLocalVarGetPos( szVarName ); + iVar = hb_compLocalGetPos( szVarName ); if( iVar ) + { + /* local variable + */ hb_compGenPCode3( HB_P_PUSHLOCALREF, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + } else { - iVar = GetStaticVarPos( szVarName ); + iVar = hb_compStaticGetPos( szVarName, hb_comp_functions.pLast ); if( iVar ) { + /* Static variable declared in current function + */ 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 - */ - hb_compVariableGenPCode( HB_P_PUSHMEMVARREF, szVarName ); + iVar = hb_compFieldGetPos( szVarName, hb_comp_functions.pLast ); + if( iVar ) + { + /* pushing fields by reference is not allowed */ + hb_compGenError( hb_comp_szErrors, 'E', ERR_INVALID_REFER, szVarName, NULL ); + } + else + { + iVar = hb_compMemvarGetPos( szVarName, hb_comp_functions.pLast ); + if( iVar ) + { + /* Memvar variable declared in current functions + */ + hb_compGenVarPCode( HB_P_PUSHMEMVARREF, szVarName ); + } + else + { + if( ! hb_comp_bStartProc ) + iVar = hb_compStaticGetPos( szVarName, hb_comp_functions.pFirst ); + if( iVar ) + { + /* Global static variable + */ + hb_compGenPCode3( HB_P_PUSHSTATICREF, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ) ); + hb_comp_functions.pLast->bFlags |= FUN_USES_STATICS; + } + else + { + if( ! hb_comp_bStartProc ) + iVar = hb_compFieldGetPos( szVarName, hb_comp_functions.pFirst ); + if( iVar ) + { + /* pushing fields by reference is not allowed */ + hb_compGenError( hb_comp_szErrors, 'E', ERR_INVALID_REFER, szVarName, NULL ); + } + else + { + if( ! hb_comp_bStartProc ) + iVar = hb_compMemvarGetPos( szVarName, hb_comp_functions.pFirst ); + if( iVar ) + { + /* Global Memvar variable declaration + */ + hb_compGenVarPCode( HB_P_PUSHMEMVARREF, szVarName ); + } + else + { + /* undeclared variable - field cannot be passed by the + * reference - assume the memvar + */ + hb_compGenVariablePCode( HB_P_PUSHMEMVARREF, szVarName ); + } + } + } + } + } } } } @@ -1637,7 +1687,7 @@ void hb_compGenPushAliasedVar( char * szVarName, */ if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) { /* M->variable */ - hb_compMemvarGenPCode( HB_P_PUSHMEMVAR, szVarName ); + hb_compGenVarPCode( HB_P_PUSHMEMVAR, szVarName ); } else { @@ -1646,7 +1696,7 @@ void hb_compGenPushAliasedVar( char * szVarName, iCmp = strncmp( szAlias, "MEMVAR", strlen( szAlias ) ); if( iCmp == 0 ) { /* MEMVAR-> or MEMVA-> or MEMV-> */ - hb_compMemvarGenPCode( HB_P_PUSHMEMVAR, szVarName ); + hb_compGenVarPCode( HB_P_PUSHMEMVAR, szVarName ); } else { /* field variable */ @@ -1655,12 +1705,12 @@ void hb_compGenPushAliasedVar( char * szVarName, iCmp = strncmp( szAlias, "FIELD", strlen( szAlias ) ); if( iCmp == 0 ) { /* FIELD-> */ - hb_compFieldGenPCode( HB_P_PUSHFIELD, szVarName ); + hb_compGenVarPCode( HB_P_PUSHFIELD, szVarName ); } else { /* database alias */ hb_compGenPushSymbol( hb_strdup( szAlias ), 0 ); - hb_compFieldGenPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + hb_compGenVarPCode( HB_P_PUSHALIASEDFIELD, szVarName ); } } } @@ -1668,12 +1718,12 @@ void hb_compGenPushAliasedVar( char * szVarName, else { hb_compGenPushLong( lWorkarea ); - hb_compFieldGenPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + hb_compGenVarPCode( HB_P_PUSHALIASEDFIELD, szVarName ); } } else /* Alias is already placed on stack */ - hb_compFieldGenPCode( HB_P_PUSHALIASEDFIELD, szVarName ); + hb_compGenVarPCode( HB_P_PUSHALIASEDFIELD, szVarName ); } void hb_compGenPushLogical( int iTrueFalse ) /* pushes a logical value on the virtual machine stack */ @@ -1696,10 +1746,17 @@ void hb_compGenPushDouble( double dNumber, BYTE bDec ) void hb_compGenPushFunCall( char * szFunName ) { - char * szFunction = RESERVED_FUNC( szFunName ); + char * szFunction; - /* If an abbreviated function name was used - change it for whole name */ - hb_compGenPushSymbol( ( szFunction ? hb_strdup( szFunction ) : szFunName ), 1 ); + szFunction = hb_compReservedName( szFunName ); + if( szFunction ) + { + /* Abbreviated function name was used - change it for whole name + */ + hb_compGenPushSymbol( hb_strdup( szFunction ), 1 ); + } + else + hb_compGenPushSymbol( szFunName, 1 ); } /* generates the pcode to push a integer number on the virtual machine stack */ @@ -1741,7 +1798,7 @@ void hb_compGenPushSymbol( char * szSymbolName, int iIsFunction ) if( iIsFunction ) { - char * pName = RESERVED_FUNC( szSymbolName ); + char * pName = hb_compReservedName( 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 diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index e7f26ffc29..2a251e9435 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -91,11 +91,14 @@ InvalidNumber [0-9]+\. HexNumber 0x[0-9A-F]+ Identifier (([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+)) +MacroVar \&{Identifier}[\.]? +MacroEnd \&{Identifier}\.({Identifier})|([0-9]+) +MacroId ({Identifier}\&(({Identifier}[\.]?)|({Identifier}\.({Identifier})|([0-9]+)))) +MacroTxt ({MacroVar}|{MacroEnd}|{MacroId})+ + TrueValue "."[t|y]"." FalseValue "."[f|n]"." -PseudoFunc {Identifier}"("+.*")"+ - Array {Identifier}[ \t]*"[" AtArray "}"[ \t]*"[" ExpArray ")"[ \t]*"[" @@ -361,7 +364,7 @@ Separator {SpaceTab} hb_comp_iState =DO; yyless( yyleng-5 ); } -{Separator}+[_a-zA-Z] { /* an identifier DO id WITH */ +{Separator}+[_a-zA-Z\&] { /* an identifier 'DO id WITH' or 'DO &id WITH' */ if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; unput( yytext[ yyleng-1 ] ); if( hb_comp_iState == LOOKUP ) @@ -756,8 +759,9 @@ Separator {SpaceTab} /* ************************************************************************ */ %} "#"{Separator}*"line" return LINE; -"loca"|"local" { BEGIN LOCAL_; +"loca"|"local" { yylval.string = hb_strupr( hb_strdup( yytext ) ); + BEGIN LOCAL_; } {Separator}+[_a-zA-Z] { /* an identifier after LOCAL */ unput( yytext[ yyleng-1 ] ); @@ -1143,7 +1147,7 @@ Separator {SpaceTab} ".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 ]; +[,\{\}\|\#\&\.\:\<\>\[\]\@] hb_comp_iState =OPERATOR; return yytext[ 0 ]; [\(] ++_iOpenBracket; hb_comp_iState =SEPARATOR; return yytext[ 0 ]; [\)] --_iOpenBracket; hb_comp_iState =SEPARATOR; return yytext[ 0 ]; @@ -1265,16 +1269,43 @@ Separator {SpaceTab} return '}'; } -{Identifier} { - if( hb_comp_bRestrictSymbolLength && strlen( yytext ) > 10 ) - { - yytext[ 10 ] = 0; - yyleng = 10; - } - yylval.string = hb_strupr( hb_strdup( yytext ) ); - hb_comp_iState =IDENTIFIER; - return IDENTIFIER; - } +{MacroVar} { + if( yytext[ yyleng-1 ] == '.' ) + yytext[ yyleng-1 ] = '\0'; + yylval.string = hb_strupr( hb_strdup( yytext+1 ) ); + hb_comp_iState = MACROVAR; + return MACROVAR; + } + +{MacroEnd} { + yylval.string = hb_strupr( hb_strdup( yytext ) ); + hb_comp_iState = MACROTEXT; + return MACROTEXT; + } + +{MacroId} { + yylval.string = hb_strupr( hb_strdup( yytext ) ); + hb_comp_iState = MACROTEXT; + return MACROTEXT; + } + +{MacroTxt} { + yylval.string = hb_strupr( hb_strdup( yytext ) ); + hb_comp_iState = MACROTEXT; + return MACROTEXT; + } + + +{Identifier} { + if( hb_comp_bRestrictSymbolLength && strlen( yytext ) > 10 ) + { + yytext[ 10 ] = 0; + yyleng = 10; + } + yylval.string = hb_strupr( hb_strdup( yytext ) ); + hb_comp_iState = IDENTIFIER; + return IDENTIFIER; + } %{ #ifdef __WATCOMC__ diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index 721089e199..d587030107 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -146,7 +146,7 @@ PTR_LOOPEXIT hb_comp_pLoops = NULL; %token INC DEC ALIASOP DOCASE CASE OTHERWISE ENDCASE ENDDO MEMVAR %token WHILE EXIT LOOP END FOR NEXT TO STEP LE GE FIELD IN PARAMETERS %token PLUSEQ MINUSEQ MULTEQ DIVEQ POWER EXPEQ MODEQ EXITLOOP -%token PRIVATE BEGINSEQ BREAK RECOVER USING DO WITH SELF LINE +%token PRIVATE BEGINSEQ BREAK RECOVER USING DO WITH SELF LINE MACROVAR MACROTEXT %token AS_NUMERIC AS_CHARACTER AS_LOGICAL AS_DATE AS_ARRAY AS_BLOCK AS_OBJECT DECLARE_FUN /*the lowest precedence*/ @@ -175,7 +175,7 @@ PTR_LOOPEXIT hb_comp_pLoops = NULL; %right '\n' ';' ',' /*the highest precedence*/ -%type IDENTIFIER LITERAL +%type IDENTIFIER LITERAL SendId MACROVAR MACROTEXT %type NUM_DOUBLE %type NUM_INTEGER %type NUM_LONG @@ -186,7 +186,7 @@ PTR_LOOPEXIT hb_comp_pLoops = NULL; %type WhileBegin %type IfElseIf Cases %type Argument ArgList ElemList BlockExpList BlockVarList BlockNoVar -%type DoProc DoArgument DoArgList +%type DoName DoProc DoArgument DoArgList %type PareExpList1 PareExpList2 PareExpList3 PareExpListN %type ExpList ExpList1 ExpList2 ExpList3 %type NumValue NumAlias @@ -200,7 +200,7 @@ PTR_LOOPEXIT hb_comp_pLoops = NULL; %type Variable VarAlias %type MacroVar MacroVarAlias %type MacroExpr MacroExprAlias -%type AliasVar AliasExpr +%type AliasId AliasVar AliasExpr %type VariableAt VariableAtAlias %type FunCall FunCallAlias %type ObjectData ObjectDataAlias @@ -284,7 +284,7 @@ Statement : ExecFlow CrlfStmnt { } | PareExpList CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } | ExprPreOp CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } | ExprPostOp CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } - | ExprOperEq CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } + | ExprOperEq CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } | ExprEqual CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } | ExprAssign CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } | DoProc CrlfStmnt { hb_compExprDelete( hb_compExprGenStatement( $1 ) ); } @@ -340,7 +340,7 @@ LineStat : Crlf { $$ = 0; hb_comp_bDontGenLineNum = TRUE; } ; Statements : LineStat { $$ = $1; } - | Statements LineStat { $$ += $1; } + | Statements LineStat { $$ += $2; } ; ExtList : IDENTIFIER { hb_compExternAdd( $1 ); } @@ -418,24 +418,21 @@ ArrayAtAlias : ArrayAt ALIASOP { $$ = $1; } Variable : IDENTIFIER { $$ = hb_compExprNewVar( $1 ); } ; -VarAlias : IDENTIFIER ALIASOP { $$ = hb_compExprNewSymbol( $1 ); } +VarAlias : IDENTIFIER ALIASOP { $$ = hb_compExprNewAlias( $1 ); } ; /* 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 ); } - ; +MacroVar : MACROVAR { $$ = hb_compExprNewMacro( NULL, '&', $1 ); } + | MACROTEXT { $$ = hb_compExprNewMacro( NULL, 0, $1 ); } +; MacroVarAlias : MacroVar ALIASOP { $$ = $1; } ; /* Macro expressions */ -MacroExpr : '&' PareExpList { $$ = hb_compExprNewMacro( $2, NULL ); } +MacroExpr : '&' PareExpList { $$ = hb_compExprNewMacro( $2, 0, NULL ); } ; MacroExprAlias : MacroExpr ALIASOP { $$ = $1; } @@ -445,7 +442,7 @@ MacroExprAlias : MacroExpr ALIASOP { $$ = $1; } */ /* special case: _FIELD-> and FIELD-> can be nested */ -FieldAlias : FIELD ALIASOP { $$ = hb_compExprNewSymbol( "FIELD" ); } +FieldAlias : FIELD ALIASOP { $$ = hb_compExprNewAlias( "FIELD" ); } | FIELD ALIASOP FieldAlias { $$ = $3; } ; @@ -466,25 +463,29 @@ FieldVarAlias : FieldAlias VarAlias { hb_compExprDelete( $1 ); $$ = | 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 ); } +AliasId : IDENTIFIER { $$ = hb_compExprNewVar( $1 ); } + | MacroVar { $$ = $1; } + ; + +AliasVar : NumAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | MacroVarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | MacroExprAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | PareExpListAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | NilAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | LiteralAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | LogicalAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | CodeBlockAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | SelfAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | ArrayAlias AliasId { $$ = hb_compErrorAlias( $1 ); } + | ArrayAtAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | VariableAtAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | IfInlineAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | FunCallAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | ObjectDataAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | ObjectMethodAlias AliasId { $$ = hb_compErrorAlias( $1 ); } /* QUESTION: Clipper reports error here - we can handle this */ + | VarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | FieldAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | FieldVarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } ; /* Aliased expressions @@ -493,11 +494,11 @@ AliasVar : NumAlias IDENTIFIER { $$ = hb_compExprNewAliasVar( $1, $2 * 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 ) ); } +AliasExpr : NumAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | VarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | MacroVarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | MacroExprAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | PareExpListAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } | FieldAlias PareExpList { $$ = hb_compErrorAlias( $2 ); } /* QUESTION: Clipper reports error here - we can handle it */ ; @@ -525,7 +526,8 @@ VariableAtAlias : VariableAt ALIASOP { $$ = $1; } /* Function call */ -FunCall : IDENTIFIER '(' ArgList ')' { $$ = hb_compExprNewFunCall( $1, $3 ); } +FunCall : IDENTIFIER '(' ArgList ')' { $$ = hb_compExprNewFunCall( hb_compExprNewSymbol( $1 ), $3 ); } + | MacroVar '(' ArgList ')' { $$ = hb_compExprNewFunCall( $1, $3 ); } ; ArgList : Argument { $$ = hb_compExprNewArgList( $1 ); } @@ -542,25 +544,29 @@ 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 ); } +SendId : IDENTIFIER { $$ = $1; } + | MacroVar { $$ = "&"; hb_compGenError( hb_comp_szErrors, 'E', ERR_INVALID_SEND, "&", NULL); } + ; + +ObjectData : NumValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | NilValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | LiteralValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | CodeBlock ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | Logical ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | SelfValue ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | Array ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | ArrayAt ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | Variable ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | AliasVar ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | AliasExpr ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | MacroVar ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | MacroExpr ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | FunCall ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | IfInline ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | PareExpList ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | VariableAt ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | ObjectMethod ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } + | ObjectData ':' SendId { $$ = hb_compExprNewSend( $1, $3 ); } ; ObjectDataAlias : ObjectData ALIASOP { $$ = $1; } @@ -929,7 +935,7 @@ PareExpList : PareExpList1 { $$ = $1; } | PareExpListN { $$ = $1; } ; -PareExpListAlias : PareExpList ALIASOP { $$ = hb_compExprReduce( $1 ); } +PareExpListAlias : PareExpList ALIASOP { $$ = $1; } ; ExpList1 : '(' EmptyExpression { $$ = hb_compExprNewList( $2 ); } @@ -1312,12 +1318,16 @@ RecoverUsing : RECOVER USING IDENTIFIER * DO .. WITH ++variable * will pass the value of variable not a reference */ -DoProc : DO IDENTIFIER +DoName : IDENTIFIER { $$ = hb_compExprNewSymbol( $1 ); } + | MacroVar { $$ = $1; } + ; + +DoProc : DO DoName { $$ = hb_compExprNewFunCall( $2, NULL ); } - | DO IDENTIFIER WITH DoArgList + | DO DoName WITH DoArgList { $$ = hb_compExprNewFunCall( $2, $4 ); } | WHILE WITH DoArgList - { $$ = hb_compExprNewFunCall( hb_strdup("WHILE"), $3 ); } + { $$ = hb_compExprNewFunCall( hb_compExprNewSymbol( hb_strdup("WHILE") ), $3 ); } ; DoArgList : ',' { $$ = hb_compExprAddListExpr( hb_compExprNewArgList( hb_compExprNewNil() ), hb_compExprNewNil() ); } diff --git a/harbour/source/compiler/hbgenerr.c b/harbour/source/compiler/hbgenerr.c index 179a27759a..886c6b8c94 100644 --- a/harbour/source/compiler/hbgenerr.c +++ b/harbour/source/compiler/hbgenerr.c @@ -79,6 +79,8 @@ char * hb_comp_szErrors[] = "Invalid alias expression: \'%s\'", "Invalid array index expression: \'%s\'", "Bound error: \'%s\'" + "Macro of declared symbol: \'%s\'", + "Invalid selector in send: \'%s\'" }; /* Table with parse warnings */ diff --git a/harbour/source/macro/Makefile b/harbour/source/macro/Makefile new file mode 100644 index 0000000000..d339bd827f --- /dev/null +++ b/harbour/source/macro/Makefile @@ -0,0 +1,40 @@ +# +# $Id$ +# + +ROOT = ../../ + +YACC_FLAGS = -p hb_comp + +YACC_SOURCE=macro.y + +YACC_HEADERS=\ + macro.h \ + hbsetup.h \ + pcode.h \ + hbdefs.h \ + +#NOTE: You can pass additional parameters that control the speed/size +# ratio of generated flex scanner. These parameters are: +# -Cf - fastest/biggest +# -CF +# -C - in between +# -Cm +# -Ce +# -Cem - slowest/smallest +# see Flex documentation for full set of switches +LEX_FLAGS = -Phb_comp -C + +LEX_SOURCE=macro.l + +LEX_HEADERS=\ + hbsetup.h \ + hberrors.h \ + hbdefs.h \ + macro.h \ + +C_SOURCES=macro.c \ + +LIBNAME=macro + +include $(TOP)$(ROOT)config/lib.cf diff --git a/harbour/source/macro/macro.c b/harbour/source/macro/macro.c new file mode 100644 index 0000000000..77676c327f --- /dev/null +++ b/harbour/source/macro/macro.c @@ -0,0 +1,669 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Compiler main file + * + * Copyright 1999 Ryszard Glab + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +/* this #define HAVE TO be placed before all #include directives + */ +#define HB_MACRO_SUPPORT + +#include "macro.h" + +/* TODO: + * include these variables in SET subsystem ? + */ +static BOOL hb_comp_bShortCuts = TRUE; /* .and. & .or. expressions shortcuts */ +static BOOL hb_comp_bUseName10 = FALSE; /* names limited to 10 characters */ + +/* ************************************************************************* */ + +/* Compile passes string into a pcode buffer + */ +static int hb_macroCompile( HB_MACRO_PTR pMacro, char * szString, int iFlag ) +{ + /* initialize the input buffer - it will be scanned by lex */ + pMacro->string = szString; + pMacro->length = strlen( szString ); + pMacro->pos = 0; + + /* initialize the output (pcode) buffer - it will be filled by yacc */ + pMacro->pCodeInfo = (HB_PCODE_INFO_PTR ) hb_xgrab( sizeof( HB_PCODE_INFO ) ); + pMacro->pCodeInfo->lPCodeSize = HB_PCODE_SIZE; + pMacro->pCodeInfo->lPCodePos = 0; + pMacro->pCodeInfo->pLocals = NULL; + pMacro->pCodeInfo->pPrev = NULL; + pMacro->pCodeInfo->pCode = ( BYTE * ) hb_xgrab( HB_PCODE_SIZE ); + + /* We have to specify if we want a push or pop operation because + * we are using different pcodes for these operations + */ + pMacro->Flags = iFlag; + + return hb_compParse( pMacro ); +} + +static void hb_macroDelete( HB_MACRO_PTR pMacro ) +{ + hb_xfree( (void *) pMacro->pCodeInfo->pCode ); + hb_xfree( (void *) pMacro->pCodeInfo ); +} + +static BOOL hb_macroCheckParam( HB_ITEM_PTR pItem ) +{ + BOOL bValid = TRUE; + + if( ! IS_STRING(pItem) ) + { + HB_ITEM_PTR pResult = hb_errRT_BASE_Subst( EG_ARG, 1080, NULL, "&" ); + + bValid = FALSE; + if( pResult ) + { + hb_stackPop(); + hb_vmPush( pResult ); + hb_itemRelease( pResult ); + bValid = TRUE; + } + } + return bValid; +} + +static void hb_macroRun( HB_MACRO_PTR pMacro ) +{ + hb_vmExecute( pMacro->pCodeInfo->pCode, pMacro->pSymbols ); +} + +static void hb_macroSyntaxError( HB_MACRO_PTR pMacro ) +{ + HB_ITEM_PTR pResult = hb_errRT_BASE_Subst( EG_SYNTAX, 1449, NULL, "&" ); + + if( pResult ) + { + hb_vmPush( pResult ); + hb_itemRelease( pResult ); + } + HB_SYMBOL_UNUSED( pMacro ); /* TODO: better error messagess */ +} + + +/* NOTE: + * This will be called when macro variable or macro expression is + * placed on the right side of the assignment or when it is used as + * a parameter. + */ +void hb_macroGetValue( HB_ITEM_PTR pItem, PHB_SYMB pTable ) +{ + if( hb_macroCheckParam( pItem ) ) + { + HB_MACRO struMacro; + int iStatus; + char * szString = pItem->item.asString.value; + + struMacro.bShortCuts = hb_comp_bShortCuts; + struMacro.bName10 = hb_comp_bUseName10; + struMacro.pSymbols = pTable; + iStatus = hb_macroCompile( &struMacro, szString, HB_P_MACROPUSH ); + + hb_stackPop(); /* remove compiled string */ + if( iStatus == HB_MACRO_OK && struMacro.status == HB_MACRO_OK ) + hb_macroRun( &struMacro ); + else + hb_macroSyntaxError( &struMacro ); + hb_macroDelete( &struMacro ); + } +} + +/* NOTE: + * This will be called when macro variable or macro expression is + * placed on the left side of the assignment + */ +void hb_macroSetValue( HB_ITEM_PTR pItem, PHB_SYMB pTable ) +{ + if( hb_macroCheckParam( pItem ) ) + { + HB_MACRO struMacro; + int iStatus; + char * szString = pItem->item.asString.value; + + struMacro.bShortCuts = hb_comp_bShortCuts; + struMacro.bName10 = hb_comp_bUseName10; + struMacro.pSymbols = pTable; + iStatus = hb_macroCompile( &struMacro, szString, HB_P_MACROPOP ); + + hb_stackPop(); /* remove compiled string */ + if( iStatus == HB_MACRO_OK && struMacro.status == HB_MACRO_OK ) + hb_macroRun( &struMacro ); + else + hb_macroSyntaxError( &struMacro ); + hb_macroDelete( &struMacro ); + } +} + +/* ************************************************************************* */ + +/* returns the order + 1 of a variable if defined or zero */ +int hb_compLocalVarGetPos( char * szVarName, HB_MACRO_DECL ) +{ + int iVar = 1; + HB_CBVAR_PTR pVars = HB_PCODE_DATA->pLocals; + + while( pVars ) + { + if( pVars->szName && ! strcmp( pVars->szName, szVarName ) ) + return iVar; + else + { + if( pVars->pNext ) + { + pVars = pVars->pNext; + iVar++; + } + else + return 0; + } + } + return 0; +} + + +ULONG hb_compGenJump( LONG lOffset, HB_MACRO_DECL ) +{ + /* TODO: We need a longer offset (longer then two bytes) + */ + if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) + hb_macroError( HB_MACRO_TOO_COMPLEX, HB_MACRO_PARAM ); + + hb_compGenPCode3( HB_P_JUMP, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ), HB_MACRO_PARAM ); + + return HB_PCODE_DATA->lPCodePos - 2; +} + +ULONG hb_compGenJumpFalse( LONG lOffset, HB_MACRO_DECL ) +{ + /* TODO: We need a longer offset (longer then two bytes) + */ + if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) + hb_macroError( HB_MACRO_TOO_COMPLEX, HB_MACRO_PARAM ); + + hb_compGenPCode3( HB_P_JUMPFALSE, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ), HB_MACRO_PARAM ); + + return HB_PCODE_DATA->lPCodePos - 2; +} + +void hb_compGenJumpThere( ULONG ulFrom, ULONG ulTo, HB_MACRO_DECL ) +{ + BYTE * pCode = HB_PCODE_DATA->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_macroError( HB_MACRO_TOO_COMPLEX, HB_MACRO_PARAM ); + + pCode[ ( ULONG ) ulFrom ] = HB_LOBYTE( lOffset ); + pCode[ ( ULONG ) ulFrom + 1 ] = HB_HIBYTE( lOffset ); +} + +void hb_compGenJumpHere( ULONG ulOffset, HB_MACRO_DECL ) +{ + hb_compGenJumpThere( ulOffset, HB_PCODE_DATA->lPCodePos, HB_MACRO_PARAM ); +} + +ULONG hb_compGenJumpTrue( LONG lOffset, HB_MACRO_DECL ) +{ + /* TODO: We need a longer offset (longer then two bytes) + */ + if( lOffset < ( LONG ) SHRT_MIN || lOffset > ( LONG ) SHRT_MAX ) + hb_macroError( HB_MACRO_TOO_COMPLEX, HB_MACRO_PARAM ); + + hb_compGenPCode3( HB_P_JUMPTRUE, HB_LOBYTE( lOffset ), HB_HIBYTE( lOffset ), HB_MACRO_PARAM ); + + return HB_PCODE_DATA->lPCodePos - 2; +} + +/* + * Function generates pcode for passed memvar name + */ +void hb_compMemvarGenPCode( BYTE bPCode, char * szVarName, HB_MACRO_DECL ) +{ + HB_DYNS_PTR pSym; + + /* Find the address of passed symbol - create the symbol if doesn't exist + */ + pSym = hb_dynsymGet( szVarName ); + hb_compGenPCode1( bPCode, HB_MACRO_PARAM ); + hb_compGenPCodeN( ( BYTE * )( &pSym ), sizeof( pSym ), HB_MACRO_PARAM ); +} + +/* generates the pcode to push a symbol on the virtual machine stack */ +void hb_compGenPushSymbol( char * szSymbolName, int iIsFunction, HB_MACRO_DECL ) +{ + HB_DYNS_PTR pSym; + + if( iIsFunction ) + { + char * pName = hb_compReservedName( 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_dynsymGet( szSymbolName ); + hb_compGenPCode1( HB_P_MPUSHSYM, HB_MACRO_PARAM ); + hb_compGenPCodeN( ( BYTE * ) &pSym, sizeof( pSym ), HB_MACRO_PARAM ); +} + +/* generates the pcode to push a long number on the virtual machine stack */ +void hb_compGenPushLong( long lNumber, HB_MACRO_DECL ) +{ + if( lNumber ) + { + hb_compGenPCode1( HB_P_PUSHLONG, HB_MACRO_PARAM ); + hb_compGenPCode1( ( ( char * ) &lNumber )[ 0 ], HB_MACRO_PARAM ); + hb_compGenPCode1( ( ( char * ) &lNumber )[ 1 ], HB_MACRO_PARAM ); + hb_compGenPCode1( ( ( char * ) &lNumber )[ 2 ], HB_MACRO_PARAM ); + hb_compGenPCode1( ( ( char * ) &lNumber )[ 3 ], HB_MACRO_PARAM ); + } + else + hb_compGenPCode1( HB_P_ZERO, HB_MACRO_PARAM ); +} + + +/* sends a message to an object */ +void hb_compGenMessage( char * szMsgName, HB_MACRO_DECL ) +{ + /* Find the address of passed symbol - create the symbol if doesn't exist + */ + HB_DYNS_PTR pSym = hb_dynsymGet( szMsgName ); + + hb_compGenPCode1( HB_P_MMESSAGE, HB_MACRO_PARAM ); + hb_compGenPCodeN( ( BYTE * ) &pSym, sizeof( pSym ), HB_MACRO_PARAM ); +} + +/* generates an underscore-symbol name for a data assignment */ +void hb_compGenMessageData( char * szMsg, HB_MACRO_DECL ) +{ + char * szResult = ( char * ) hb_xgrab( strlen( szMsg ) + 2 ); + + strcpy( szResult, "_" ); + strcat( szResult, szMsg ); + + hb_compGenMessage( szResult, HB_MACRO_PARAM ); +} + +/* generates the pcode to pop a value from the virtual machine stack onto a variable */ +void hb_compGenPopVar( char * szVarName, HB_MACRO_DECL ) +{ + int iVar; + + iVar = hb_compLocalVarGetPos( szVarName, HB_MACRO_PARAM ); + if( iVar ) + { + /* this is a codeblock parameter */ + hb_compGenPCode3( HB_P_POPLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_MACRO_PARAM ); + } + else + { + /* NOTE: In clipper all undeclared variables are assumed MEMVAR if + * they are popped however there is nno such assumption if avariable + * is pushed on the eval stack + */ + hb_compMemvarGenPCode( HB_P_MPOPMEMVAR, szVarName, HB_MACRO_PARAM ); + } +} + +/* generates the pcode to pop a value from the virtual machine stack onto + * an aliased variable + */ +void hb_compGenPopAliasedVar( char * szVarName, + BOOL bPushAliasValue, + char * szAlias, + long lWorkarea, HB_MACRO_DECL ) +{ + if( bPushAliasValue ) + { + if( szAlias ) + { + if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) + { /* M->variable */ + hb_compMemvarGenPCode( HB_P_MPOPMEMVAR, szVarName, HB_MACRO_PARAM ); + } + else + { + int iCmp = strncmp( szAlias, "MEMVAR", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "MEMVAR", strlen( szAlias ) ); + if( iCmp == 0 ) + { /* MEMVAR-> or MEMVA-> or MEMV-> */ + hb_compMemvarGenPCode( HB_P_MPOPMEMVAR, szVarName, HB_MACRO_PARAM ); + } + else + { /* field variable */ + iCmp = strncmp( szAlias, "FIELD", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "FIELD", strlen( szAlias ) ); + if( iCmp == 0 ) + { /* FIELD-> */ + hb_compMemvarGenPCode( HB_P_MPOPFIELD, szVarName, HB_MACRO_PARAM ); + } + else + { /* database alias */ + hb_compGenPushSymbol( hb_strdup( szAlias ), 0, HB_MACRO_PARAM ); + hb_compMemvarGenPCode( HB_P_MPOPALIASEDFIELD, szVarName, HB_MACRO_PARAM ); + } + } + } + } + else + { + hb_compGenPushLong( lWorkarea, HB_MACRO_PARAM ); + hb_compMemvarGenPCode( HB_P_MPOPALIASEDFIELD, szVarName, HB_MACRO_PARAM ); + } + } + else + /* Alias is already placed on stack */ + hb_compMemvarGenPCode( HB_P_MPOPALIASEDFIELD, szVarName, HB_MACRO_PARAM ); +} + +/* generates the pcode to push a nonaliased variable value to the virtual + * machine stack + */ +void hb_compGenPushVar( char * szVarName, HB_MACRO_DECL ) +{ + int iVar; + + iVar = hb_compLocalVarGetPos( szVarName, HB_MACRO_PARAM ); + if( iVar ) + { + /* this is a codeblock parameter */ + hb_compGenPCode3( HB_P_PUSHLOCAL, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_MACRO_PARAM ); + } + else + { + /* NOTE: In clipper all undeclared variables are assumed MEMVAR if + * they are popped however there is nno such assumption if avariable + * is pushed on the eval stack + */ + hb_compMemvarGenPCode( HB_P_MPUSHVARIABLE, szVarName, HB_MACRO_PARAM ); + } +} + +/* generates the pcode to push a variable by reference to the virtual machine stack */ +void hb_compGenPushVarRef( char * szVarName, HB_MACRO_DECL ) +{ + USHORT iVar; + + iVar = hb_compLocalVarGetPos( szVarName, HB_MACRO_PARAM ); + if( iVar ) + hb_compGenPCode3( HB_P_PUSHLOCALREF, HB_LOBYTE( iVar ), HB_HIBYTE( iVar ), HB_MACRO_PARAM ); + else + { + hb_compMemvarGenPCode( HB_P_MPUSHMEMVARREF, szVarName, HB_MACRO_PARAM ); + } +} + + /* generates the pcode to push an aliased variable value to the virtual + * machine stack + */ +void hb_compGenPushAliasedVar( char * szVarName, + BOOL bPushAliasValue, + char * szAlias, + long lWorkarea, HB_MACRO_DECL ) +{ + if( bPushAliasValue ) + { + if( szAlias ) + { + /* myalias->var + * FIELD->var + * MEMVAR->var + */ + if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) + { /* M->variable */ + hb_compMemvarGenPCode( HB_P_MPUSHMEMVAR, szVarName, HB_MACRO_PARAM ); + } + else + { + int iCmp = strncmp( szAlias, "MEMVAR", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "MEMVAR", strlen( szAlias ) ); + if( iCmp == 0 ) + { /* MEMVAR-> or MEMVA-> or MEMV-> */ + hb_compMemvarGenPCode( HB_P_MPUSHMEMVAR, szVarName, HB_MACRO_PARAM ); + } + else + { /* field variable */ + iCmp = strncmp( szAlias, "FIELD", 4 ); + if( iCmp == 0 ) + iCmp = strncmp( szAlias, "FIELD", strlen( szAlias ) ); + if( iCmp == 0 ) + { /* FIELD-> */ + hb_compMemvarGenPCode( HB_P_MPUSHFIELD, szVarName, HB_MACRO_PARAM ); + } + else + { /* database alias */ + hb_compGenPushSymbol( hb_strdup( szAlias ), 0, HB_MACRO_PARAM ); + hb_compMemvarGenPCode( HB_P_MPUSHALIASEDFIELD, szVarName, HB_MACRO_PARAM ); + } + } + } + } + else + { + hb_compGenPushLong( lWorkarea, HB_MACRO_PARAM ); + hb_compMemvarGenPCode( HB_P_MPUSHALIASEDFIELD, szVarName, HB_MACRO_PARAM ); + } + } + else + /* Alias is already placed on stack */ + hb_compMemvarGenPCode( HB_P_MPUSHALIASEDFIELD, szVarName, HB_MACRO_PARAM ); +} + +/* pushes a logical value on the virtual machine stack , */ +void hb_compGenPushLogical( int iTrueFalse, HB_MACRO_DECL ) +{ + if( iTrueFalse ) + hb_compGenPCode1( HB_P_TRUE, HB_MACRO_PARAM ); + else + hb_compGenPCode1( HB_P_FALSE, HB_MACRO_PARAM ); +} + +/* generates the pcode to push a double number on the virtual machine stack */ +void hb_compGenPushDouble( double dNumber, BYTE bDec, HB_MACRO_DECL ) +{ + hb_compGenPCode1( HB_P_PUSHDOUBLE, HB_MACRO_PARAM ); + hb_compGenPCodeN( ( BYTE * ) &dNumber, sizeof( double ), HB_MACRO_PARAM ); + hb_compGenPCode1( bDec, HB_MACRO_PARAM ); +} + +void hb_compGenPushFunCall( char * szFunName, HB_MACRO_DECL ) +{ + char * szFunction; + + szFunction = hb_compReservedName( szFunName ); + if( szFunction ) + { + /* Abbreviated function name was used - change it for whole name + */ + hb_compGenPushSymbol( szFunction, 1, HB_MACRO_PARAM ); + } + else + hb_compGenPushSymbol( szFunName, 1, HB_MACRO_PARAM ); +} + +/* generates the pcode to push a string on the virtual machine stack */ +void hb_compGenPushString( char * szText, ULONG ulStrLen, HB_MACRO_DECL ) +{ + hb_compGenPCode3( HB_P_PUSHSTR, HB_LOBYTE( ulStrLen ), HB_HIBYTE( ulStrLen ), HB_MACRO_PARAM ); + hb_compGenPCodeN( ( BYTE * ) szText, ulStrLen, HB_MACRO_PARAM ); +} + + +void hb_compGenPCode1( BYTE byte, HB_MACRO_DECL ) +{ + HB_PCODE_INFO_PTR pFunc = HB_PCODE_DATA; + + if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 1 ) + pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += HB_PCODE_SIZE ); + + pFunc->pCode[ pFunc->lPCodePos++ ] = byte; +} + +void hb_compGenPCode3( BYTE byte1, BYTE byte2, BYTE byte3, HB_MACRO_DECL ) +{ + HB_PCODE_INFO_PTR pFunc = HB_PCODE_DATA; + + if( ( pFunc->lPCodeSize - pFunc->lPCodePos ) < 3 ) + pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize += HB_PCODE_SIZE ); + + pFunc->pCode[ pFunc->lPCodePos++ ] = byte1; + pFunc->pCode[ pFunc->lPCodePos++ ] = byte2; + pFunc->pCode[ pFunc->lPCodePos++ ] = byte3; +} + +void hb_compGenPCodeN( BYTE * pBuffer, ULONG ulSize, HB_MACRO_DECL ) +{ + HB_PCODE_INFO_PTR pFunc = HB_PCODE_DATA; + + if( pFunc->lPCodePos + ulSize > pFunc->lPCodeSize ) + { + /* not enough free space in pcode buffer - increase it */ + pFunc->lPCodeSize += ( ( ( ulSize / HB_PCODE_SIZE ) + 1 ) * HB_PCODE_SIZE ); + pFunc->pCode = ( BYTE * ) hb_xrealloc( pFunc->pCode, pFunc->lPCodeSize ); + } + + memcpy( pFunc->pCode + pFunc->lPCodePos, pBuffer, ulSize ); + pFunc->lPCodePos += ulSize; +} + +/* ************************************************************************* */ + +void hb_macroError( int iError, HB_MACRO_DECL ) +{ + HB_MACRO_DATA->status = iError; +} + +/* + * Start a new pcode buffer for a codeblock +*/ +void hb_compCodeBlockStart( HB_MACRO_DECL ) +{ + HB_PCODE_INFO_PTR pCB = ( HB_PCODE_INFO_PTR ) hb_xgrab( sizeof( HB_PCODE_INFO ) ); + + /* replace current pcode buffer with the new one + */ + pCB->pPrev = HB_PCODE_DATA; + HB_PCODE_DATA = pCB; + + pCB->pCode = ( BYTE * ) hb_xgrab( HB_PCODE_SIZE ); + pCB->lPCodeSize = HB_PCODE_SIZE; + pCB->lPCodePos = 0; + pCB->pLocals = NULL; +} + +void hb_compCodeBlockEnd( HB_MACRO_DECL ) +{ + HB_PCODE_INFO_PTR pCodeblock; /* pointer to the current codeblock */ + USHORT wSize; + USHORT wParms = 0; /* number of codeblock parameters */ + HB_CBVAR_PTR pVar, pFree; + + /* a currently processed codeblock */ + pCodeblock = HB_PCODE_DATA; + + /* return to pcode buffer of a codeblock in which the current + * codeblock was defined + */ + HB_PCODE_DATA = pCodeblock->pPrev; + + /* 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 codeblock parameters */ + pVar = pCodeblock->pLocals; + while( pVar ) + { + pVar = pVar->pNext; + ++wParms; + } + + /*NOTE: 8 = HB_P_MPUSHBLOCK + USHORT( size ) + USHORT( wParams ) + USHORT( 0 ) + _ENDBLOCK + * runtime compiled codeblock cannot reference local variables defined in a + * function + */ + wSize = ( USHORT ) pCodeblock->lPCodePos + 8; + + /*NOTE: HB_P_MPUSHBLOCK differs from HB_P_PUSHBLOCK - the pcode + * is stored in dynamic memory pool instead of static memory + */ + hb_compGenPCode3( HB_P_MPUSHBLOCK, HB_LOBYTE( wSize ), HB_HIBYTE( wSize ), HB_MACRO_PARAM ); + hb_compGenPCode1( HB_LOBYTE( wParms ), HB_MACRO_PARAM ); + hb_compGenPCode1( HB_HIBYTE( wParms ), HB_MACRO_PARAM ); + hb_compGenPCode1( 0, HB_MACRO_PARAM ); + hb_compGenPCode1( 0, HB_MACRO_PARAM ); + + /* copy a codeblock pcode buffer */ + hb_compGenPCodeN( pCodeblock->pCode, pCodeblock->lPCodePos, HB_MACRO_PARAM ); + hb_compGenPCode1( HB_P_ENDBLOCK, HB_MACRO_PARAM ); /* finish the codeblock */ + + /* free memory allocated for a codeblock */ + hb_xfree( ( void * ) pCodeblock->pCode ); + pVar = pCodeblock->pLocals; + while( pVar ) + { + /* free used variables */ + pFree = pVar; + hb_xfree( ( void * ) pFree->szName ); + pVar = pVar->pNext; + hb_xfree( ( void * ) pFree ); + } + hb_xfree( ( void * ) pCodeblock ); +} + +/* ************************************************************************ */ + +/* Include the common part of expression optimalizer + * NOTE: It cannot be compiled into a single library because the code + * required for macro compiler differs a little - we are passing additional + * parameter that holds macro compiler internal data + */ +#include "../compiler/expropt.c" + diff --git a/harbour/source/macro/macro.l b/harbour/source/macro/macro.l new file mode 100644 index 0000000000..0b6cf75b89 --- /dev/null +++ b/harbour/source/macro/macro.l @@ -0,0 +1,496 @@ +%option noyywrap +%option never-interactive +%{ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Macro Compiler LEX rules + * + * Copyright 1999 Antonio Linares + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +/* Compile using: flex -i -8 -omacrol.c -Phb_comp -C macro.l + +NOTE: -C controls the speed/size ratio of generated scanner +-Cf = fastest/biggest +-CF +-C = in between +-Cm +-Ce +-Cem = slowest/smallest +*/ + +#include +#include +#include +#include +#include "macro.h" +#include "macroy.h" +#include "hbsetup.h" /* main configuration file */ +#include "hberrors.h" +#include "hbdefs.h" + +/* NOTE: these symbols are used internally in bison.simple + */ +#undef alloca +#define alloca hb_xgrab +#undef malloc +#define malloc hb_xgrab + +/* declaration of yylex function + * NOTE: yylval is paassed automaticaly by bison if %pure_parser is used + */ +#undef YY_DECL +#define YY_DECL int yylex( YYSTYPE *yylval_ptr, HB_MACRO_PTR pMacro ) +#define YYLEX_PARAM pMacro + +/* code that fills input buffer + */ +#define YY_INPUT( buf, result, max_size ) result = 0; + + + + +#define LOOKUP 0 /* scan from the begining of line */ +#define OPERATOR -1 +#define SEPARATOR -2 +static int hb_comp_iState = LOOKUP; +static int _iOpenBracket = 0; + +/* Support for Array Index */ +static int iIndexSets = 0; +static int i_INDEX_STATE = 0; + +%} + +%{ +#ifdef __WATCOMC__ +/* disable warnings for unreachable code */ +#pragma warning 13 9 +#endif +%} + +SpaceTab [ \t]+ +Number ([0-9]+)|([0-9]*\.[0-9]+) +InvalidNumber [0-9]+\. +HexNumber 0x[0-9A-F]+ +Identifier (([a-zA-Z])|([_a-zA-Z][_a-zA-Z0-9]+)) + +MacroVar \&{Identifier}[\.]? +MacroEnd \&{Identifier}\.({Identifier})|([0-9]+) +MacroId {Identifier}({MacroVar}|{MacroEnd}) +MacroTxt ({MacroVar}|{MacroEnd}|{MacroId})+ + +Array {Identifier}[ \t]*"[" +AtArray "}"[ \t]*"[" +ExpArray ")"[ \t]*"[" +SubArray "]"[ \t]*"[" + +Separator {SpaceTab} + +%x STRING1 STRING2 STRING3 +%x FIELD_ IIF_ IF_ +%s INDEX + +%% + + +"&"("'"|\"|\[) { hb_macroError( EG_SYNTAX, YYLEX_PARAM ); } + +' BEGIN STRING1; +\" BEGIN STRING2; + +"="[ \t]*"[" { BEGIN STRING3; return '='; } +"+"[ \t]*"[" { BEGIN STRING3; return '+'; } +"-"[ \t]*"[" { BEGIN STRING3; return '-'; } +"*"[ \t]*"[" { BEGIN STRING3; return '*'; } +"/"[ \t]*"[" { BEGIN STRING3; return '/'; } +"%"[ \t]*"[" { BEGIN STRING3; return '%'; } +"$"[ \t]*"[" { BEGIN STRING3; return '$'; } +("<>"|"!=")[ \t]*"[" { BEGIN STRING3; return NE2; } +":="[ \t]*"[" { BEGIN STRING3; return INASSIGN; } +"=="[ \t]*"[" { BEGIN STRING3; return EQ; } +"<="[ \t]*"[" { BEGIN STRING3; return LE; } +">="[ \t]*"[" { BEGIN STRING3; return GE; } +"+="[ \t]*"[" { BEGIN STRING3; return PLUSEQ; } +"-="[ \t]*"[" { BEGIN STRING3; return MINUSEQ; } +"*="[ \t]*"[" { BEGIN STRING3; return MULTEQ; } +"/="[ \t]*"[" { BEGIN STRING3; return DIVEQ; } +"^="[ \t]*"[" { BEGIN STRING3; return EXPEQ; } +"%="[ \t]*"[" { BEGIN STRING3; return MODEQ; } +("**"|"^")[ \t]*"[" { BEGIN STRING3; return POWER; } +".and."[ \t]*"[" { BEGIN STRING3; return AND; } +".or."[ \t]*"[" { BEGIN STRING3; return OR; } +("!"|".not.")[ \t]*"[" { BEGIN STRING3; return NOT; } +(","|"{"|"<"|">"|"(")[ \t]*"[" { BEGIN STRING3; yyleng = 1; yytext[1] = 0; return yytext[ 0 ]; } + +\[ BEGIN STRING3; + +[^'^\n]* { hb_macroError( EG_SYNTAX, YYLEX_PARAM ); BEGIN 0; } +[^\"^\n]* { hb_macroError( EG_SYNTAX, YYLEX_PARAM ); BEGIN 0; } +[^\]]*\n { hb_macroError( EG_SYNTAX, YYLEX_PARAM ); BEGIN 0; } + +[^']*' { if( i_INDEX_STATE ) + BEGIN INDEX; + else + BEGIN 0; + + yyleng--; + yytext[yyleng] = 0; + yylval_ptr->string = hb_strdup( yytext ); + return LITERAL; + } + +[^\"]*\" { if( i_INDEX_STATE ) + BEGIN INDEX; + else + BEGIN 0; + + yyleng--; + yytext[yyleng] = 0; + yylval_ptr->string = hb_strdup( yytext ); + return LITERAL; + } + +[^\]]*\] { if( i_INDEX_STATE ) + BEGIN INDEX; + else + BEGIN 0; + + yyleng--; + yytext[yyleng] = 0; + yylval_ptr->string = hb_strdup( yytext ); + return LITERAL; + } + +\n { hb_macroError( EG_SYNTAX, YYLEX_PARAM ); } + +\[ { iIndexSets++; return yytext[ 0 ]; } + +\] { + iIndexSets-- ; + if( iIndexSets == 0 ) + { + /*printf( "\nIndex End\n" );*/ + + /* No longer in this state. */ + i_INDEX_STATE = 0; + BEGIN 0; + } + return yytext[ 0 ]; + } + +{SpaceTab} ; + +\n.* { + yyless( 1 ); + return '\n'; + } +%{ +/* ************************************************************************ */ +%} +"_fie"|"_fiel"|"_field" { + if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; + return FIELD; + } + +"fiel"|"field" { + if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; + hb_comp_iState =FIELD; + } + +"iif" { + if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; + return IIF; + } + +"if" { + if( i_INDEX_STATE ) BEGIN INDEX; else BEGIN 0; + return IF; + } + +"nil" return NIL; + +"qself"{SpaceTab}*\({SpaceTab}*\) return SELF; + +%{ +/* ************************************************************************ */ +%} + +"#" return NE1; +"=" return yytext[ 0 ]; +"+" return yytext[ 0 ]; +"-" return yytext[ 0 ]; +"*" return yytext[ 0 ]; +[\/] return yytext[ 0 ]; +"%" return yytext[ 0 ]; +"$" return yytext[ 0 ]; +"<>"|"!=" return NE2; +":=" return INASSIGN; +"==" return EQ; +"++" return INC; +"--" return DEC; +"->" return ALIASOP; +"<=" return LE; +">=" return GE; +"+=" return PLUSEQ; +"-=" return MINUSEQ; +"*=" return MULTEQ; +"/=" return DIVEQ; +"^=" return EXPEQ; +"%=" return MODEQ; +"**"|"^" return POWER; +".and." return AND; +".or." return OR; +"."[t|y]"." return TRUEVALUE; +"."[f|n]"." return FALSEVALUE; +"!"|".not." return NOT; +"::" unput( ':' ); unput( 'f' ); unput( 'l' ); unput( 'e' ); unput( 'S' ); +[,\{\}\|\#\&\.\:\<\>\[\]\@] return yytext[ 0 ]; +[\(] ++_iOpenBracket; return yytext[ 0 ]; +[\)] --_iOpenBracket; return yytext[ 0 ]; + + +{Number} { + char * ptr; + + yylval_ptr->valDouble.dNumber = atof( yytext ); + ptr = strchr( yytext, '.' ); + if( ptr ) + { + yylval_ptr->valDouble.bDec = strlen( ptr + 1 ); + yylval_ptr->valDouble.szValue = yytext ; + return NUM_DOUBLE; + } + else + { + if( ( double )LONG_MIN <= yylval_ptr->valDouble.dNumber && + yylval_ptr->valDouble.dNumber <= ( double )LONG_MAX ) + { + yylval_ptr->valLong.lNumber = ( long ) yylval_ptr->valDouble.dNumber; + yylval_ptr->valLong.szValue = yytext; + return NUM_LONG; + } + else + { + yylval_ptr->valDouble.bDec = 0; + yylval_ptr->valDouble.szValue = yytext; + return NUM_DOUBLE; + } + } +} + + +{HexNumber} { + long lNumber = 0; + + sscanf( yytext, "%lxI", &lNumber ); + + if( ( double )LONG_MIN <= lNumber && + lNumber <= ( double )LONG_MAX ) + { + yylval_ptr->valLong.lNumber = lNumber; + yylval_ptr->valLong.szValue = yytext; + return NUM_LONG; + } + else + { + yylval_ptr->valDouble.dNumber = lNumber; + yylval_ptr->valDouble.bDec = 0; + yylval_ptr->valDouble.szValue = yytext; + return NUM_DOUBLE; + } + } + +{Array} { + if( ! i_INDEX_STATE ) + { + BEGIN INDEX; + i_INDEX_STATE = 1; + } + + unput( '[' ); + yyleng--; + + /* Remove optional white space between Identifier and Index */ + while( yytext[ yyleng - 1 ] < 48 ) + yyleng--; + + yytext[yyleng] = 0; + + { + if( YYLEX_PARAM->bName10 && strlen( yytext ) > 10 ) + { + yytext[ 10 ] = 0; + yyleng = 10; + } + yylval_ptr->string = hb_strupr( hb_strdup( yytext ) ); + return IDENTIFIER; + } + } + +{ExpArray} { + /* Must be recursive */ + if( ! i_INDEX_STATE ) + { + BEGIN INDEX; + i_INDEX_STATE = 1; + } + + unput( '[' ); + --_iOpenBracket; + return ')'; + } + +{SubArray} { + /* Must be recursive */ + if( i_INDEX_STATE ) + { + BEGIN INDEX; + i_INDEX_STATE = 1; + } + + iIndexSets--; + + unput( '[' ); + return ']'; + } + +{AtArray} { + /* Must be recursive */ + if( ! i_INDEX_STATE ) + { + BEGIN INDEX; + i_INDEX_STATE = 1; + } + + unput( '[' ); + --_iOpenBracket; + return '}'; + } + +{MacroVar} { + if( yytext[ yyleng-1 ] == '.' ) + yytext[ yyleng-1 ] = '\0'; + yylval_ptr->string = hb_strupr( hb_strdup( yytext+1 ) ); + hb_comp_iState = MACROVAR; + return MACROVAR; + } + +{MacroEnd} { + yylval_ptr->string = hb_strupr( hb_strdup( yytext ) ); + hb_comp_iState = MACROTEXT; + return MACROTEXT; + } + +{MacroId} { + yylval_ptr->string = hb_strupr( hb_strdup( yytext ) ); + hb_comp_iState = MACROTEXT; + return MACROTEXT; + } + +{MacroTxt} { + yylval_ptr->string = hb_strupr( hb_strdup( yytext ) ); + hb_comp_iState = MACROTEXT; + return MACROTEXT; + } + +{Identifier} { + if( YYLEX_PARAM->bName10 && strlen( yytext ) > 10 ) + { + yytext[ 10 ] = 0; + yyleng = 10; + } + yylval_ptr->string = hb_strupr( hb_strdup( yytext ) ); + return IDENTIFIER; + } + +%% + +#ifdef __WATCOMC__ +/* enable warnings for unreachable code */ +#pragma warning 13 1 +#endif + + +void * hb_compFlexNew( HB_MACRO_PTR pMacro ) +{ + /* This creates the scanner buffer based on passed string. + * Unfortunately it creates a copy of this string - the string can be + * modified during scanning and the string have to end with TWO zero bytes + * NOTE: It must be used in macro.l because yy_scan_bytes is not + * visible in macro.y + */ + return (void *) yy_scan_bytes( pMacro->string, pMacro->length ); +} + +void hb_compFlexDelete( void * pBuffer ) +{ + yy_delete_buffer( ( YY_BUFFER_STATE ) pBuffer ); +} + +/* +static int hb_compInput( char * buf, int max_size, HB_MACRO_PTR pMacro ) +{ + int iRead; + + if( pMacro->length < max_size ) + { + memcpy( buf, pMacro->string, pMacro->length ); + buf[ pMacro->length++ ] = '\n'; + buf[ pMacro->length ] = 0; + iRead = pMacro->length; + } + else + { + int iLen = pMacro->length - pMacro->pos; + if( iLen <= 0 ) + { + iRead = 0; + } + else if( iLen >= max_size ) + { + iRead = max_size; + memcpy( buf, pMacro->string + pMacro->pos, iRead ); + pMacro->pos += iRead; + } + else + { + memcpy( buf, pMacro->string + pMacro->pos, iLen ); + buf[ iLen++ ] = '\n'; + buf[ iLen ] = 0; + iRead = iLen; + pMacro->pos += iRead; + } + } + return iRead; +} +*/ + diff --git a/harbour/source/macro/macro.y b/harbour/source/macro/macro.y new file mode 100644 index 0000000000..38ad552084 --- /dev/null +++ b/harbour/source/macro/macro.y @@ -0,0 +1,721 @@ +%pure_parser +%{ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Macro compiler YACC rules and actions + * + * Copyright 1999 Antonio Linares + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +/* TODO list + * 1) jumps longer then 2^15 bytes + * 2) Change the pcode generated by ::cVar from Self:cVar to QSELF():cVar + * 3) Support this syntax: nPtr := @Hello() + */ + +/* this #define HAVE TO be placed before all #include directives + */ +#define HB_MACRO_SUPPORT + +#include "macro.h" + +/* Compile using: bison -d -p hb_comp macro.y */ + +/* NOTE: these symbols are used internally in bison.simple + */ +#undef alloca +#define alloca hb_xgrab +#undef malloc +#define malloc hb_xgrab + +/* yacc/lex related definitions + */ +#undef YYPARSE_PARAM +#define YYPARSE_PARAM HB_MACRO_PARAM /* parameter passed to yyparse function - it have to be of 'void *' type */ +#undef YYLEX_PARAM +#define YYLEX_PARAM ( (HB_MACRO_PTR)YYPARSE_PARAM ) /* additional parameter passed to yylex */ + +extern void * hb_compFlexNew( HB_MACRO_PTR ); +extern void hb_compFlexDelete( void * ); + +extern void yyerror( char * ); /* parsing error management function */ + +/* Standard checking for valid expression creation + */ +#define HB_MACRO_CHECK( pExpr ) \ + if( HB_MACRO_DATA->status != HB_MACRO_OK ) \ + { \ + hb_compExprDelete( pExpr, HB_MACRO_PARAM ); \ + YYABORT; \ + } + +%} + +%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 temporary integer number */ + long lNumber; /* to hold a temporary long number */ + struct + { + 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 */ + char * szValue; + } valDouble; + HB_EXPR_PTR asExpr; + void * pVoid; /* to hold any memory structure we may need */ +}; + +%{ +/* This must be placed after the above union - the union is + * typedef-ined to YYSTYPE + */ +int yylex( YYSTYPE *, HB_MACRO_PTR ); +%} + + +%token IDENTIFIER NIL NUM_DOUBLE INASSIGN NUM_LONG +%token IIF IF LITERAL TRUEVALUE FALSEVALUE +%token AND OR NOT EQ NE1 NE2 INC DEC ALIASOP SELF +%token LE GE FIELD MACROVAR MACROTEXT +%token PLUSEQ MINUSEQ MULTEQ DIVEQ POWER EXPEQ MODEQ + +/*the lowest precedence*/ +/*postincrement and postdecrement*/ +%left POST +/*assigment - from right to left*/ +%right INASSIGN +%right PLUSEQ MINUSEQ +%right MULTEQ DIVEQ MODEQ +%right EXPEQ +/*logical operators*/ +%right OR +%right AND +%right NOT +/*relational operators*/ +%right '=' '<' '>' EQ NE1 NE2 LE GE '$' +/*mathematical operators*/ +%right '+' '-' +%right '*' '/' '%' +%right POWER +%right UNARY +/*preincrement and predecrement*/ +%right PRE +/*special operators*/ +%right ALIASOP '&' '@' +%right ',' +/*the highest precedence*/ + +%type IDENTIFIER LITERAL MACROVAR MACROTEXT +%type NUM_DOUBLE +%type NUM_LONG +%type Argument ArgList ElemList BlockExpList BlockVarList BlockNoVar +%type NumValue NumAlias +%type NilValue +%type LiteralValue +%type CodeBlock +%type Logical +%type SelfValue +%type Array +%type ArrayAt +%type Variable VarAlias +%type MacroVar MacroVarAlias +%type MacroExpr MacroExprAlias +%type AliasId AliasVar AliasExpr +%type VariableAt +%type FunCall +%type ObjectData +%type ObjectMethod +%type IfInline +%type ExpList PareExpList PareExpListAlias +%type Expression SimpleExpression +%type EmptyExpression +%type ExprAssign ExprOperEq ExprPreOp ExprPostOp +%type ExprMath ExprBool ExprRelation ExprUnary +%type ExprPlusEq ExprMinusEq ExprMultEq ExprDivEq ExprModEq ExprExpEq +%type ArrayIndex IndexList +%type FieldAlias FieldVarAlias +%type PostOp + +%% + +Main : Expression '\n' { if( HB_MACRO_DATA->Flags & HB_P_MACROPUSH ) + hb_compExprDelete( hb_compExprGenPush( $1, HB_MACRO_PARAM ), HB_MACRO_PARAM ); + else + hb_compExprDelete( hb_compExprGenPop( $1, HB_MACRO_PARAM ), HB_MACRO_PARAM ); + hb_compGenPCode1( HB_P_ENDPROC, HB_MACRO_PARAM ); + } + | Expression { if( HB_MACRO_DATA->Flags & HB_P_MACROPUSH ) + hb_compExprDelete( hb_compExprGenPush( $1, HB_MACRO_PARAM ), HB_MACRO_PARAM ); + else + hb_compExprDelete( hb_compExprGenPop( $1, HB_MACRO_PARAM ), HB_MACRO_PARAM ); + hb_compGenPCode1( HB_P_ENDPROC, HB_MACRO_PARAM ); + } + | error { hb_macroError( EG_SYNTAX, HB_MACRO_PARAM ); } +; + +/* Numeric values + */ +NumValue : NUM_DOUBLE { $$ = hb_compExprNewDouble( $1.dNumber, $1.bDec ); } + | NUM_LONG { $$ = hb_compExprNewLong( $1.lNumber ); } + ; + +NumAlias : NUM_LONG ALIASOP { $$ = hb_compExprNewLong( $1.lNumber ); } +; + +/* NIL value + */ +NilValue : NIL { $$ = hb_compExprNewNil(); } +; + +/* Literal string value + */ +LiteralValue : LITERAL { $$ = hb_compExprNewString( $1 ); } +; + +/* Logical value + */ +Logical : TRUEVALUE { $$ = hb_compExprNewLogical( TRUE ); } + | FALSEVALUE { $$ = hb_compExprNewLogical( FALSE ); } + ; + +/* SELF value and expressions + */ +SelfValue : SELF { $$ = hb_compExprNewSelf(); } +; + +/* Literal array + */ +Array : '{' ElemList '}' { $$ = hb_compExprNewArray( $2 ); } + ; + +/* Literal array access + */ +ArrayAt : Array ArrayIndex { $$ = $2; } +; + +/* Variables + */ +Variable : IDENTIFIER { $$ = hb_compExprNewVar( $1 ); } +; + +VarAlias : IDENTIFIER ALIASOP { $$ = hb_compExprNewAlias( $1 ); } +; + +/* Macro variables - this can signal compilation errors + */ +MacroVar : MACROVAR { $$ = hb_compExprNewMacro( NULL, '&', $1 ); + HB_MACRO_CHECK( $$ ); + } + | MACROTEXT { $$ = hb_compExprNewMacro( NULL, 0, $1 ); + HB_MACRO_CHECK( $$ ); + } +; + +MacroVarAlias : MacroVar ALIASOP { $$ = $1; } +; + +/* Macro expressions + */ +MacroExpr : '&' PareExpList { $$ = hb_compExprNewMacro( $2, 0, NULL ); } +; + +MacroExprAlias : MacroExpr ALIASOP { $$ = $1; } +; + +/* Aliased variables + */ +/* special case: _FIELD-> and FIELD-> can be nested + */ +FieldAlias : FIELD ALIASOP { $$ = hb_compExprNewAlias( "FIELD" ); } + | FIELD ALIASOP FieldAlias { $$ = $3; } + ; + +/* ignore _FIELD-> or FIELD-> if a real alias is specified + */ +FieldVarAlias : FieldAlias VarAlias { hb_compExprDelete( $1, HB_MACRO_PARAM ); $$ = $2; } + | FieldAlias NumAlias { hb_compExprDelete( $1, HB_MACRO_PARAM ); $$ = $2; } + | FieldAlias PareExpListAlias { hb_compExprDelete( $1, HB_MACRO_PARAM ); $$ = $2; } + | FieldAlias MacroVarAlias { hb_compExprDelete( $1, HB_MACRO_PARAM ); $$ = $2; } + | FieldAlias MacroExprAlias { hb_compExprDelete( $1, HB_MACRO_PARAM ); $$ = $2; } + ; + +AliasId : IDENTIFIER { $$ = hb_compExprNewVar( $1 ); } + | MacroVar { $$ = $1; } + ; + +AliasVar : NumAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | MacroVarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | MacroExprAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | PareExpListAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | VarAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | FieldAlias AliasId { $$ = hb_compExprNewAliasVar( $1, $2 ); } + | FieldVarAlias AliasId { $$ = 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, $2 ); } + | VarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | MacroVarAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | MacroExprAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + | PareExpListAlias PareExpList { $$ = hb_compExprNewAliasExpr( $1, $2 ); } + ; + +/* 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; } + ; + +/* Function call + */ +FunCall : IDENTIFIER '(' ArgList ')' { $$ = hb_compExprNewFunCall( hb_compExprNewSymbol( $1 ), $3, HB_MACRO_PARAM ); + HB_MACRO_CHECK( $$ ); + } + | MacroVar '(' ArgList ')' { $$ = hb_compExprNewFunCall( $1, $3, HB_MACRO_PARAM ); + HB_MACRO_CHECK( $$ ); + } +; + +ArgList : Argument { $$ = hb_compExprNewArgList( $1 ); } + | ArgList ',' Argument { $$ = hb_compExprAddListExpr( $1, $3 ); } + ; + +Argument : EmptyExpression { $$ = $1; } + | '@' IDENTIFIER { $$ = hb_compExprNewVarRef( $2 ); } + | '@' IDENTIFIER '(' ')' { $$ = hb_compExprNewFunRef( $2 ); } + ; + +/* 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 ); } + ; + +/* Object's method + */ +ObjectMethod : ObjectData '(' ArgList ')' { $$ = hb_compExprNewMethodCall( $1, $3 ); } + ; + +SimpleExpression : + NumValue + | NilValue { $$ = $1; } + | LiteralValue { $$ = $1; } + | CodeBlock { $$ = $1; } + | Logical { $$ = $1; } + | SelfValue { $$ = $1; } + | Array { $$ = $1; } + | ArrayAt { $$ = $1; } + | AliasVar { $$ = $1; } + | MacroVar { $$ = $1; } + | MacroExpr { $$ = $1; } + | Variable { $$ = $1; } + | VariableAt { $$ = $1; } + | FunCall { $$ = $1; } + | IfInline { $$ = $1; } + | ObjectData { $$ = $1; } + | ObjectMethod { $$ = $1; } + | AliasExpr { $$ = $1; } + | ExprAssign { $$ = $1; } + | ExprOperEq { $$ = $1; } + | ExprPostOp { $$ = $1; } + | ExprPreOp { $$ = $1; } + | ExprUnary { $$ = $1; } + | ExprMath { $$ = $1; } + | ExprBool { $$ = $1; } + | ExprRelation { $$ = $1; } +; + +Expression : SimpleExpression { $$ = $1; HB_MACRO_CHECK( $$ ); } + | PareExpList { $$ = $1; HB_MACRO_CHECK( $$ ); } +; + +EmptyExpression: /* nothing => nil */ { $$ = hb_compExprNewEmpty(); } + | Expression +; + +/* NOTE: PostOp can be used in one context only - it uses $0 rule + * (the rule that stands before PostOp) + */ +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 ); } + ; + +ExprUnary : NOT Expression { $$ = hb_compExprNewNot( $2 ); } + | '-' Expression %prec UNARY { $$ = hb_compExprNewNegate( $2 ); } + | '+' Expression %prec UNARY { $$ = $2; } + ; + +ExprAssign : NumValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | NilValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | LiteralValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | CodeBlock INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | Logical INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | SelfValue INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | Array INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | ArrayAt INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | Variable INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | MacroVar INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | MacroExpr INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | AliasVar INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | AliasExpr INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | VariableAt INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | PareExpList INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | IfInline INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | FunCall INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | ObjectData INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + | ObjectMethod INASSIGN Expression { $$ = hb_compExprAssign( $1, $3 ); } + ; + +ExprPlusEq : NumValue PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | NilValue PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | LiteralValue PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | CodeBlock PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | Logical PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | SelfValue PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | Array PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | ArrayAt PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | Variable PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroVar PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroExpr PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasVar PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasExpr PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | VariableAt PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | PareExpList PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | IfInline PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | FunCall PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectData PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectMethod PLUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlusEq( $1 ), $3, HB_MACRO_PARAM ); } + ; + +ExprMinusEq : NumValue MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | NilValue MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | LiteralValue MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | CodeBlock MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | Logical MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | SelfValue MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | Array MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | ArrayAt MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | Variable MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroVar MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroExpr MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasVar MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasExpr MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | VariableAt MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | PareExpList MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | IfInline MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | FunCall MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectData MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectMethod MINUSEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinusEq( $1 ), $3, HB_MACRO_PARAM ); } + ; + +ExprMultEq : NumValue MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | NilValue MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | LiteralValue MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | CodeBlock MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | Logical MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | SelfValue MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | Array MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | ArrayAt MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | Variable MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroVar MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroExpr MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasVar MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasExpr MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | VariableAt MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | PareExpList MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | IfInline MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | FunCall MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectData MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectMethod MULTEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewMultEq( $1 ), $3, HB_MACRO_PARAM ); } + ; + +ExprDivEq : NumValue DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | NilValue DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | LiteralValue DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | CodeBlock DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | Logical DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | SelfValue DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | Array DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | ArrayAt DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | Variable DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroVar DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroExpr DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasVar DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasExpr DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | VariableAt DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | PareExpList DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | IfInline DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | FunCall DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectData DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectMethod DIVEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewDivEq( $1 ), $3, HB_MACRO_PARAM ); } + ; + +ExprModEq : NumValue MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | NilValue MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | LiteralValue MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | CodeBlock MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | Logical MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | SelfValue MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | Array MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | ArrayAt MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | Variable MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroVar MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroExpr MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasVar MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasExpr MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | VariableAt MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | PareExpList MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | IfInline MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | FunCall MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectData MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectMethod MODEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewModEq( $1 ), $3, HB_MACRO_PARAM ); } + ; + +ExprExpEq : NumValue EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | NilValue EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | LiteralValue EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | CodeBlock EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | Logical EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | SelfValue EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | Array EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | ArrayAt EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | Variable EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroVar EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | MacroExpr EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasVar EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | AliasExpr EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | VariableAt EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | PareExpList EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | IfInline EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | FunCall EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectData EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + | ObjectMethod EXPEQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewExpEq( $1 ), $3, HB_MACRO_PARAM ); } + ; + +ExprOperEq : ExprPlusEq { $$ = $1; } + | ExprMinusEq { $$ = $1; } + | ExprMultEq { $$ = $1; } + | ExprDivEq { $$ = $1; } + | ExprModEq { $$ = $1; } + | ExprExpEq { $$ = $1; } + ; + +ExprMath : Expression '+' Expression { $$ = hb_compExprSetOperand( hb_compExprNewPlus( $1 ), $3, HB_MACRO_PARAM ); } + | Expression '-' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMinus( $1 ), $3, HB_MACRO_PARAM ); } + | Expression '*' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMult( $1 ), $3, HB_MACRO_PARAM ); } + | Expression '/' Expression { $$ = hb_compExprSetOperand( hb_compExprNewDiv( $1 ), $3, HB_MACRO_PARAM ); } + | Expression '%' Expression { $$ = hb_compExprSetOperand( hb_compExprNewMod( $1 ), $3, HB_MACRO_PARAM ); } + | Expression POWER Expression { $$ = hb_compExprSetOperand( hb_compExprNewPower( $1 ), $3, HB_MACRO_PARAM ); } + ; + +ExprBool : Expression AND Expression { $$ = hb_compExprSetOperand( hb_compExprNewAnd( $1 ), $3, HB_MACRO_PARAM ); } + | Expression OR Expression { $$ = hb_compExprSetOperand( hb_compExprNewOr( $1 ), $3, HB_MACRO_PARAM ); } + ; + +ExprRelation: Expression EQ Expression { $$ = hb_compExprSetOperand( hb_compExprNewEQ( $1 ), $3, HB_MACRO_PARAM ); } + | Expression '<' Expression { $$ = hb_compExprSetOperand( hb_compExprNewLT( $1 ), $3, HB_MACRO_PARAM ); } + | Expression '>' Expression { $$ = hb_compExprSetOperand( hb_compExprNewGT( $1 ), $3, HB_MACRO_PARAM ); } + | Expression LE Expression { $$ = hb_compExprSetOperand( hb_compExprNewLE( $1 ), $3, HB_MACRO_PARAM ); } + | Expression GE Expression { $$ = hb_compExprSetOperand( hb_compExprNewGE( $1 ), $3, HB_MACRO_PARAM ); } + | Expression NE1 Expression { $$ = hb_compExprSetOperand( hb_compExprNewNE( $1 ), $3, HB_MACRO_PARAM ); } + | Expression NE2 Expression { $$ = hb_compExprSetOperand( hb_compExprNewNE( $1 ), $3, HB_MACRO_PARAM ); } + | Expression '$' Expression { $$ = hb_compExprSetOperand( hb_compExprNewIN( $1 ), $3, HB_MACRO_PARAM ); } + | Expression '=' Expression { $$ = hb_compExprSetOperand( hb_compExprNewEqual( $1 ), $3, HB_MACRO_PARAM ); } + ; + +ArrayIndex : IndexList ']' { $$ = $1; } + ; + +/* 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, HB_MACRO_PARAM ); } + | IndexList ',' Expression { $$ = hb_compExprNewArrayAt( $1, $3, HB_MACRO_PARAM ); } + | IndexList ']' '[' Expression { $$ = hb_compExprNewArrayAt( $1, $4, HB_MACRO_PARAM ); } + ; + +ElemList : EmptyExpression { $$ = hb_compExprNewList( $1 ); } + | ElemList ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } + ; + +CodeBlock : '{' '|' + { $$ = hb_compExprNewCodeBlock(); } BlockNoVar + '|' BlockExpList '}' + { $$ = $3; } + | '{' '|' + { $$ = hb_compExprNewCodeBlock(); } + BlockVarList + '|' BlockExpList '}' + { $$ = $3; } + ; + +/* NOTE: This uses $-2 then don't use BlockExpList in other context + */ +BlockExpList : Expression { $$ = hb_compExprAddListExpr( $-2, $1 ); } + | BlockExpList ',' Expression { $$ = hb_compExprAddListExpr( $-2, $3 ); } + ; + +/* 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; } +; + +BlockVarList : IDENTIFIER { $$ = hb_compExprCBVarAdd( $0, $1, HB_MACRO_PARAM ); } + | BlockVarList ',' IDENTIFIER { $$ = hb_compExprCBVarAdd( $0, $3, HB_MACRO_PARAM ); HB_MACRO_CHECK( $$ ); } + ; + +ExpList : '(' EmptyExpression { $$ = hb_compExprNewList( $2 ); } + | ExpList ',' EmptyExpression { $$ = hb_compExprAddListExpr( $1, $3 ); } +; + +PareExpList : ExpList ')' { $$ = $1; } +; + +PareExpListAlias : PareExpList ALIASOP { $$ = $1; } +; + +IfInline : IIF '(' Expression ',' EmptyExpression ',' + { $$ = hb_compExprAddListExpr( $3, $5 ); } + EmptyExpression ')' + { $$ = hb_compExprNewIIF( hb_compExprAddListExpr( $7, $8 ) ); } + + | IF '(' Expression ',' EmptyExpression ',' + { $$ = hb_compExprAddListExpr( $3, $5 ); } + EmptyExpression ')' + { $$ = hb_compExprNewIIF( hb_compExprAddListExpr( $7, $8 ) ); } + ; + +%% + +/* + ** ------------------------------------------------------------------------ ** + */ + +int hb_compParse( HB_MACRO_PTR pMacro ) +{ + int iResult; + void * lexBuffer; + + lexBuffer = hb_compFlexNew( pMacro ); + + pMacro->status = HB_MACRO_OK; + /* NOTE: bison requires (void *) pointer + */ + iResult = yyparse( ( void * ) pMacro ); + + hb_compFlexDelete( lexBuffer ); + + return iResult; +} + +/* ************************************************************************* */ + +void yyerror( char * s ) +{ + HB_SYMBOL_UNUSED( s ); +} + diff --git a/harbour/source/runner/stdalone/Makefile b/harbour/source/runner/stdalone/Makefile index 414ec8186f..32be1f6431 100644 --- a/harbour/source/runner/stdalone/Makefile +++ b/harbour/source/runner/stdalone/Makefile @@ -24,5 +24,6 @@ LIBS=\ rtl \ pp \ common \ + macro \ include $(TOP)$(ROOT)config/bin.cf diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 4f9cba8647..f2af5fcfbc 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -135,6 +135,7 @@ static void hb_vmPushLocal( SHORT iLocal ); /* pushes the containts of a l static void hb_vmPushLocalByRef( SHORT iLocal ); /* pushes a local by refrence onto the stack */ static void hb_vmPushStatic( USHORT uiStatic ); /* pushes the containts of a static onto the stack */ static void hb_vmPushStaticByRef( USHORT uiStatic ); /* pushes a static by refrence onto the stack */ +static void hb_vmPushVariable( PHB_SYMB pVarSymb ); /* pushes undeclared variable */ static void hb_vmDuplicate( void ); /* duplicates the latest value on the stack */ static void hb_vmDuplTwo( void ); /* duplicates the latest two value on the stack */ @@ -149,8 +150,8 @@ static void hb_vmPopLocal( SHORT iLocal ); /* pops the stack latest value static void hb_vmPopStatic( USHORT uiStatic ); /* pops the stack latest value onto a static */ /* stack management functions */ + void hb_stackPop( void ); /* pops an item from the stack */ static void hb_stackDec( void ); /* pops an item from the stack without clearing it's contents */ -static void hb_stackPop( void ); /* pops an item from the stack */ static void hb_stackFree( void ); /* releases all memory used by the stack */ static void hb_stackPush( void ); /* pushes an item on to the stack */ static void hb_stackInit( void ); /* initializes the stack */ @@ -838,39 +839,8 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) case HB_P_PUSHVARIABLE: /* Push a value of variable of unknown type onto the eval stack */ - { - USHORT uiAction = E_DEFAULT; - PHB_SYMB pVarSymb = pSymbols + pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ); - - do - { - /* First try if passed symbol is a name of field - * in a current workarea - if it is not a field (FAILURE) - * then try the memvar variable - */ - if( hb_rddFieldGet( hb_stack.pPos, pVarSymb ) == SUCCESS ) - hb_stackPush(); - else - { - if( hb_memvarGet( hb_stack.pPos, pVarSymb ) == SUCCESS ) - hb_stackPush(); - else - { - HB_ITEM_PTR pError; - - pError = hb_errRT_New( ES_ERROR, NULL, EG_NOVAR, 1003, - NULL, pVarSymb->szName, - 0, EF_CANRETRY ); - - uiAction = hb_errLaunch( pError ); - hb_errRelease( pError ); - } - } - } - while( uiAction == E_RETRY ); - HB_TRACE(HB_TR_INFO, ("(hb_vmPushVariable)")); - w += 3; - } + hb_vmPushVariable( pSymbols + pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) ); + w += 3; break; case HB_P_DUPLICATE: @@ -950,6 +920,151 @@ void hb_vmExecute( BYTE * pCode, PHB_SYMB pSymbols ) w += 3; break; + /* macro creation */ + + case HB_P_MACROPOP: + /* compile and run - pop a value from the stack */ + hb_macroSetValue( hb_stack.pPos - 1, pSymbols ); + w++; + break; + + case HB_P_MACROPOPALIASED: + /* compile and run - pop a field value from the stack */ + w++; + break; + case HB_P_MACROPUSH: + /* compile and run - leave the result on the stack */ + /* the topmost element on the stack contains a macro + * string for compilation + */ + hb_macroGetValue( hb_stack.pPos - 1, pSymbols ); + w++; + break; + + case HB_P_MACROPUSHALIASED: + /* compile and run - leave the field value on the stack */ + w++; + break; + + case HB_P_MACROSYMBOL: + /* compile into a symbol name (used in function calls) */ + w++; + break; + + case HB_P_MACROTEXT: + /* macro text substitution */ + w++; + break; + + /* macro compiled opcodes - we are using symbol address here */ + + case HB_P_MMESSAGE: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_vmMessage( ( *pDynSym )->pSymbol ); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + + case HB_P_MPOPALIASEDFIELD: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_vmPopAliasedField( ( *pDynSym )->pSymbol ); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + + case HB_P_MPOPFIELD: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + /* Pops a value from the eval stack and uses it to set + * a new value of the given field + */ + hb_stackDec(); + hb_rddPutFieldValue( hb_stack.pPos, ( *pDynSym )->pSymbol ); + hb_itemClear( hb_stack.pPos ); + HB_TRACE(HB_TR_INFO, ("(hb_vmMPopField)")); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + + case HB_P_MPOPMEMVAR: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_stackDec(); + hb_memvarSetValue( ( *pDynSym )->pSymbol, hb_stack.pPos ); + hb_itemClear( hb_stack.pPos ); + HB_TRACE(HB_TR_INFO, ("(hb_vmMPopMemvar)")); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + + case HB_P_MPUSHALIASEDFIELD: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_vmPushAliasedField( ( *pDynSym )->pSymbol ); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + + case HB_P_MPUSHBLOCK: + { + /*NOTE: the pcode is stored in damically allocated memory + * We need to handle it with more care than compile-time + * codeblocks + */ + w += ( pCode[ w + 1 ] + ( pCode[ w + 2 ] * 256 ) ); + } + break; + + case HB_P_MPUSHFIELD: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + /* It pushes the current value of the given field onto the eval stack + */ + hb_rddGetFieldValue( hb_stack.pPos, ( *pDynSym )->pSymbol ); + hb_stackPush(); + HB_TRACE(HB_TR_INFO, ("(hb_vmMPushField)")); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + + case HB_P_MPUSHMEMVAR: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_memvarGetValue( hb_stack.pPos, ( *pDynSym )->pSymbol ); + hb_stackPush(); + HB_TRACE(HB_TR_INFO, ("(hb_vmMPushMemvar)")); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + + case HB_P_MPUSHMEMVARREF: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_memvarGetRefer( hb_stack.pPos, ( *pDynSym )->pSymbol ); + hb_stackPush(); + HB_TRACE(HB_TR_INFO, ("(hb_vmMPushMemvarRef)")); + w += sizeof( HB_DYNS_PTR ) + 1; + } + break; + + case HB_P_MPUSHSYM: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_vmPushSymbol( ( *pDynSym )->pSymbol ); + } + w += sizeof( HB_DYNS_PTR ) + 1; + break; + + case HB_P_MPUSHVARIABLE: + { + HB_DYNS_PTR *pDynSym = ( HB_DYNS_PTR *) ( pCode + w + 1 ); + hb_vmPushVariable( ( *pDynSym )->pSymbol ); + } + w += sizeof( HB_DYNS_PTR ) + 1; + break; + /* misc */ case HB_P_NOOP: @@ -2817,6 +2932,40 @@ static void hb_vmPushStaticByRef( USHORT uiStatic ) hb_stackPush(); } +static void hb_vmPushVariable( PHB_SYMB pVarSymb ) +{ + USHORT uiAction = E_DEFAULT; + + do + { + /* First try if passed symbol is a name of field + * in a current workarea - if it is not a field (FAILURE) + * then try the memvar variable + */ + if( hb_rddFieldGet( hb_stack.pPos, pVarSymb ) == SUCCESS ) + hb_stackPush(); + else + { + if( hb_memvarGet( hb_stack.pPos, pVarSymb ) == SUCCESS ) + hb_stackPush(); + else + { + HB_ITEM_PTR pError; + + pError = hb_errRT_New( ES_ERROR, NULL, EG_NOVAR, 1003, + NULL, pVarSymb->szName, + 0, EF_CANRETRY ); + + uiAction = hb_errLaunch( pError ); + hb_errRelease( pError ); + } + } + } + while( uiAction == E_RETRY ); + HB_TRACE(HB_TR_INFO, ("(hb_vmPushVariable)")); +} + + static void hb_vmDuplicate( void ) { HB_TRACE(HB_TR_DEBUG, ("hb_vmDuplicate()")); @@ -3017,7 +3166,7 @@ static void hb_vmPopStatic( USHORT uiStatic ) /* stack management functions */ /* ------------------------------- */ -static void hb_stackPop( void ) +void hb_stackPop( void ) { HB_TRACE(HB_TR_DEBUG, ("hb_stackPop()")); diff --git a/harbour/tests/Makefile b/harbour/tests/Makefile index 7f1066b7b9..beeecce836 100644 --- a/harbour/tests/Makefile +++ b/harbour/tests/Makefile @@ -16,6 +16,7 @@ LIBS=\ vm \ rdd \ rtl \ + macro \ pp \ runner \ common \ @@ -180,6 +181,11 @@ BAD_C_SOURCES=\ include $(TOP)$(ROOT)config/test.cf +DIRS=\ + regress \ + +include $(TOP)$(ROOT)config/dir.cf + else #PM defined = build specified file ifneq ($(findstring .prg,$(PM)),) @@ -195,8 +201,3 @@ include $(TOP)$(ROOT)config/bin.cf endif - -DIRS=\ - regress \ - -include $(TOP)$(ROOT)config/dir.cf diff --git a/harbour/tests/regress/Makefile b/harbour/tests/regress/Makefile index 710cad26ec..27393700e1 100644 --- a/harbour/tests/regress/Makefile +++ b/harbour/tests/regress/Makefile @@ -25,6 +25,7 @@ LIBS=\ vm \ rdd \ rtl \ + macro \ pp \ runner \ common \ diff --git a/harbour/tests/tstmacro.prg b/harbour/tests/tstmacro.prg index bf183d350e..6cb6608671 100644 --- a/harbour/tests/tstmacro.prg +++ b/harbour/tests/tstmacro.prg @@ -1,4 +1,4 @@ -#INCLUDE "HBCLASS.CH" +#include "hbclass.ch" Function Main( )