diff --git a/ChangeLog.txt b/ChangeLog.txt index d6e6f8187f..68eacb8507 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,17 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2015-12-04 23:05 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * include/hbexpra.c + ! accept strings passed in 2-nd parameter of _GET_() function + with the highest priority for macro and macroalias expressions + ! fixed late evaluation of macroalias expressions in GET variables. + Thanks to Volodimyr for information about the problem and self + contain code example. + + * include/hbexprb.c + ! fixed typo in SetGet expression LValue validation + 2015-12-04 22:56 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * contrib/hbnetio/netiosrv.c ! fixed typo in previous modification diff --git a/include/hbexpra.c b/include/hbexpra.c index 166e3b3716..5365d60681 100644 --- a/include/hbexpra.c +++ b/include/hbexpra.c @@ -377,55 +377,56 @@ PHB_EXPR hb_compExprNewFunCall( PHB_EXPR pName, PHB_EXPR pParms, HB_COMP_DECL ) } } } - else if( pArg->ExprType == HB_ET_MACRO ) + else if( pArg->ExprType == HB_ET_MACRO || + ( pArg->ExprType == HB_ET_ALIASVAR && + ( pArg->value.asAlias.pAlias->ExprType == HB_ET_MACRO || + pArg->value.asAlias.pVar->ExprType == HB_ET_MACRO ) ) ) { - /* @ 0,0 GET &var => __Get( NIL, var,... ) - * @ 0,0 GET var&var => __Get( NIL, "var&var",... ) - */ - pName->value.asSymbol.name = "__GET"; - if( pArg->value.asMacro.pExprList == NULL ) + const char * szText = NULL; + + if( pArg->ExprType == HB_ET_ALIASVAR ) { - /* Simple macro expansion (not a parenthesized expressions) - */ - PHB_EXPR pFirst; + const char * szAlias = NULL, * szAliasPref = "", + * szVar = NULL, * szVarPref = ""; - pFirst = pArg; /* first argument */ - pNext = pFirst->pNext; /* second argument */ - if( pNext ) - pNext = pNext->pNext; /* third argument */ + if( pArg->value.asAlias.pAlias->ExprType == HB_ET_ALIAS ) + szAlias = pArg->value.asAlias.pAlias->value.asSymbol.name; + else if( pArg->value.asAlias.pAlias->ExprType == HB_ET_MACRO && + pArg->value.asAlias.pAlias->value.asMacro.pExprList == NULL ) + { + szAlias = pArg->value.asAlias.pAlias->value.asMacro.szMacro; + if( pArg->value.asAlias.pAlias->value.asMacro.cMacroOp == '&' ) + szAliasPref = "&"; + } - pArg = hb_compExprNewNil( HB_COMP_PARAM ); /* replace 1st with NIL */ - pParms->value.asList.pExprList = pArg; - pArg->pNext = pFirst->pNext; - if( pFirst->value.asMacro.cMacroOp == '&' ) + if( pArg->value.asAlias.pVar->ExprType == HB_ET_VARIABLE ) + szVar = pArg->value.asAlias.pVar->value.asSymbol.name; + else if( pArg->value.asAlias.pVar->ExprType == HB_ET_MACRO && + pArg->value.asAlias.pVar->value.asMacro.pExprList == NULL ) { - /* simple &variable - replace the second argument with - * a variable name - */ - const char * szName = pFirst->value.asMacro.szMacro; - if( pFirst->pNext ) - HB_COMP_EXPR_FREE( pFirst->pNext ); /* delete a second argument */ - pArg->pNext = hb_compExprNewVar( szName, HB_COMP_PARAM ); - pArg->pNext->pNext = pNext; /* restore third argument */ + szVar = pArg->value.asAlias.pVar->value.asMacro.szMacro; + if( pArg->value.asAlias.pVar->value.asMacro.cMacroOp == '&' ) + szVarPref = "&"; } - else + + if( szAlias != NULL && szVar != NULL ) { - /* text substitution text&variable - replace the second - * argument with a string - */ - if( pArg->pNext == NULL ) - { - /* no second argument */ - const char *szText = pFirst->value.asMacro.szMacro; - pArg->pNext = hb_compExprNewString( szText, strlen( szText ), HB_FALSE, HB_COMP_PARAM ); - pArg->pNext->pNext = pNext; - } + if( pArg->pNext && pArg->pNext->ExprType == HB_ET_STRING ) + szText = ""; + else + szText = hb_xstrcpy( NULL, szAliasPref, szAlias, "->", szVarPref, szVar, NULL ); } - HB_COMP_EXPR_FREE( pFirst ); /* delete first argument */ } - else + else if( pArg->value.asMacro.pExprList == NULL ) + /* Simple macro expansion (not a parenthesized expressions) */ + szText = pArg->value.asMacro.szMacro; + + pName->value.asSymbol.name = "__GET"; + if( szText == NULL ) { /* @ 0,0 GET &(var) + * @ 0,0 GET &(var)->var + * @ 0,0 GET var->&(var) */ #if defined( HB_MACRO_SUPPORT ) hb_macroError( EG_SYNTAX, HB_COMP_PARAM ); @@ -433,6 +434,44 @@ PHB_EXPR hb_compExprNewFunCall( PHB_EXPR pName, PHB_EXPR pParms, HB_COMP_DECL ) hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_GET_COMPLEX_MACRO, NULL, NULL ); #endif } + else + { + /* @ 0,0 GET &var => __Get( NIL, var,... ) + * @ 0,0 GET var&var => __Get( NIL, "var&var",... ) + * @ 0,0 GET &var->var => __Get( NIL, "&var->var",... ) + * @ 0,0 GET var->var&var => __Get( NIL, "var->var&var",... ) + * @ 0,0 GET var&var->&var => __Get( NIL, "var&var->&var",... ) + */ + PHB_EXPR pFirst = pArg; /* save first argument */ + + pArg = hb_compExprNewNil( HB_COMP_PARAM ); /* replace 1-st with NIL */ + if( pFirst->pNext && pFirst->pNext->ExprType == HB_ET_STRING ) + pArg->pNext = pFirst->pNext; + else + { + if( pArg->ExprType == HB_ET_ALIASVAR ) + pArg->pNext = hb_compExprNewString( szText, strlen( szText ), HB_TRUE, HB_COMP_PARAM ); + else if( pFirst->value.asMacro.cMacroOp == '&' ) + /* simple &variable - replace the second argument with + * a variable name + */ + pArg->pNext = hb_compExprNewVar( szText, HB_COMP_PARAM ); + else + /* text substitution text&variable - replace the second + * argument with a string + */ + pArg->pNext = hb_compExprNewString( szText, strlen( szText ), HB_FALSE, HB_COMP_PARAM ); + + if( pFirst->pNext ) + { + pArg->pNext->pNext = pFirst->pNext->pNext; + HB_COMP_EXPR_FREE( pFirst->pNext ); /* delete a second argument */ + } + } + HB_COMP_EXPR_FREE( pFirst ); /* delete first argument */ + /* set an updated list of arguments */ + pParms->value.asList.pExprList = pArg; + } } else { @@ -443,20 +482,16 @@ PHB_EXPR hb_compExprNewFunCall( PHB_EXPR pName, PHB_EXPR pParms, HB_COMP_DECL ) pArg->pNext = NULL; /* replace first argument with a set/get codeblock */ #if ! defined( HB_MACRO_SUPPORT ) - if( pArg->ExprType == HB_ET_VARIABLE ) + if( pArg->ExprType == HB_ET_VARIABLE && + ! hb_compVariableFind( HB_COMP_PARAM, pArg->value.asSymbol.name, NULL, NULL ) ) { - if( hb_compVariableFind( HB_COMP_PARAM, pArg->value.asSymbol.name, NULL, NULL ) ) - pArg = hb_compExprSetGetBlock( pArg, HB_COMP_PARAM ); - else - { - /* Undeclared variable name - create a set/get codeblock - * at runtime - */ - if( HB_COMP_PARAM->iWarnings >= 2 ) - hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_AMBIGUOUS_VAR, pArg->value.asSymbol.name, NULL ); - HB_COMP_EXPR_FREE( pArg ); - pArg = hb_compExprNewNil( HB_COMP_PARAM ); - } + /* Undeclared variable name - create a set/get codeblock + * at runtime + */ + if( HB_COMP_PARAM->iWarnings >= 2 ) + hb_compGenWarning( HB_COMP_PARAM, hb_comp_szWarnings, 'W', HB_COMP_WARN_AMBIGUOUS_VAR, pArg->value.asSymbol.name, NULL ); + HB_COMP_EXPR_FREE( pArg ); + pArg = hb_compExprNewNil( HB_COMP_PARAM ); } else #endif diff --git a/include/hbexprb.c b/include/hbexprb.c index c7b5a67c45..21c0aae065 100644 --- a/include/hbexprb.c +++ b/include/hbexprb.c @@ -2603,7 +2603,7 @@ static HB_EXPR_FUNC( hb_compExprUseSetGet ) if( ! HB_SUPPORT_HARBOUR ) pSelf->value.asSetGet.pVar = hb_compExprListStrip( pSelf->value.asSetGet.pVar, HB_COMP_PARAM ); #endif - HB_EXPR_USE( pSelf->value.asSetGet.pVar, HB_EA_LVALUE ); + HB_EXPR_USE( pSelf->value.asSetGet.pExpr, HB_EA_LVALUE ); break; case HB_EA_ARRAY_AT: case HB_EA_ARRAY_INDEX: