2012-09-19 04:06 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* harbour/include/hbexprb.c
* harbour/include/hbcomp.h
* harbour/include/hbcompdf.h
* harbour/src/compiler/hbusage.c
* harbour/src/compiler/harbour.yyc
* harbour/src/compiler/harbour.y
* harbour/src/compiler/ppcomp.c
* harbour/src/compiler/hbmain.c
* harbour/src/compiler/cmdcheck.c
* harbour/doc/cmpopt.txt
* harbour/doc/xhb-diff.txt
+ added new harbour compiler switch:
-kd => accept macros with declared symbols
This switch allows to use declared symbols like LOCALs, STATICs
and FIELDs in macros and macrocodeblocks (every evaluated).
; Please do not confuse different things. Above modification
does not mean to that such variables are visible for macro
compiler. It only allows to write code like:
cbVar := {|| &cLocal + cPrivate }
or:
cbVar := {|| &cLocalPref.func&cPriv1( cPriv2 ) }
or:
? &cLocalPref.func&cPriv1( cPriv2 )
etc.
If possible then for macrocodeblocks Harbour compiler tries to
generate early eval code in which macros are expanded when codeblock
is created. Otherwise macros are expanded each time codeblocks are
evaluated.
For more information look at harbour/doc/xhb-diff.txt section:
MACROS WITH DECLARED SYMBOLS
This commit is contained in:
@@ -16,6 +16,38 @@
|
||||
The license applies to all entries newer than 2009-04-28.
|
||||
*/
|
||||
|
||||
2012-09-19 04:06 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
|
||||
* harbour/include/hbexprb.c
|
||||
* harbour/include/hbcomp.h
|
||||
* harbour/include/hbcompdf.h
|
||||
* harbour/src/compiler/hbusage.c
|
||||
* harbour/src/compiler/harbour.yyc
|
||||
* harbour/src/compiler/harbour.y
|
||||
* harbour/src/compiler/ppcomp.c
|
||||
* harbour/src/compiler/hbmain.c
|
||||
* harbour/src/compiler/cmdcheck.c
|
||||
* harbour/doc/cmpopt.txt
|
||||
* harbour/doc/xhb-diff.txt
|
||||
+ added new harbour compiler switch:
|
||||
-kd => accept macros with declared symbols
|
||||
This switch allows to use declared symbols like LOCALs, STATICs
|
||||
and FIELDs in macros and macrocodeblocks (every evaluated).
|
||||
; Please do not confuse different things. Above modification
|
||||
does not mean to that such variables are visible for macro
|
||||
compiler. It only allows to write code like:
|
||||
cbVar := {|| &cLocal + cPrivate }
|
||||
or:
|
||||
cbVar := {|| &cLocalPref.func&cPriv1( cPriv2 ) }
|
||||
or:
|
||||
? &cLocalPref.func&cPriv1( cPriv2 )
|
||||
etc.
|
||||
If possible then for macrocodeblocks Harbour compiler tries to
|
||||
generate early eval code in which macros are expanded when codeblock
|
||||
is created. Otherwise macros are expanded each time codeblocks are
|
||||
evaluated.
|
||||
For more information look at harbour/doc/xhb-diff.txt section:
|
||||
MACROS WITH DECLARED SYMBOLS
|
||||
|
||||
2012-09-18 18:26 UTC+0200 Viktor Szakats (harbour syenar.net)
|
||||
* contrib/hbide/main.prg
|
||||
! include rddads.hbx on win/linux platforms only
|
||||
|
||||
@@ -199,6 +199,25 @@ declarations. This code illustrates it:
|
||||
This behavior is not replicated in Harbour even if -kc switch is used
|
||||
and Harbour optimize expressions in all declarations.
|
||||
|
||||
Harbour supports macro expansion for expressions with declared symbols.
|
||||
This functionality can be enabled by -kd compiler switch:
|
||||
-kd => accept macros with declared symbols
|
||||
It only allows to write code like:
|
||||
cbVar := {|| &cLocal + cPrivate }
|
||||
or:
|
||||
cbVar := {|| &cLocalPref.func&cPriv1( cPriv2 ) }
|
||||
or:
|
||||
? &cLocalPref.func&cPriv1( cPriv2, &cStatic )
|
||||
etc.
|
||||
If possible then for macrocodeblocks Harbour compiler tries to
|
||||
generate early eval code in which macros are expanded when codeblock
|
||||
is created. Otherwise macros are expanded each time codeblock is
|
||||
evaluated.
|
||||
This feature can be useful also in porting some other xbase compatible
|
||||
code to Harbour because some compilers just like xHarbour accepted
|
||||
in some limited way officially unsupported syntax with macros using
|
||||
declared symbols.
|
||||
|
||||
Harbour has additional optimization phase which operates on generated PCODE.
|
||||
It can also reduce expressions, joins jumps, removes death or meaningless
|
||||
code which can appear after all other optimizations and were not optimized
|
||||
|
||||
@@ -627,6 +627,69 @@ hb_arrayToParams() or similar function.
|
||||
|
||||
|
||||
|
||||
### MACROS WITH DECLARED SYMBOLS ###
|
||||
==========================================
|
||||
Harbour supports macro expansion for expressions with declared symbols.
|
||||
This functionality can be enabled by -kd compiler switch:
|
||||
-kd => accept macros with declared symbols
|
||||
It allows to write code like:
|
||||
cbVar := {|| &cLocal + cPrivate }
|
||||
or:
|
||||
cbVar := {|| &cLocalPref.func&cPriv1( cPriv2 ) }
|
||||
or:
|
||||
? &cLocalPref.func&cPriv1( cPriv2, &cStatic )
|
||||
etc.
|
||||
If it's possible then for macrocodeblocks Harbour compiler tries to
|
||||
generate early eval code in which macros are expanded when codeblock
|
||||
is created. Otherwise macros are expanded each time codeblock is
|
||||
evaluated.
|
||||
xHarbour has also similar extension but limited to only to macro
|
||||
variables and it works only if other macros are not used in the
|
||||
same expression. When more complicated examples are create xHarbour
|
||||
compiler generates broken code which generate RTE or GPF during
|
||||
execution. It also does not support codeblocks which contain mixed
|
||||
macros and refuse to compile such code.
|
||||
|
||||
This example illustrates macros with declared symbols.
|
||||
|
||||
#ifndef __XHARBOUR__
|
||||
#pragma -kd+
|
||||
#endif
|
||||
proc main()
|
||||
memvar nPrivate
|
||||
memvar cPriv1, cPriv2
|
||||
local cbVar1, cbVar2
|
||||
local cLocal := "10", cLocalPref := "hb_"
|
||||
static cStatic := "'123xyz'"
|
||||
private nPrivate := 10000
|
||||
private cPriv1 := "test1", cPriv2 := "abc"
|
||||
#ifndef __XHARBOUR__
|
||||
cbVar1 := {|| &cLocal + nPrivate + val( &cStatic ) }
|
||||
cbVar2 := {|| &cLocalPref.func&cPriv1( cPriv2, &cStatic ) }
|
||||
? eval( cbVar1 )
|
||||
? eval( cbVar2 )
|
||||
#endif
|
||||
? &cLocal + nPrivate + val( &cStatic )
|
||||
cLocal := "upp"
|
||||
? &cLocal.er( &cStatic )
|
||||
? hb_funcTest1( cPriv2, &cStatic )
|
||||
? &cLocalPref.func&cPriv1( cPriv2, &cStatic )
|
||||
? &cLocalPref.func&cPriv1( cPriv2, &cStatic )
|
||||
return
|
||||
|
||||
func hb_funcTest1( s1, s2 )
|
||||
return s1 + ":" + s2
|
||||
|
||||
Above code can be compiled by xHarbour but it will not work exploiting
|
||||
some problems in this compiler and generated code.
|
||||
|
||||
This feature can be useful also in porting some other xbase compatible
|
||||
code to Harbour because some compilers just like xHarbour accepted
|
||||
in some limited way officially unsupported syntax with macros using
|
||||
declared symbols.
|
||||
|
||||
|
||||
|
||||
### MACRO MESSAGES ###
|
||||
============================
|
||||
Both compilers Harbour and xHarbour supports macros as messages.
|
||||
|
||||
@@ -289,13 +289,13 @@ extern void hb_compErrorVParams( HB_COMP_DECL, const char * szFuncOrBlock
|
||||
extern HB_EXPR_PTR hb_compErrorStatic( HB_COMP_DECL, const char *, HB_EXPR_PTR );
|
||||
extern void hb_compErrorCodeblock( HB_COMP_DECL, const char * szBlock );
|
||||
|
||||
extern HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen );
|
||||
extern void hb_compPushMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen, HB_BOOL fMacro );
|
||||
|
||||
/* Codeblocks */
|
||||
extern void hb_compCodeBlockStart( HB_COMP_DECL, HB_BOOL bLateEval ); /* starts a codeblock creation */
|
||||
extern void hb_compCodeBlockEnd( HB_COMP_DECL ); /* end of codeblock creation */
|
||||
extern void hb_compCodeBlockStop( HB_COMP_DECL ); /* end of fake codeblock */
|
||||
extern void hb_compCodeBlockRewind( HB_COMP_DECL ); /* restart of fake codeblock */
|
||||
extern void hb_compCodeBlockStart( HB_COMP_DECL, int iEarlyEvalPass ); /* starts a codeblock creation */
|
||||
extern void hb_compCodeBlockEnd( HB_COMP_DECL ); /* end of codeblock creation */
|
||||
extern void hb_compCodeBlockStop( HB_COMP_DECL ); /* end of fake codeblock */
|
||||
extern void hb_compCodeBlockRewind( HB_COMP_DECL ); /* restart of fake codeblock */
|
||||
|
||||
#endif /* HB_MACRO_SUPPORT */
|
||||
|
||||
@@ -383,7 +383,8 @@ extern const HB_BYTE hb_comp_pcode_len[];
|
||||
#define HB_COMPFLAG_OPTJUMP 0x0100 /* -kj turn off jump optimalization */
|
||||
#define HB_COMPFLAG_HB_INLINE 0x0200 /* -ki hb_inLine(...) { ... } support */
|
||||
#define HB_COMPFLAG_MACROTEXT 0x0400 /* -kM turn off macrotext substitution */
|
||||
#define HB_COMPFLAG_USERCP 0x0800 /* -kU strings in user encoding */
|
||||
#define HB_COMPFLAG_USERCP 0x0800 /* -ku strings in user encoding */
|
||||
#define HB_COMPFLAG_MACRODECL 0x1000 /* -kd accept macros with declared symbols */
|
||||
|
||||
#define HB_COMP_ISSUPPORTED(flag) ( HB_COMP_PARAM->supported & (flag) )
|
||||
|
||||
@@ -393,6 +394,7 @@ extern const HB_BYTE hb_comp_pcode_len[];
|
||||
#define HB_SUPPORT_EXTOPT ( HB_COMP_ISSUPPORTED(HB_COMPFLAG_EXTOPT) )
|
||||
#define HB_SUPPORT_MACROTEXT ( HB_COMP_ISSUPPORTED(HB_COMPFLAG_MACROTEXT) )
|
||||
#define HB_SUPPORT_USERCP ( HB_COMP_ISSUPPORTED(HB_COMPFLAG_USERCP) )
|
||||
#define HB_SUPPORT_MACRODECL ( HB_COMP_ISSUPPORTED(HB_COMPFLAG_MACRODECL) )
|
||||
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
# define HB_MACRO_GENFLAGS HB_COMPFLAG_RT_MACRO
|
||||
|
||||
@@ -511,13 +511,13 @@ typedef struct __FUNC
|
||||
HB_BYTE * pCode; /* pointer to a memory block where pcode is stored */
|
||||
HB_SIZE nPCodeSize; /* total memory size for pcode */
|
||||
HB_SIZE nPCodePos; /* actual pcode offset */
|
||||
int iStaticsBase; /* base for this function statics */
|
||||
int iFuncSuffix; /* function suffix for multiple static functions with the same name */
|
||||
HB_SIZE * pNOOPs; /* pointer to the NOOP array */
|
||||
HB_SIZE * pJumps; /* pointer to the Jumps array */
|
||||
HB_SIZE nNOOPs; /* NOOPs Counter */
|
||||
HB_SIZE nJumps; /* Jumps Counter */
|
||||
HB_BOOL bLateEval; /* HB_TRUE if accessing of declared (compile time) variables is allowed */
|
||||
int iStaticsBase; /* base for this function statics */
|
||||
int iFuncSuffix; /* function suffix for multiple static functions with the same name */
|
||||
int iEarlyEvalPass; /* !=0 if early evaluaded block is compiled - accessing of declared (compile time) variables is limited */
|
||||
HB_BOOL fVParams; /* HB_TRUE if variable number of parameters is used */
|
||||
HB_BOOL bError; /* error during function compilation */
|
||||
HB_BOOL bBlock; /* HB_TRUE if simple codeblock body is compiled */
|
||||
|
||||
@@ -130,7 +130,7 @@ static HB_EXPR_FUNC( hb_compExprUseNegate );
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
static void hb_compExprCodeblockPush( HB_EXPR_PTR, HB_COMP_DECL );
|
||||
#else
|
||||
static void hb_compExprCodeblockPush( HB_EXPR_PTR, HB_BOOL, HB_COMP_DECL );
|
||||
static HB_BOOL hb_compExprCodeblockPush( HB_EXPR_PTR, int, HB_COMP_DECL );
|
||||
static void hb_compExprCodeblockEarly( HB_EXPR_PTR, HB_COMP_DECL );
|
||||
static void hb_compExprCodeblockExtPush( HB_EXPR_PTR pSelf, HB_COMP_DECL );
|
||||
#endif
|
||||
@@ -394,20 +394,23 @@ static HB_EXPR_FUNC( hb_compExprUseString )
|
||||
break;
|
||||
case HB_EA_PUSH_PCODE:
|
||||
{
|
||||
#if ! defined( HB_MACRO_SUPPORT )
|
||||
if( !HB_SUPPORT_MACROTEXT )
|
||||
HB_GEN_FUNC2( PushString, pSelf->value.asString.string,
|
||||
pSelf->nLength + 1 );
|
||||
else
|
||||
hb_compPushMacroText( HB_COMP_PARAM,
|
||||
pSelf->value.asString.string,
|
||||
pSelf->nLength, HB_FALSE );
|
||||
#else
|
||||
HB_GEN_FUNC2( PushString, pSelf->value.asString.string,
|
||||
pSelf->nLength + 1 );
|
||||
#if ! defined( HB_MACRO_SUPPORT )
|
||||
if( HB_SUPPORT_MACROTEXT &&
|
||||
hb_compIsValidMacroText( HB_COMP_PARAM,
|
||||
pSelf->value.asString.string,
|
||||
pSelf->nLength ) )
|
||||
#else
|
||||
if( hb_macroIsValidMacroText( pSelf->value.asString.string,
|
||||
pSelf->nLength ) )
|
||||
#endif
|
||||
{
|
||||
HB_GEN_FUNC1( PCode1, HB_P_MACROTEXT );
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case HB_EA_POP_PCODE:
|
||||
@@ -456,7 +459,7 @@ static HB_EXPR_FUNC( hb_compExprUseCodeblock )
|
||||
/* early evaluation of a macro */
|
||||
hb_compExprCodeblockEarly( pSelf, HB_COMP_PARAM );
|
||||
else
|
||||
hb_compExprCodeblockPush( pSelf, HB_TRUE, HB_COMP_PARAM );
|
||||
hb_compExprCodeblockPush( pSelf, 0, HB_COMP_PARAM );
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@@ -1591,7 +1594,13 @@ static HB_EXPR_FUNC( hb_compExprUseMacro )
|
||||
/* simple macro variable expansion: &variable
|
||||
* 'szMacro' is a variable name
|
||||
*/
|
||||
#if ! defined( HB_MACRO_SUPPORT )
|
||||
int iEarlyEvalPass = HB_COMP_PARAM->functions.pLast->iEarlyEvalPass;
|
||||
HB_GEN_FUNC1( PushVar, pSelf->value.asMacro.szMacro );
|
||||
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = iEarlyEvalPass;
|
||||
#else
|
||||
HB_GEN_FUNC1( PushVar, pSelf->value.asMacro.szMacro );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1604,11 +1613,12 @@ static HB_EXPR_FUNC( hb_compExprUseMacro )
|
||||
* local, static or field.
|
||||
*/
|
||||
#if ! defined( HB_MACRO_SUPPORT )
|
||||
hb_compIsValidMacroText( HB_COMP_PARAM,
|
||||
pSelf->value.asMacro.szMacro,
|
||||
strlen( pSelf->value.asMacro.szMacro ) );
|
||||
#endif
|
||||
hb_compPushMacroText( HB_COMP_PARAM,
|
||||
pSelf->value.asMacro.szMacro,
|
||||
strlen( pSelf->value.asMacro.szMacro ), HB_TRUE );
|
||||
#else
|
||||
HB_GEN_FUNC2( PushString, pSelf->value.asMacro.szMacro, strlen( pSelf->value.asMacro.szMacro ) + 1 );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1676,7 +1686,13 @@ static HB_EXPR_FUNC( hb_compExprUseMacro )
|
||||
/* simple macro variable expansion: &variable
|
||||
* 'szMacro' is a variable name
|
||||
*/
|
||||
#if ! defined( HB_MACRO_SUPPORT )
|
||||
int iEarlyEvalPass = HB_COMP_PARAM->functions.pLast->iEarlyEvalPass;
|
||||
HB_GEN_FUNC1( PushVar, pSelf->value.asMacro.szMacro );
|
||||
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = iEarlyEvalPass;
|
||||
#else
|
||||
HB_GEN_FUNC1( PushVar, pSelf->value.asMacro.szMacro );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1689,11 +1705,12 @@ static HB_EXPR_FUNC( hb_compExprUseMacro )
|
||||
* local, static or field.
|
||||
*/
|
||||
#if ! defined( HB_MACRO_SUPPORT )
|
||||
hb_compIsValidMacroText( HB_COMP_PARAM,
|
||||
pSelf->value.asMacro.szMacro,
|
||||
strlen( pSelf->value.asMacro.szMacro ) );
|
||||
#endif
|
||||
hb_compPushMacroText( HB_COMP_PARAM,
|
||||
pSelf->value.asMacro.szMacro,
|
||||
strlen( pSelf->value.asMacro.szMacro ), HB_TRUE );
|
||||
#else
|
||||
HB_GEN_FUNC2( PushString, pSelf->value.asMacro.szMacro, strlen( pSelf->value.asMacro.szMacro ) + 1 );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* compile & run - macro compiler will generate pcode to pop a value
|
||||
@@ -4472,7 +4489,7 @@ static HB_EXPR_FUNC( hb_compExprUsePreDec )
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_COMP_DECL )
|
||||
#else
|
||||
static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_BOOL bLateEval, HB_COMP_DECL )
|
||||
static HB_BOOL hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, int iEarlyEvalPass, HB_COMP_DECL )
|
||||
#endif
|
||||
{
|
||||
HB_EXPR_PTR pExpr, pNext;
|
||||
@@ -4486,7 +4503,7 @@ static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_BOOL bLateEval, HB_C
|
||||
HB_PCODE_DATA->fVParams =
|
||||
( pSelf->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;
|
||||
#else
|
||||
hb_compCodeBlockStart( HB_COMP_PARAM, bLateEval );
|
||||
hb_compCodeBlockStart( HB_COMP_PARAM, iEarlyEvalPass );
|
||||
HB_COMP_PARAM->functions.pLast->fVParams =
|
||||
( pSelf->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;
|
||||
|
||||
@@ -4548,7 +4565,7 @@ static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_BOOL bLateEval, HB_C
|
||||
else
|
||||
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
|
||||
#else
|
||||
if( pNext && bLateEval )
|
||||
if( pNext && ( iEarlyEvalPass == 0 || HB_SUPPORT_MACRODECL ) )
|
||||
HB_EXPR_USE( pExpr, HB_EA_PUSH_POP );
|
||||
else
|
||||
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
|
||||
@@ -4559,10 +4576,16 @@ static void hb_compExprCodeblockPush( HB_EXPR_PTR pSelf, HB_BOOL bLateEval, HB_C
|
||||
#if defined( HB_MACRO_SUPPORT )
|
||||
hb_macroCodeBlockEnd( HB_COMP_PARAM );
|
||||
#else
|
||||
if( bLateEval )
|
||||
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 0 )
|
||||
{
|
||||
hb_compCodeBlockEnd( HB_COMP_PARAM );
|
||||
return HB_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_compCodeBlockRewind( HB_COMP_PARAM );
|
||||
return HB_FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4603,11 +4626,18 @@ static void hb_compExprCodeblockEarly( HB_EXPR_PTR pSelf, HB_COMP_DECL )
|
||||
/* everything else is macro compiled at runtime
|
||||
* {|| &variable+1} => &( '{|| &variable+1}' )
|
||||
*/
|
||||
hb_compExprCodeblockPush( pSelf, HB_FALSE, HB_COMP_PARAM );
|
||||
pExpr = hb_compExprNewMacro( hb_compExprNewString( pSelf->value.asCodeblock.string, pSelf->nLength, HB_FALSE, HB_COMP_PARAM ), 0, NULL, HB_COMP_PARAM );
|
||||
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
|
||||
HB_COMP_EXPR_FREE( pExpr );
|
||||
hb_compCodeBlockStop( HB_COMP_PARAM );
|
||||
if( !hb_compExprCodeblockPush( pSelf, 1, HB_COMP_PARAM ) )
|
||||
{
|
||||
HB_BOOL fMacroText = ( HB_COMP_PARAM->supported & HB_COMPFLAG_MACROTEXT ) != 0;
|
||||
HB_COMP_PARAM->supported |= HB_COMPFLAG_MACROTEXT;
|
||||
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = 2;
|
||||
pExpr = hb_compExprNewMacro( hb_compExprNewString( pSelf->value.asCodeblock.string, pSelf->nLength, HB_FALSE, HB_COMP_PARAM ), 0, NULL, HB_COMP_PARAM );
|
||||
HB_EXPR_USE( pExpr, HB_EA_PUSH_PCODE );
|
||||
HB_COMP_EXPR_FREE( pExpr );
|
||||
hb_compCodeBlockStop( HB_COMP_PARAM );
|
||||
if( !fMacroText )
|
||||
HB_COMP_PARAM->supported &= ~HB_COMPFLAG_MACROTEXT;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /*HB_MACRO_SUPPORT*/
|
||||
|
||||
@@ -411,6 +411,17 @@ static void hb_compChkEnvironVar( HB_COMP_DECL, const char *szSwitch )
|
||||
HB_COMP_PARAM->supported &= ~HB_COMPFLAG_MACROTEXT;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'D':
|
||||
if( s[i] == '-' )
|
||||
{
|
||||
i++;
|
||||
HB_COMP_PARAM->supported &= ~HB_COMPFLAG_MACRODECL;
|
||||
}
|
||||
else
|
||||
HB_COMP_PARAM->supported |= HB_COMPFLAG_MACRODECL;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
case 'R':
|
||||
if( s[i] == '-' )
|
||||
|
||||
@@ -1038,7 +1038,7 @@ CodeBlock : BlockHead
|
||||
HB_CBVAR_PTR pVar;
|
||||
$<sNumber>$ = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
||||
$<sNumber>2 = HB_COMP_PARAM->lastLine;
|
||||
hb_compCodeBlockStart( HB_COMP_PARAM, HB_TRUE );
|
||||
hb_compCodeBlockStart( HB_COMP_PARAM, 0 );
|
||||
HB_COMP_PARAM->functions.pLast->funFlags |= FUN_EXTBLOCK;
|
||||
HB_COMP_PARAM->functions.pLast->fVParams =
|
||||
( $1->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;
|
||||
|
||||
@@ -6110,7 +6110,7 @@ yyreduce:
|
||||
HB_CBVAR_PTR pVar;
|
||||
(yyval.sNumber) = HB_COMP_PARAM->functions.pLast->nPCodePos;
|
||||
(yyvsp[(2) - (2)].sNumber) = HB_COMP_PARAM->lastLine;
|
||||
hb_compCodeBlockStart( HB_COMP_PARAM, HB_TRUE );
|
||||
hb_compCodeBlockStart( HB_COMP_PARAM, 0 );
|
||||
HB_COMP_PARAM->functions.pLast->funFlags |= FUN_EXTBLOCK;
|
||||
HB_COMP_PARAM->functions.pLast->fVParams =
|
||||
( (yyvsp[(1) - (2)].asExpr)->value.asCodeblock.flags & HB_BLOCK_VPARAMS ) != 0;
|
||||
|
||||
@@ -733,7 +733,7 @@ PVAR hb_compVariableFind( HB_COMP_DECL, const char * szVarName, int * piPos, int
|
||||
*/
|
||||
hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_ILLEGAL_INIT, "(b)", szVarName );
|
||||
}
|
||||
else if( fBlock )
|
||||
else if( fBlock && HB_COMP_PARAM->functions.pLast->iEarlyEvalPass < 2 )
|
||||
{
|
||||
/* We want to access a local variable defined in a function
|
||||
* that owns this codeblock. We cannot access this variable in
|
||||
@@ -892,10 +892,12 @@ int hb_compVariableScope( HB_COMP_DECL, const char * szVarName )
|
||||
return iScope;
|
||||
}
|
||||
|
||||
HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen )
|
||||
void hb_compPushMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen, HB_BOOL fMacro )
|
||||
{
|
||||
int iEarlyEvalPass = HB_COMP_PARAM->functions.pLast->iEarlyEvalPass;
|
||||
HB_BOOL fFound = HB_FALSE;
|
||||
HB_SIZE n = 0;
|
||||
int iParts = 0;
|
||||
|
||||
while( n < nLen )
|
||||
{
|
||||
@@ -919,7 +921,7 @@ HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen
|
||||
if( ch >= 'a' && ch <= 'z' )
|
||||
szSymName[ iSize++ ] = ch - ( 'a' - 'A' );
|
||||
else if( ch == '_' || ( ch >= 'A' && ch <= 'Z' ) ||
|
||||
( ch >= '0' && ch <= '9' ) )
|
||||
( iSize > 0 && ch >= '0' && ch <= '9' ) )
|
||||
szSymName[ iSize++ ] = ch;
|
||||
else
|
||||
break;
|
||||
@@ -928,7 +930,10 @@ HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen
|
||||
|
||||
if( iSize )
|
||||
{
|
||||
const char * pszVarName;
|
||||
|
||||
szSymName[ iSize ] = '\0';
|
||||
pszVarName = hb_compIdentifierNew( HB_COMP_PARAM, szSymName, HB_IDENT_COPY );
|
||||
|
||||
/* NOTE: All variables are assumed memvars in macro compiler -
|
||||
* there is no need to check for a valid name but to be Clipper
|
||||
@@ -937,20 +942,59 @@ HB_BOOL hb_compIsValidMacroText( HB_COMP_DECL, const char * szText, HB_SIZE nLen
|
||||
* Only MEMVAR or undeclared (memvar will be assumed)
|
||||
* variables can be used in macro text.
|
||||
*/
|
||||
fFound = HB_TRUE;
|
||||
iScope = hb_compVariableScope( HB_COMP_PARAM, szSymName );
|
||||
if( iScope != HB_VS_UNDECLARED && !( iScope & HB_VS_LOCAL_MEMVAR ) )
|
||||
iScope = hb_compVariableScope( HB_COMP_PARAM, pszVarName );
|
||||
if( iScope == HB_VS_UNDECLARED || ( iScope & HB_VS_LOCAL_MEMVAR ) )
|
||||
{
|
||||
hb_compErrorMacro( HB_COMP_PARAM, szText );
|
||||
break;
|
||||
fFound = HB_TRUE;
|
||||
if( fMacro && iScope == HB_VS_UNDECLARED )
|
||||
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_AMBIGUOUS_VAR, pszVarName, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( HB_SUPPORT_MACRODECL )
|
||||
{
|
||||
HB_SIZE nPrefix = n - iSize - 1;
|
||||
if( nPrefix > 0 )
|
||||
{
|
||||
char * pszPrefix = ( char * ) hb_xgrab( nPrefix + 1 );
|
||||
memcpy( pszPrefix, szText, nPrefix );
|
||||
pszPrefix[ nPrefix ] = '\0';
|
||||
hb_compGenPushString( pszPrefix, nPrefix + 1, HB_COMP_PARAM );
|
||||
hb_xfree( pszPrefix );
|
||||
if( iParts++ > 0 )
|
||||
hb_compGenPCode1( HB_P_PLUS, HB_COMP_PARAM );
|
||||
}
|
||||
hb_compGenPushVar( pszVarName, HB_COMP_PARAM );
|
||||
if( iParts++ > 0 )
|
||||
hb_compGenPCode1( HB_P_PLUS, HB_COMP_PARAM );
|
||||
if( n < nLen && szText[ n ] == '.' )
|
||||
++n;
|
||||
szText += n;
|
||||
nLen -= n;
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_compErrorMacro( HB_COMP_PARAM, szText );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( ! HB_SUPPORT_HARBOUR )
|
||||
fFound = HB_TRUE; /* always macro substitution in Clipper */
|
||||
}
|
||||
}
|
||||
if( nLen > 0 )
|
||||
{
|
||||
hb_compGenPushString( szText, nLen + 1, HB_COMP_PARAM );
|
||||
if( iParts > 0 )
|
||||
hb_compGenPCode1( HB_P_PLUS, HB_COMP_PARAM );
|
||||
}
|
||||
|
||||
return fFound;
|
||||
if( fFound )
|
||||
hb_compGenPCode1( HB_P_MACROTEXT, HB_COMP_PARAM );
|
||||
|
||||
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = iEarlyEvalPass;
|
||||
}
|
||||
|
||||
|
||||
@@ -1844,7 +1888,7 @@ static PFUNCTION hb_compFunctionNew( HB_COMP_DECL, const char * szName, HB_SYMBO
|
||||
pFunc->szName = szName;
|
||||
pFunc->cScope = cScope;
|
||||
pFunc->iStaticsBase = HB_COMP_PARAM->iStaticCnt;
|
||||
pFunc->bLateEval = HB_TRUE;
|
||||
pFunc->iEarlyEvalPass = 0;
|
||||
pFunc->fVParams = HB_FALSE;
|
||||
pFunc->bError = HB_FALSE;
|
||||
|
||||
@@ -2498,7 +2542,7 @@ static void hb_compGenVariablePCode( HB_COMP_DECL, HB_BYTE bPCode, const char *
|
||||
* Clipper always assumes a memvar variable if undeclared variable
|
||||
* is popped (a value is asssigned to a variable).
|
||||
*/
|
||||
if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_HARBOUR ) )
|
||||
if( HB_SUPPORT_HARBOUR )
|
||||
bGenCode = HB_COMP_PARAM->fForceMemvars; /* harbour compatibility */
|
||||
else
|
||||
bGenCode = ( HB_COMP_PARAM->fForceMemvars || bPCode == HB_P_POPVARIABLE );
|
||||
@@ -2507,7 +2551,8 @@ static void hb_compGenVariablePCode( HB_COMP_DECL, HB_BYTE bPCode, const char *
|
||||
{
|
||||
/* -v switch was used -> assume it is a memvar variable
|
||||
*/
|
||||
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_MEMVAR_ASSUMED, szVarName, NULL );
|
||||
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 0 || HB_SUPPORT_MACRODECL )
|
||||
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_MEMVAR_ASSUMED, szVarName, NULL );
|
||||
|
||||
if( bPCode == HB_P_POPVARIABLE )
|
||||
bPCode = HB_P_POPMEMVAR;
|
||||
@@ -2516,7 +2561,7 @@ static void hb_compGenVariablePCode( HB_COMP_DECL, HB_BYTE bPCode, const char *
|
||||
else
|
||||
bPCode = HB_P_PUSHMEMVARREF;
|
||||
}
|
||||
else
|
||||
else if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 0 || HB_SUPPORT_MACRODECL )
|
||||
hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_AMBIGUOUS_VAR, szVarName, NULL );
|
||||
|
||||
hb_compGenVarPCode( bPCode, szVarName, HB_COMP_PARAM );
|
||||
@@ -2582,18 +2627,24 @@ void hb_compGenMessageData( const char * szMsg, HB_BOOL bIsObject, HB_COMP_DECL
|
||||
hb_compGenMessage( hb_compIdentifierNew( HB_COMP_PARAM, szResult, HB_IDENT_COPY ), bIsObject, HB_COMP_PARAM );
|
||||
}
|
||||
|
||||
static void hb_compCheckEarlyMacroEval( HB_COMP_DECL, const char *szVarName )
|
||||
static void hb_compCheckEarlyMacroEval( HB_COMP_DECL, const char *szVarName, int iScope )
|
||||
{
|
||||
int iScope = hb_compVariableScope( HB_COMP_PARAM, szVarName );
|
||||
|
||||
if( iScope == HB_VS_CBLOCAL_VAR ||
|
||||
/* iScope == HB_VS_LOCAL_VAR || */
|
||||
/* iScope == HB_VS_LOCAL_VAR || */ /* codeblock parameters */
|
||||
iScope == HB_VS_STATIC_VAR ||
|
||||
iScope == HB_VS_GLOBAL_STATIC ||
|
||||
iScope == HB_VS_LOCAL_FIELD ||
|
||||
iScope == HB_VS_GLOBAL_FIELD )
|
||||
{
|
||||
hb_compErrorCodeblock( HB_COMP_PARAM, szVarName );
|
||||
/* Disable early evaluation if codeblock contains macros and
|
||||
* declared variables, i.e. {|x| cLocal + &cPriv }
|
||||
* and support for macros with declared symbols is enabled.
|
||||
*/
|
||||
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 1 &&
|
||||
HB_SUPPORT_MACRODECL )
|
||||
HB_COMP_PARAM->functions.pLast->iEarlyEvalPass = 0;
|
||||
else
|
||||
hb_compErrorCodeblock( HB_COMP_PARAM, szVarName );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2612,16 +2663,12 @@ void hb_compGenPopVar( const char * szVarName, HB_COMP_DECL ) /* generates the p
|
||||
int iVar, iScope;
|
||||
PVAR pVar;
|
||||
|
||||
if( ! HB_COMP_PARAM->functions.pLast->bLateEval )
|
||||
{
|
||||
/* pseudo-generation of pcode for a codeblock with macro symbol */
|
||||
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName );
|
||||
return;
|
||||
}
|
||||
|
||||
pVar = hb_compVariableFind( HB_COMP_PARAM, szVarName, &iVar, &iScope );
|
||||
if( pVar )
|
||||
{
|
||||
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 1 )
|
||||
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName, iScope );
|
||||
|
||||
switch( iScope )
|
||||
{
|
||||
case HB_VS_LOCAL_VAR:
|
||||
@@ -2668,12 +2715,12 @@ void hb_compGenPopVar( const char * szVarName, HB_COMP_DECL ) /* generates the p
|
||||
break;
|
||||
|
||||
default:
|
||||
/* undeclared variable */
|
||||
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_POPVARIABLE, szVarName );
|
||||
pVar = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if( !pVar )
|
||||
{ /* undeclared variable */
|
||||
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_POPVARIABLE, szVarName );
|
||||
}
|
||||
@@ -2696,16 +2743,12 @@ void hb_compGenPushVar( const char * szVarName, HB_COMP_DECL )
|
||||
int iVar, iScope;
|
||||
PVAR pVar;
|
||||
|
||||
if( ! HB_COMP_PARAM->functions.pLast->bLateEval )
|
||||
{
|
||||
/* pseudo-generation of pcode for a codeblock with macro symbol */
|
||||
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName );
|
||||
return;
|
||||
}
|
||||
|
||||
pVar = hb_compVariableFind( HB_COMP_PARAM, szVarName, &iVar, &iScope );
|
||||
if( pVar )
|
||||
{
|
||||
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 1 )
|
||||
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName, iScope );
|
||||
|
||||
switch( iScope )
|
||||
{
|
||||
case HB_VS_LOCAL_VAR:
|
||||
@@ -2742,12 +2785,12 @@ void hb_compGenPushVar( const char * szVarName, HB_COMP_DECL )
|
||||
break;
|
||||
|
||||
default:
|
||||
/* undeclared variable */
|
||||
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHVARIABLE, szVarName );
|
||||
pVar = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if( !pVar )
|
||||
{ /* undeclared variable */
|
||||
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHVARIABLE, szVarName );
|
||||
}
|
||||
@@ -2758,16 +2801,12 @@ void hb_compGenPushVarRef( const char * szVarName, HB_COMP_DECL ) /* generates t
|
||||
int iVar, iScope;
|
||||
PVAR pVar;
|
||||
|
||||
if( ! HB_COMP_PARAM->functions.pLast->bLateEval )
|
||||
{
|
||||
/* pseudo-generation of pcode for a codeblock with macro symbol */
|
||||
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName );
|
||||
return;
|
||||
}
|
||||
|
||||
pVar = hb_compVariableFind( HB_COMP_PARAM, szVarName, &iVar, &iScope );
|
||||
if( pVar )
|
||||
{
|
||||
if( HB_COMP_PARAM->functions.pLast->iEarlyEvalPass == 1 )
|
||||
hb_compCheckEarlyMacroEval( HB_COMP_PARAM, szVarName, iScope );
|
||||
|
||||
switch( iScope )
|
||||
{
|
||||
case HB_VS_LOCAL_VAR:
|
||||
@@ -2796,13 +2835,11 @@ void hb_compGenPushVarRef( const char * szVarName, HB_COMP_DECL ) /* generates t
|
||||
break;
|
||||
|
||||
default:
|
||||
/* undeclared variable */
|
||||
/* field cannot be passed by the reference - assume the memvar */
|
||||
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHMEMVARREF, szVarName );
|
||||
break;
|
||||
pVar = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if( !pVar )
|
||||
{ /* undeclared variable */
|
||||
/* field cannot be passed by the reference - assume the memvar */
|
||||
hb_compGenVariablePCode( HB_COMP_PARAM, HB_P_PUSHMEMVARREF, szVarName );
|
||||
@@ -3470,13 +3507,13 @@ static void hb_compLineNumberDefEnd( HB_COMP_DECL )
|
||||
/*
|
||||
* Start a new fake-function that will hold pcodes for a codeblock
|
||||
*/
|
||||
void hb_compCodeBlockStart( HB_COMP_DECL, HB_BOOL bLateEval )
|
||||
void hb_compCodeBlockStart( HB_COMP_DECL, int iEarlyEvalPass )
|
||||
{
|
||||
PFUNCTION pBlock;
|
||||
|
||||
pBlock = hb_compFunctionNew( HB_COMP_PARAM, NULL, HB_FS_STATIC | HB_FS_LOCAL );
|
||||
pBlock->pOwner = HB_COMP_PARAM->functions.pLast;
|
||||
pBlock->bLateEval = bLateEval;
|
||||
pBlock = hb_compFunctionNew( HB_COMP_PARAM, NULL, HB_FS_STATIC | HB_FS_LOCAL );
|
||||
pBlock->pOwner = HB_COMP_PARAM->functions.pLast;
|
||||
pBlock->iEarlyEvalPass = iEarlyEvalPass;
|
||||
|
||||
HB_COMP_PARAM->functions.pLast = pBlock;
|
||||
}
|
||||
@@ -3707,6 +3744,18 @@ void hb_compCodeBlockRewind( HB_COMP_DECL )
|
||||
pCodeblock->pJumps = NULL;
|
||||
pCodeblock->nJumps = 0;
|
||||
}
|
||||
while( pCodeblock->pDetached )
|
||||
{
|
||||
PVAR pVar = pCodeblock->pDetached;
|
||||
pCodeblock->pDetached = pVar->pNext;
|
||||
hb_xfree( pVar );
|
||||
}
|
||||
while( pCodeblock->pLocals )
|
||||
{
|
||||
PVAR pVar = pCodeblock->pLocals;
|
||||
pCodeblock->pLocals = pVar->pNext;
|
||||
hb_xfree( pVar );
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
@@ -140,8 +140,9 @@ void hb_compPrintModes( HB_COMP_DECL )
|
||||
"\n s[-] allow indexed assignment on all types",
|
||||
"\n x[-] extended Xbase++ mode",
|
||||
"\n u[-] strings in user encoding",
|
||||
"\n j[+] turn off jump optimization in pcode",
|
||||
"\n d[-] accept macros with declared symbols",
|
||||
"\n m[+] turn off macrotext substitution",
|
||||
"\n j[+] turn off jump optimization in pcode",
|
||||
"\n ? this info",
|
||||
"\n"
|
||||
};
|
||||
@@ -154,8 +155,10 @@ void hb_compPrintModes( HB_COMP_DECL )
|
||||
HB_COMPFLAG_RT_MACRO,
|
||||
HB_COMPFLAG_ARRSTR,
|
||||
HB_COMPFLAG_XBASE,
|
||||
~HB_COMPFLAG_OPTJUMP,
|
||||
HB_COMPFLAG_USERCP,
|
||||
HB_COMPFLAG_MACRODECL,
|
||||
~HB_COMPFLAG_MACROTEXT,
|
||||
~HB_COMPFLAG_OPTJUMP,
|
||||
};
|
||||
int iLine;
|
||||
|
||||
|
||||
@@ -291,6 +291,10 @@ static HB_BOOL hb_pp_CompilerSwitch( void * cargo, const char * szSwitch,
|
||||
iFlag = HB_COMPFLAG_MACROTEXT;
|
||||
iValue = !iValue;
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
iFlag = HB_COMPFLAG_MACRODECL;
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
iFlag = HB_COMPFLAG_ARRSTR;
|
||||
|
||||
Reference in New Issue
Block a user