diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 43a3c9122d..7ee5b92c2d 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,49 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ * fixed <-x-> match marker +2006-02-14 11:40 UTC+0100 Ryszard Glab + * include/hbapiitm.h + * include/hbcomp.h + * include/hbexpra.c + * include/hbexprb.c + * include/hbexprc.c + * include/hbexprop.h + * include/hbpcode.h + * source/common/expropt1.c + * source/common/hbfsapi.c + * source/compiler/expropta.c + * source/compiler/exproptb.c + * source/compiler/exproptc.c + * source/compiler/genc.c + * source/compiler/harbour.c + * source/compiler/harbour.l + * source/compiler/harbour.y + * source/compiler/hbdead.c + * source/compiler/hbfix.c + * source/compiler/hbpcode.c + * source/compiler/hbstripl.c + * source/macro/macro.y + * source/macro/macroa.c + * source/macro/macrob.c + * source/macro/macroc.c + * source/pp/ppcore.c + * source/vm/hvm.c + * source/vm/itemapi.c + * fixed many more memory leaks in the compiler + (the Harbour code compiles itself with no memory leaks). + However there are still leaks when the compiler aborts + compilation due to errors. + + added optimalization of '+=' '-=' '*=' '/=' operators + + added hb_itemGetNDDec(), + hb_itemPutHBLong(), + hb_itemPutNumType() + borrowed from xHarbour + + NOTE: new pcodes: + HB_[PLUS|MINUS|MULT|DIV]EQ + HB_[PLUS|MINUS|MULT|DIV]EQPOP + recompile all sources. + 2006-02-12 14:33 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbapi.h * harbour/include/hbdefs.h diff --git a/harbour/include/hbapiitm.h b/harbour/include/hbapiitm.h index ce69bff2c7..48860c9e61 100644 --- a/harbour/include/hbapiitm.h +++ b/harbour/include/hbapiitm.h @@ -85,6 +85,7 @@ extern HB_EXPORT char * hb_itemGetDS ( PHB_ITEM pItem, char * szDate ); extern HB_EXPORT long hb_itemGetDL ( PHB_ITEM pItem ); extern HB_EXPORT BOOL hb_itemGetL ( PHB_ITEM pItem ); extern HB_EXPORT double hb_itemGetND ( PHB_ITEM pItem ); +extern HB_EXPORT double hb_itemGetNDDec ( PHB_ITEM pItem, int * piDec ); extern HB_EXPORT int hb_itemGetNI ( PHB_ITEM pItem ); extern HB_EXPORT long hb_itemGetNL ( PHB_ITEM pItem ); extern HB_EXPORT HB_LONG hb_itemGetNInt ( PHB_ITEM pItem ); @@ -103,6 +104,7 @@ extern HB_EXPORT void hb_itemSetCMemo ( PHB_ITEM pItem ); extern HB_EXPORT PHB_ITEM hb_itemPutD ( PHB_ITEM pItem, int iYear, int iMonth, int iDay ); extern HB_EXPORT PHB_ITEM hb_itemPutDS ( PHB_ITEM pItem, const char * szDate ); extern HB_EXPORT PHB_ITEM hb_itemPutDL ( PHB_ITEM pItem, long lJulian ); +extern HB_EXPORT PHB_ITEM hb_itemPutHBLong( PHB_ITEM pItem, HB_LONG lNumber ); extern HB_EXPORT PHB_ITEM hb_itemPutL ( PHB_ITEM pItem, BOOL bValue ); extern HB_EXPORT PHB_ITEM hb_itemPutND ( PHB_ITEM pItem, double dNumber ); extern HB_EXPORT PHB_ITEM hb_itemPutNI ( PHB_ITEM pItem, int iNumber ); @@ -111,8 +113,10 @@ extern HB_EXPORT PHB_ITEM hb_itemPutNInt ( PHB_ITEM pItem, HB_LONG lNumber ); extern HB_EXPORT PHB_ITEM hb_itemPutNIntLen( PHB_ITEM pItem, HB_LONG lNumber, int iWidth ); extern HB_EXPORT PHB_ITEM hb_itemPutNLen ( PHB_ITEM pItem, double dNumber, int iWidth, int iDec ); extern HB_EXPORT PHB_ITEM hb_itemPutNDLen ( PHB_ITEM pItem, double dNumber, int iWidth, int iDec ); +extern HB_EXPORT PHB_ITEM hb_itemPutNDDec ( PHB_ITEM pItem, double dNumber, int iDec ); extern HB_EXPORT PHB_ITEM hb_itemPutNILen ( PHB_ITEM pItem, int iNumber, int iWidth ); extern HB_EXPORT PHB_ITEM hb_itemPutNLLen ( PHB_ITEM pItem, long lNumber, int iWidth ); +extern HB_EXPORT PHB_ITEM hb_itemPutNumType( PHB_ITEM pItem, double dNumber, int iDec, int iType1, int iType2 ); extern HB_EXPORT PHB_ITEM hb_itemPutPtr ( PHB_ITEM pItem, void * pValue ); extern HB_EXPORT BOOL hb_itemRelease ( PHB_ITEM pItem ); extern HB_EXPORT PHB_ITEM hb_itemReturn ( PHB_ITEM pItem ); diff --git a/harbour/include/hbcomp.h b/harbour/include/hbcomp.h index dda89ca0d0..931d7e359c 100644 --- a/harbour/include/hbcomp.h +++ b/harbour/include/hbcomp.h @@ -464,6 +464,7 @@ extern void hb_compCodeTraceMarkDead( PFUNCTION pFunc ); extern int hb_compYACCMain( char * szName ); #endif extern BOOL hb_compInclude( char * szFileName, HB_PATHNAMES * pSearchPath ); /* end #include support */ +extern void hb_compParserStop( void ); /* cleanup the bison parser */ extern char * hb_comp_buffer; /* yacc input buffer */ diff --git a/harbour/include/hbexpra.c b/harbour/include/hbexpra.c index 88f2f48106..791e4f1e1c 100644 --- a/harbour/include/hbexpra.c +++ b/harbour/include/hbexpra.c @@ -381,10 +381,20 @@ HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) if( ( strcmp( "EVAL", pName->value.asSymbol ) == 0 ) && iCount ) { + HB_EXPR_PTR pEval; /* Optimize Eval( bBlock, [ArgList] ) to: bBlock:Eval( [ArgList] ) */ - return hb_compExprNewMethodCall( hb_compExprNewSend( pParms->value.asList.pExprList, - hb_strdup( "EVAL" ) ), - hb_compExprNewArgList( pParms->value.asList.pExprList->pNext ) ); + pEval = hb_compExprNewMethodCall( +#ifndef HB_MACRO_SUPPORT + hb_compExprNewSend( pParms->value.asList.pExprList, hb_compIdentifierNew( "EVAL", TRUE ) ), +#else + hb_compExprNewSend( pParms->value.asList.pExprList, "EVAL" ), +#endif + hb_compExprNewArgList( pParms->value.asList.pExprList->pNext ) ); + + pParms->value.asList.pExprList = NULL; + HB_EXPR_PCODE1( hb_compExprDelete, pParms ); + HB_EXPR_PCODE1( hb_compExprDelete, pName ); + return pEval; } else if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_XBASE ) && (( strcmp( "__DBLIST", pName->value.asSymbol ) == 0 ) && iCount >= 10) ) @@ -484,6 +494,7 @@ HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) if( pArg->ExprType == HB_ET_ARRAYAT ) { HB_EXPR_PTR pIndex, pVar; + HB_EXPR_PTR pBase; #ifdef HB_MACRO_SUPPORT HB_XFREE( pName->value.asSymbol ); @@ -495,6 +506,7 @@ HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) * ((a->[ i ])->[ j ]) */ pVar = HB_EXPR_USE( pArg->value.asList.pExprList, HB_EA_REDUCE ); + pBase = pVar; pIndex = HB_EXPR_USE( pArg->value.asList.pIndex, HB_EA_REDUCE ); pIndex->pNext = NULL; while( pVar->ExprType == HB_ET_ARRAYAT ) @@ -532,7 +544,7 @@ HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) hb_compExprClear( pArg ); /* Create an array with index elements */ - pIndex = hb_compExprNewArray( hb_compExprNewList( pIndex ) ); + pIndex = HB_EXPR_PCODE1(hb_compExprNewArray, hb_compExprNewList( pIndex ) ); /* The array with index elements have to be the sixth argument * of __GETA() call */ @@ -570,6 +582,8 @@ HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms ) } } } + pBase->value.asList.pExprList = NULL; + hb_compExprClear( pBase ); } else if( pArg->ExprType == HB_ET_MACRO ) { @@ -760,6 +774,50 @@ HB_EXPR_PTR hb_compExprNewString( char *szValue ) return pExpr; } +/* Creates a new literal array { item1, item2, ... itemN } + * 'pArrList' is a list of array elements + */ +#ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR pArrList, HB_MACRO_DECL ) +#else +HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR pArrList ) +#endif +{ + HB_EXPR_PTR pExpr; + + HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArray()")); + + pArrList->ExprType = HB_ET_ARRAY; /* change type from ET_LIST */ + pArrList->ValType = HB_EV_ARRAY; + pArrList->ulLength = 0; + + pExpr = pArrList->value.asList.pExprList; /* get first element on the list */ + /* Now we need to replace all EO_NONE expressions with ET_NIL expressions + * If EO_NONE is the first expression and there is no more expressions + * then it is an empty array {} and ET_NIL cannot be used + */ + if( pExpr->ExprType == HB_ET_NONE && pExpr->pNext == NULL ) + { + pArrList->value.asList.pExprList = NULL; + HB_EXPR_PCODE1( hb_compExprDelete, pExpr ); + } + else + { + /* there are at least one non-empty element specified + */ + while( pExpr ) + { + /* if empty element was specified replace it with NIL value */ + if( pExpr->ExprType == HB_ET_NONE ) + pExpr->ExprType = HB_ET_NIL; + pExpr = pExpr->pNext; + ++pArrList->ulLength; + } + } + pArrList->value.asList.pIndex = NULL; + return pArrList; +} + /* Creates new array access expression * pArray[ pIndex ] @@ -1054,11 +1112,12 @@ HB_EXPR_PTR hb_compExprSetGetBlock( HB_EXPR_PTR pExpr ) /* create {|var| expression * NOTE: this is not a valid variable name so there will be no collisions */ - pIIF =hb_compExprNewVar( hb_strdup("~1") ); /* create var==NIL */ #ifdef HB_MACRO_SUPPORT + pIIF =hb_compExprNewVar( hb_strdup("~1") ); pIIF = hb_compExprSetOperand( hb_compExprNewEQ( pIIF ), hb_compExprNewNil(), HB_MACRO_PARAM ); #else + pIIF =hb_compExprNewVar( hb_compIdentifierNew("~1",TRUE) ); pIIF = hb_compExprSetOperand( hb_compExprNewEQ( pIIF ), hb_compExprNewNil() ); #endif /* create ( var==NIL, */ @@ -1066,7 +1125,11 @@ HB_EXPR_PTR hb_compExprSetGetBlock( HB_EXPR_PTR pExpr ) /* create ( var==NIL, , */ pIIF = hb_compExprAddListExpr( pIIF, pExpr ); /* create var */ +#ifdef HB_MACRO_SUPPORT pSet =hb_compExprNewVar( hb_strdup("~1") ); +#else + pSet =hb_compExprNewVar( hb_compIdentifierNew("~1",TRUE) ); +#endif /* create :=var */ pSet = hb_compExprAssign( hb_compExprClone( pExpr ), pSet ); /* create ( var==nil, , :=var ) */ diff --git a/harbour/include/hbexprb.c b/harbour/include/hbexprb.c index 4476cb1d7b..6b3de06df7 100644 --- a/harbour/include/hbexprb.c +++ b/harbour/include/hbexprb.c @@ -487,7 +487,11 @@ static HB_EXPR_FUNC( hb_compExprUseCodeblock ) HB_EXPR_PTR pNext; hb_compExprCBVarDel( pSelf->value.asCodeblock.pLocals ); - + + if( pSelf->value.asCodeblock.string ) + { + HB_XFREE( pSelf->value.asCodeblock.string ); + } /* Delete all expressions of the block. */ while( pExp ) @@ -1853,11 +1857,8 @@ static HB_EXPR_FUNC( hb_compExprUseAliasVar ) case HB_EA_DELETE: HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asAlias.pAlias ); - /* NOTE: variable name is released only during macro compilation */ -#if defined( HB_MACRO_SUPPORT ) if( pSelf->value.asAlias.pVar ) HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asAlias.pVar ); -#endif break; } return pSelf; @@ -2005,7 +2006,12 @@ static HB_EXPR_FUNC( hb_compExprUseRTVariable ) case HB_EA_PUSH_POP: case HB_EA_STATEMENT: + break; case HB_EA_DELETE: +#if ! defined( HB_MACRO_SUPPORT ) + if( ! pSelf->value.asRTVar.szName ) + HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asRTVar.pMacro ); +#endif break; } return pSelf; @@ -2143,16 +2149,17 @@ static HB_EXPR_FUNC( hb_compExprUseSend ) */ hb_compWarnMeaningless( pSelf ); } + break; case HB_EA_DELETE: -#if defined( HB_MACRO_SUPPORT ) { HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMessage.pObject ); if( pSelf->value.asMessage.pParms ) HB_EXPR_PCODE1( hb_compExprDelete, pSelf->value.asMessage.pParms ); +#if defined( HB_MACRO_SUPPORT ) HB_XFREE( pSelf->value.asMessage.szMessage ); - } #endif + } break; } return pSelf; diff --git a/harbour/include/hbexprc.c b/harbour/include/hbexprc.c index 6c5ed2793b..79d315dcd1 100644 --- a/harbour/include/hbexprc.c +++ b/harbour/include/hbexprc.c @@ -144,21 +144,81 @@ void hb_compExprPushOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) /* call pop message with one argument */ HB_EXPR_GENPCODE2( hb_compGenPCode2, HB_P_SENDSHORT, 1, ( BOOL ) 1 ); + + return; } /* TODO: add a special code for arrays to correctly handle a[ i++ ]++ */ - else + else if( ( bOpEq == HB_P_PLUS || bOpEq == HB_P_MINUS || + bOpEq == HB_P_MULT || bOpEq == HB_P_DIVIDE ) && + ( pSelf->value.asOperator.pLeft->ExprType == HB_ET_VARIABLE ) ) { - /* push old value */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - /* push increment value */ - HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - /* perform operation and duplicate the new value */ - HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); - HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); - /* pop the new value into variable and leave the copy on the stack */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + /* NOTE: direct type change */ + pSelf->value.asOperator.pLeft->ExprType = HB_ET_VARREF; + + if( pSelf->value.asOperator.pRight->ExprType == HB_ET_NUMERIC || + pSelf->value.asOperator.pRight->ExprType == HB_ET_STRING || + pSelf->value.asOperator.pRight->ExprType == HB_ET_VARIABLE ) + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + if( pSelf->value.asOperator.pRight->ExprType == HB_ET_VARIABLE ) + { + /* NOTE: direct type change */ + pSelf->value.asOperator.pRight->ExprType = HB_ET_VARREF; + } + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + switch( bOpEq ) + { + case HB_P_PLUS: + bOpEq = HB_P_PLUSEQ; + break; + case HB_P_MINUS: + bOpEq = HB_P_MINUSEQ; + break; + case HB_P_MULT: + bOpEq = HB_P_MULTEQ; + break; + case HB_P_DIVIDE: + bOpEq = HB_P_DIVEQ; + break; + } + HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); + return; + } + else if( pSelf->value.asOperator.pRight->ExprType == HB_ET_VARIABLE ) + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* NOTE: direct type change */ + pSelf->value.asOperator.pRight->ExprType = HB_ET_VARREF; + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + switch( bOpEq ) + { + case HB_P_PLUS: + bOpEq = HB_P_PLUSEQ; + break; + case HB_P_MINUS: + bOpEq = HB_P_MINUSEQ; + break; + case HB_P_MULT: + bOpEq = HB_P_MULTEQ; + break; + case HB_P_DIVIDE: + bOpEq = HB_P_DIVEQ; + break; + } + HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); + return; + } } + /* push old value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* perform operation and duplicate the new value */ + HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); + HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_DUPLICATE ); + /* pop the new value into variable and leave the copy on the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); } /* Generates pcodes for = syntax @@ -198,18 +258,75 @@ void hb_compExprUseOperEq( HB_EXPR_PTR pSelf, BYTE bOpEq ) /* pop the unneeded value from the stack */ HB_EXPR_GENPCODE1( hb_compGenPCode1, HB_P_POP ); + + return; } - else + /* TODO: add a special code for arrays to correctly handle a[ i++ ]++ + */ + else if( ( bOpEq == HB_P_PLUS || bOpEq == HB_P_MINUS || + bOpEq == HB_P_MULT || bOpEq == HB_P_DIVIDE ) && + ( pSelf->value.asOperator.pLeft->ExprType == HB_ET_VARIABLE ) ) { - /* push old value */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); - /* push increment value */ - HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - /* add */ - HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); - /* pop the new value into variable and remove it from the stack */ - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); + /* NOTE: direct type change */ + pSelf->value.asOperator.pLeft->ExprType = HB_ET_VARREF; + + if( pSelf->value.asOperator.pRight->ExprType == HB_ET_NUMERIC || + pSelf->value.asOperator.pRight->ExprType == HB_ET_STRING ) + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + switch( bOpEq ) + { + case HB_P_PLUS: + bOpEq = HB_P_PLUSEQPOP; + break; + case HB_P_MINUS: + bOpEq = HB_P_MINUSEQPOP; + break; + case HB_P_MULT: + bOpEq = HB_P_MULTEQPOP; + break; + case HB_P_DIVIDE: + bOpEq = HB_P_DIVEQPOP; + break; + } + HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); + return; + } + else if( pSelf->value.asOperator.pRight->ExprType == HB_ET_VARIABLE ) + { + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* NOTE: direct type change */ + pSelf->value.asOperator.pRight->ExprType = HB_ET_VARREF; + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + switch( bOpEq ) + { + case HB_P_PLUS: + bOpEq = HB_P_PLUSEQPOP; + break; + case HB_P_MINUS: + bOpEq = HB_P_MINUSEQPOP; + break; + case HB_P_MULT: + bOpEq = HB_P_MULTEQPOP; + break; + case HB_P_DIVIDE: + bOpEq = HB_P_DIVEQPOP; + break; + } + HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); + return; + } } + + /* push old value */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + /* push increment value */ + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + /* add */ + HB_EXPR_GENPCODE1( hb_compGenPCode1, bOpEq ); + /* pop the new value into variable and remove it from the stack */ + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); } /* Generates the pcodes for pre- increment/decrement expressions @@ -513,6 +630,8 @@ HB_EXPR_PTR hb_compExprReducePlusStrings( HB_EXPR_PTR pLeft, HB_EXPR_PTR pRight, memcpy( szString + pLeft->ulLength, pRight->value.asString.string, pRight->ulLength ); pLeft->ulLength += pRight->ulLength; szString[ pLeft->ulLength ] = '\0'; + if( pLeft->value.asString.dealloc ) + hb_xfree( pLeft->value.asString.string ); pLeft->value.asString.string = szString; pLeft->value.asString.dealloc = TRUE; hb_compExprFree( pRight, HB_MACRO_PARAM ); diff --git a/harbour/include/hbexprop.h b/harbour/include/hbexprop.h index f286f96a29..20e690ecd7 100644 --- a/harbour/include/hbexprop.h +++ b/harbour/include/hbexprop.h @@ -315,7 +315,6 @@ HB_EXPR_PTR hb_compExprNewString( char * ); HB_EXPR_PTR hb_compExprNewLogical( int ); HB_EXPR_PTR hb_compExprNewSelf( void ); HB_EXPR_PTR hb_compExprNewCodeBlock( char *, BOOL, BOOL ); -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 ); @@ -394,6 +393,7 @@ BOOL hb_compExprIsValidMacro( char *, BOOL *, HB_MACRO_DECL ); #ifdef HB_MACRO_SUPPORT +HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR, HB_MACRO_DECL ); 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 ); @@ -406,6 +406,7 @@ HB_EXPR_PTR hb_compExprSetGetBlock( HB_EXPR_PTR pExpr, HB_MACRO_DECL ); #else +HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR ); 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 ); diff --git a/harbour/include/hbpcode.h b/harbour/include/hbpcode.h index cc34e232ad..e70e715a2a 100644 --- a/harbour/include/hbpcode.h +++ b/harbour/include/hbpcode.h @@ -205,8 +205,17 @@ typedef enum HB_P_ENUMEND, /* 131 End of FOR EACH loop */ HB_P_SWITCH, /* 132 SWITCH using long values */ HB_P_PUSHDATE, /* 133 places a data constant value on the virtual machine stack */ +/* optimalization of inlined math operations */ + HB_P_PLUSEQPOP, /* 134 adds a value to the variable reference */ + HB_P_MINUSEQPOP, /* 135 subs a value from the variable reference */ + HB_P_MULTEQPOP, /* 136 multiplies a variable reference by a value */ + HB_P_DIVEQPOP, /* 137 divides the var reference by a value */ + HB_P_PLUSEQ, /* 138 adds a value to the variable reference, leave result on the stack */ + HB_P_MINUSEQ, /* 139 subs a value from the variable reference, leave result on the stack */ + HB_P_MULTEQ, /* 140 multiplies a variable reference by a value, leave result on the stack */ + HB_P_DIVEQ, /* 141 divides the var reference by a value, leave result on the stack */ /* NOTE: This have to be the last definition */ - HB_P_LAST_PCODE /* 134 this defines the number of defined pcodes */ + HB_P_LAST_PCODE /* 142 this defines the number of defined pcodes */ } HB_PCODE; #endif /* HB_PCODE_H_ */ diff --git a/harbour/source/common/expropt1.c b/harbour/source/common/expropt1.c index 88febc9f14..c077eef1e6 100644 --- a/harbour/source/common/expropt1.c +++ b/harbour/source/common/expropt1.c @@ -377,45 +377,6 @@ HB_EXPR_PTR hb_compExprNewRef( HB_EXPR_PTR pRefer ) return pExpr; } -/* Creates a new literal array { item1, item2, ... itemN } - * 'pArrList' is a list of array elements - */ -HB_EXPR_PTR hb_compExprNewArray( HB_EXPR_PTR pArrList ) -{ - HB_EXPR_PTR pExpr; - - HB_TRACE(HB_TR_DEBUG, ("hb_compExprNewArray()")); - - pArrList->ExprType = HB_ET_ARRAY; /* change type from ET_LIST */ - pArrList->ValType = HB_EV_ARRAY; - pArrList->ulLength = 0; - - pExpr = pArrList->value.asList.pExprList; /* get first element on the list */ - /* Now we need to replace all EO_NONE expressions with ET_NIL expressions - * If EO_NONE is the first expression and there is no more expressions - * then it is an empty array {} and ET_NIL cannot be used - */ - if( pExpr->ExprType == HB_ET_NONE && pExpr->pNext == NULL ) - { - pArrList->value.asList.pExprList = NULL; - } - else - { - /* there are at least one non-empty element specified - */ - while( pExpr ) - { - /* if empty element was specified replace it with NIL value */ - if( pExpr->ExprType == HB_ET_NONE ) - pExpr->ExprType = HB_ET_NIL; - pExpr = pExpr->pNext; - ++pArrList->ulLength; - } - } - pArrList->value.asList.pIndex = NULL; - return pArrList; -} - /* Creates new macro expression */ HB_EXPR_PTR hb_compExprNewMacro( HB_EXPR_PTR pMacroExpr, unsigned char cMacroOp, char * szName ) diff --git a/harbour/source/common/hbfsapi.c b/harbour/source/common/hbfsapi.c index 23e1371b11..86de6153d0 100644 --- a/harbour/source/common/hbfsapi.c +++ b/harbour/source/common/hbfsapi.c @@ -94,10 +94,10 @@ void hb_fsFreeSearchPath( HB_PATHNAMES * pSearchList ) /* Only the first path holds an allocated string. All of the other paths in the list are part of that first string. */ - hb_xfree( pSearchList->szPath ); while( pSearchList ) { + hb_xfree( pSearchList->szPath ); pNext = pSearchList->pNext; hb_xfree( pSearchList ); pSearchList = pNext; diff --git a/harbour/source/compiler/Makefile b/harbour/source/compiler/Makefile index 560c151918..6e70b653d5 100644 --- a/harbour/source/compiler/Makefile +++ b/harbour/source/compiler/Makefile @@ -60,6 +60,8 @@ C_SOURCES=\ C_MAIN=harbour.c LIBS=\ + ccmalloc \ + dl \ pp \ common \ diff --git a/harbour/source/compiler/expropta.c b/harbour/source/compiler/expropta.c index 332b5352dc..0835d0d346 100644 --- a/harbour/source/compiler/expropta.c +++ b/harbour/source/compiler/expropta.c @@ -5,6 +5,6 @@ /* hbexpra.c is also included from ../macro/macro.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.17 - ignore this magic number - this is used to force compilation + * 1.18 - ignore this magic number - this is used to force compilation */ #include "hbexpra.c" diff --git a/harbour/source/compiler/exproptb.c b/harbour/source/compiler/exproptb.c index a40b1f080f..2cc4b6a689 100644 --- a/harbour/source/compiler/exproptb.c +++ b/harbour/source/compiler/exproptb.c @@ -5,6 +5,6 @@ /* hbexprb.c is also included from ../macro/macro.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.15 - ignore this magic number - this is used to force compilation + * 1.16 - ignore this magic number - this is used to force compilation */ #include "hbexprb.c" diff --git a/harbour/source/compiler/exproptc.c b/harbour/source/compiler/exproptc.c index e50897e4bb..eb0193b0dd 100644 --- a/harbour/source/compiler/exproptc.c +++ b/harbour/source/compiler/exproptc.c @@ -5,6 +5,6 @@ /* hbexprc.c is also included from ../macro/macro.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.5 - ignore this magic number - this is used to force compilation + * 1.6 - ignore this magic number - this is used to force compilation */ #include "hbexprc.c" diff --git a/harbour/source/compiler/genc.c b/harbour/source/compiler/genc.c index 87027d29e4..f346c7f7c6 100644 --- a/harbour/source/compiler/genc.c +++ b/harbour/source/compiler/genc.c @@ -1925,6 +1925,79 @@ static HB_GENC_FUNC( hb_p_localnearaddint ) return 4; } +static HB_GENC_FUNC( hb_p_pluseqpop ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_PLUSEQPOP,\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_minuseqpop ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_MINUSEQPOP,\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_multeqpop ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_MULTEQPOP,\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_diveqpop ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_DIVEQPOP,\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_pluseq ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_PLUSEQ,\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_minuseq ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_MINUSEQ,\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_multeq ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_MULTEQ,\n" ); + return 1; +} + +static HB_GENC_FUNC( hb_p_diveq ) +{ + HB_SYMBOL_UNUSED( pFunc ); + HB_SYMBOL_UNUSED( lPCodePos ); + + fprintf( cargo->yyc, "\tHB_P_DIVEQ,\n" ); + return 1; +} + + /* NOTE: The order of functions have to match the order of opcodes * mnemonics */ @@ -2067,7 +2140,16 @@ static HB_GENC_FUNC_PTR s_verbose_table[] = { hb_p_enumprev, hb_p_enumend, hb_p_switch, - hb_p_pushdate + hb_p_pushdate, + /* optimalization of inlined math operations (+=, -= */ + hb_p_pluseqpop, + hb_p_minuseqpop, + hb_p_multeqpop, + hb_p_diveqpop, + hb_p_pluseq, + hb_p_minuseq, + hb_p_multeq, + hb_p_diveq }; static void hb_compGenCReadable( PFUNCTION pFunc, FILE * yyc ) diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index baf2d4e07e..e576c13da5 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -310,6 +310,8 @@ int main( int argc, char * argv[] ) hb_comp_pPpoPath = NULL; } + hb_compParserStop(); + if( hb_comp_iErrorCount > 0 ) iStatus = EXIT_FAILURE; @@ -816,7 +818,8 @@ void hb_compVariableAdd( char * szVarName, BYTE cValueType ) { PVAR pVar, pLastVar; PFUNCTION pFunc = hb_comp_functions.pLast; - + BOOL bFreeVar = TRUE; + HB_SYMBOL_UNUSED( cValueType ); if( ! hb_comp_bStartProc && hb_comp_functions.iCount <= 1 && hb_comp_iVarScope == VS_LOCAL ) @@ -902,6 +905,7 @@ void hb_compVariableAdd( char * szVarName, BYTE cValueType ) pLastVar = pLastVar->pNext; pLastVar->pNext = pVar; } + bFreeVar = FALSE; } switch( hb_comp_iVarScope ) @@ -919,7 +923,7 @@ void hb_compVariableAdd( char * szVarName, BYTE cValueType ) pSym = hb_compSymbolFind( szVarName, &wPos, HB_SYM_MEMVAR ); /* check if symbol exists already */ if( ! pSym ) - pSym = hb_compSymbolAdd( hb_strdup( szVarName ), &wPos, HB_SYM_MEMVAR ); + pSym = hb_compSymbolAdd( szVarName, &wPos, HB_SYM_MEMVAR ); pSym->cScope |= VS_MEMVAR; @@ -956,6 +960,10 @@ void hb_compVariableAdd( char * szVarName, BYTE cValueType ) /*printf( "\nAdded Private: %s Type %c\n", pVar->szName, pVar->cType );*/ } } + else if( bFreeVar ) + { + hb_xfree( pVar ); + } break; @@ -963,7 +971,7 @@ void hb_compVariableAdd( char * szVarName, BYTE cValueType ) { pSym = hb_compSymbolFind( szVarName, &wPos, HB_SYM_MEMVAR ); /* check if symbol exists already */ if( ! pSym ) - pSym = hb_compSymbolAdd( hb_strdup( szVarName ), &wPos, HB_SYM_MEMVAR ); + pSym = hb_compSymbolAdd( szVarName, &wPos, HB_SYM_MEMVAR ); pSym->cScope |= VS_MEMVAR; @@ -998,6 +1006,10 @@ void hb_compVariableAdd( char * szVarName, BYTE cValueType ) /*printf( "\nAdded Private: %s Type %c\n", pVar->szName, pVar->cType );*/ } } + else if( bFreeVar ) + { + hb_xfree( pVar ); + } break; @@ -1005,8 +1017,12 @@ void hb_compVariableAdd( char * szVarName, BYTE cValueType ) { pSym = hb_compSymbolFind( szVarName, &wPos, HB_SYM_MEMVAR ); /* check if symbol exists already */ if( ! pSym ) - pSym = hb_compSymbolAdd( hb_strdup( szVarName ), &wPos, HB_SYM_MEMVAR ); + pSym = hb_compSymbolAdd( szVarName, &wPos, HB_SYM_MEMVAR ); pSym->cScope |= VS_MEMVAR; + if( bFreeVar ) + { + hb_xfree( pVar ); + } } break; @@ -1891,7 +1907,8 @@ void hb_compFunctionAdd( char * szFunName, HB_SYMBOLSCOPE cScope, int iType ) strcpy( szNewName, szFunName ); szNewName[ iLen ] ='$'; szNewName[ iLen+1 ] = '\0'; - szFunName = szNewName; + szFunName = hb_compIdentifierNew( szNewName, TRUE ); + hb_xfree( szNewName ); } pFunc = hb_compFunctionFind( szFunName ); if( pFunc ) @@ -2121,7 +2138,7 @@ PCOMSYMBOL hb_compSymbolKill( PCOMSYMBOL pSym ) void hb_compGenBreak( void ) { - hb_compGenPushSymbol( hb_strdup("BREAK"), TRUE, FALSE ); + hb_compGenPushSymbol( "BREAK", TRUE, FALSE ); hb_compGenPushNil(); } @@ -3012,7 +3029,8 @@ void hb_compGenMessageData( char * szMsg ) /* generates an underscore-symbol nam strcpy( szResult, "_" ); strcat( szResult, szMsg ); - hb_compGenMessage( szResult ); + hb_compGenMessage( hb_compIdentifierNew( szResult, TRUE ) ); + hb_xfree( szResult ); } static void hb_compCheckEarlyMacroEval( char *szVarName ) @@ -3190,7 +3208,7 @@ void hb_compGenPopAliasedVar( char * szVarName, } else { /* database alias */ - hb_compGenPushSymbol( hb_strdup( szAlias ), FALSE, TRUE ); + hb_compGenPushSymbol( szAlias, FALSE, TRUE ); hb_compGenVarPCode( HB_P_POPALIASEDFIELD, szVarName ); } } @@ -3446,7 +3464,7 @@ void hb_compGenPushAliasedVar( char * szVarName, } else { /* database alias */ - hb_compGenPushSymbol( hb_strdup( szAlias ), FALSE, TRUE ); + hb_compGenPushSymbol( szAlias, FALSE, TRUE ); hb_compGenVarPCode( HB_P_PUSHALIASEDFIELD, szVarName ); } } @@ -4342,7 +4360,7 @@ void hb_compStaticDefStart( void ) { BYTE pBuffer[ 5 ]; - hb_comp_pInitFunc = hb_compFunctionNew( hb_strdup("(_INITSTATICS)"), HB_FS_INIT ); + hb_comp_pInitFunc = hb_compFunctionNew( hb_compIdentifierNew("(_INITSTATICS)", TRUE), HB_FS_INIT ); hb_comp_pInitFunc->pOwner = hb_comp_functions.pLast; hb_comp_pInitFunc->bFlags = FUN_USES_STATICS | FUN_PROCEDURE; hb_comp_pInitFunc->cScope = HB_FS_INIT | HB_FS_EXIT; @@ -4495,7 +4513,7 @@ void hb_compCodeBlockEnd( void ) hb_compGenPCodeN( pBuffer, 3 + strlen( hb_comp_files.pLast->szFileName ) + strlen( pFunc->szName ), 0 ); hb_xfree( pBuffer ); - /* generate the name of reference local variables */ + /* generate the name of referenced local variables */ pVar = pCodeblock->pStatics; iLocalPos = -1; while( wLocalsCnt-- ) @@ -4520,7 +4538,16 @@ void hb_compCodeBlockEnd( void ) } } - + else + { + pVar = pCodeblock->pStatics; + while( pVar ) + { + pFree = pVar; + pVar = pVar->pNext; + hb_xfree( ( void * ) pFree ); + } + } hb_compGenPCodeN( pCodeblock->pCode, pCodeblock->lPCodePos, ( BOOL ) 0 ); /* this fake-function is no longer needed */ @@ -4785,7 +4812,9 @@ int hb_compCompile( char * szPrg, int argc, char * argv[] ) /* Generate the starting procedure frame */ if( hb_comp_bStartProc ) - hb_compFunctionAdd( hb_strupr( hb_strdup( hb_comp_pFileName->szName ) ), HB_FS_PUBLIC, FUN_PROCEDURE ); + { + hb_compFunctionAdd( hb_compIdentifierNew( hb_comp_pFileName->szName, TRUE ), HB_FS_PUBLIC, FUN_PROCEDURE ); + } else { /* Don't pass the name of module if the code for starting procedure @@ -4798,13 +4827,25 @@ int hb_compCompile( char * szPrg, int argc, char * argv[] ) yyparse(); /* Close processed file (it is opened in hb_compInclude() function ) */ - fclose( yyin ); - hb_comp_files.pLast = NULL; +/* fclose( yyin ); */ + + while( hb_comp_files.pLast ) + { + PFILE pFile = hb_comp_files.pLast; + fclose( pFile->handle ); + if( pFile->pBuffer ) + hb_xfree( (void *) pFile->pBuffer ); + hb_comp_files.pLast = pFile->pPrev; + hb_xfree( pFile ); + } + hb_comp_files.pLast = NULL; if( hb_comp_bPPO && hb_comp_yyppo ) { fclose( hb_comp_yyppo ); hb_comp_yyppo = NULL; + if( hb_comp_pFilePpo ) + hb_xfree( hb_comp_pFilePpo ); } /* Saving main file. */ @@ -4920,6 +4961,7 @@ int hb_compCompile( char * szPrg, int argc, char * argv[] ) hb_compGenOutput( hb_comp_iLanguage ); } + hb_compParserStop(); } else { @@ -5105,5 +5147,7 @@ int hb_compAutoOpen( char * szPrg, BOOL * pbSkipGen ) iStatus = EXIT_FAILURE; } + hb_xfree( hb_comp_pFileName ); + return iStatus; } diff --git a/harbour/source/compiler/harbour.l b/harbour/source/compiler/harbour.l index da9ac3f1cd..ab13696f63 100644 --- a/harbour/source/compiler/harbour.l +++ b/harbour/source/compiler/harbour.l @@ -1,4 +1,4 @@ -%{ +%{ /* * $Id$ */ @@ -1718,17 +1718,22 @@ Separator {SpaceTab} /* ************************************************************************ */ %} -{InvalidNumber} BEGIN INVALIDNUM_; yylval.string = hb_strupr( hb_strdup( yytext ) ); +{InvalidNumber} BEGIN INVALIDNUM_; yylval.string = hb_strdup( yytext ); ("."|{Separator}+) { BEGIN 0; + hb_xfree( yylval.string ); hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_NUMERIC_FORMAT, NULL, NULL ); } . { + int iRet; + char *pTmp = yylval.string; BEGIN 0; unput( yytext[ yyleng-1 ] ); unput( '.' ); yylval.string[ strlen(yylval.string) - 1 ] = '\0'; - return yy_ConvertNumber( yylval.string ); + iRet = yy_ConvertNumber( yylval.string ); + hb_xfree( pTmp ); + return iRet; } @@ -1748,19 +1753,21 @@ Separator {SpaceTab} } {MacroEnd} { - yylval.string = hb_strupr( hb_strdup( yytext ) ); +/* yylval.string = hb_strupr( hb_strdup( yytext ) );*/ + yylval.string = yytext; hb_comp_iState = MACROTEXT; return MACROTEXT; } {MacroId} { - yylval.string = hb_strupr( hb_strdup( yytext ) ); +/* yylval.string = hb_strupr( hb_strdup( yytext ) );*/ + yylval.string = yytext; hb_comp_iState = MACROTEXT; return MACROTEXT; } {MacroTxt} { - yylval.string = hb_strupr( hb_strdup( yytext ) ); +/* yylval.string = hb_strupr( hb_strdup( yytext ) );*/ hb_comp_iState = MACROTEXT; return MACROTEXT; } @@ -1831,3 +1838,4 @@ static int yy_ConvertDate( char * szBuffer ) return NUM_DATE; } + diff --git a/harbour/source/compiler/harbour.y b/harbour/source/compiler/harbour.y index b0a57b26fa..6fa52ec236 100644 --- a/harbour/source/compiler/harbour.y +++ b/harbour/source/compiler/harbour.y @@ -432,7 +432,7 @@ Statement : ExecFlow { hb_comp_bDontGenLineNum = TRUE; } CrlfStmnt { } { hb_compGenError( hb_comp_szErrors, 'E', HB_COMP_ERR_EXIT_IN_SEQUENCE, "RETURN", NULL ); } - hb_compExprGenPush( $3 ); /* TODO: check if return value agree with declared value */ + hb_compExprDelete( hb_compExprGenPush( $3 ) ); /* TODO: check if return value agree with declared value */ hb_compGenPCode2( HB_P_RETVALUE, HB_P_ENDPROC, ( BOOL ) 1 ); if( hb_comp_functions.pLast->bFlags & FUN_PROCEDURE ) { /* procedure returns a value */ @@ -444,10 +444,10 @@ Statement : ExecFlow { hb_comp_bDontGenLineNum = TRUE; } CrlfStmnt { } } | PUBLIC { hb_compLinePushIfInside(); hb_comp_iVarScope = VS_PUBLIC; } ExtVarList - { hb_compRTVariableGen( "__MVPUBLIC" ); hb_comp_cVarType = ' '; hb_comp_iVarScope = VS_NONE; } Crlf + { hb_compRTVariableGen( hb_compIdentifierNew("__MVPUBLIC",TRUE) ); hb_comp_cVarType = ' '; hb_comp_iVarScope = VS_NONE; } Crlf | PRIVATE { hb_compLinePushIfInside(); hb_comp_iVarScope = VS_PRIVATE; } ExtVarList - { hb_compRTVariableGen( "__MVPRIVATE" ); hb_comp_cVarType = ' '; hb_comp_iVarScope = VS_NONE; } Crlf + { hb_compRTVariableGen( hb_compIdentifierNew("__MVPRIVATE",TRUE) ); hb_comp_cVarType = ' '; hb_comp_iVarScope = VS_NONE; } Crlf | EXIT { hb_comp_bDontGenLineNum = !hb_comp_bDebugInfo; } CrlfStmnt { hb_compLoopExit(); hb_comp_functions.pLast->bFlags |= FUN_BREAK_CODE; } | LOOP { hb_comp_bDontGenLineNum = !hb_comp_bDebugInfo; } CrlfStmnt { hb_compLoopLoop(); hb_comp_functions.pLast->bFlags |= FUN_BREAK_CODE; } @@ -1385,10 +1385,10 @@ DummyArgument : EmptyExpression {} FormalList : IdentName AsType { hb_compDeclaredParameterAdd( $1, hb_comp_cVarType ); } | '@' IdentName AsType { hb_compDeclaredParameterAdd( $2, hb_comp_cVarType + VT_OFFSET_BYREF ); } - | '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( $2, 'F' ); } + | '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( $2, 'F' ); hb_compExprDelete( $4 );} | FormalList ',' IdentName AsType { hb_compDeclaredParameterAdd( $3, hb_comp_cVarType ); } | FormalList ',' '@' IdentName AsType { hb_compDeclaredParameterAdd( $4, hb_comp_cVarType + VT_OFFSET_BYREF ); } - | FormalList ',' '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( $4, 'F' ); } + | FormalList ',' '@' IdentName '(' DummyArgList ')' { hb_compDeclaredParameterAdd( $4, 'F' ); hb_compExprDelete( $6 ); } ; OptList : OPTIONAL IdentName AsType { hb_compDeclaredParameterAdd( $2, hb_comp_cVarType + VT_OFFSET_OPTIONAL ); } @@ -2021,6 +2021,19 @@ int yywrap( void ) /* handles the EOF of the currently processed file */ return 0; } +void hb_compParserStop( void ) +{ + if( hb_comp_buffer ) + { +#ifdef __cplusplus + yy_delete_buffer( (YY_BUFFER_STATE) hb_comp_buffer ); +#else + yy_delete_buffer( (void *) hb_comp_buffer ); +#endif + hb_comp_buffer = NULL; + } +} + /* ************************************************************************* */ /* @@ -2211,11 +2224,14 @@ static void * hb_compElseIfGen( void * pFirst, ULONG ulOffset ) static void hb_compElseIfFix( void * pFixElseIfs ) { PELSEIF pFix = ( PELSEIF ) pFixElseIfs; - + PELSEIF pDel; + while( pFix ) { hb_compGenJumpHere( pFix->ulOffset ); + pDel = pFix; pFix = pFix->pNext; + hb_xfree( pDel ); } } @@ -2247,7 +2263,7 @@ static void hb_compRTVariableGen( char * szCreateFun ) HB_RTVAR_PTR pDel; /* generate the function call frame */ - hb_compGenPushSymbol( hb_strdup( szCreateFun ), TRUE, FALSE ); + hb_compGenPushSymbol( szCreateFun, TRUE, FALSE ); hb_compGenPushNil(); /* push variable names to create */ diff --git a/harbour/source/compiler/hbdead.c b/harbour/source/compiler/hbdead.c index 08119e72ee..deb5c9b8c8 100644 --- a/harbour/source/compiler/hbdead.c +++ b/harbour/source/compiler/hbdead.c @@ -488,7 +488,16 @@ static PHB_CODETRACE_FUNC s_codeTraceFuncTable[ HB_P_LAST_PCODE ] = hb_p_default, /* HB_P_ENUMPREV */ hb_p_default, /* HB_P_ENUMEND */ hb_p_switch, /* HB_P_SWITCH */ - hb_p_default /* HB_P_PUSHDATE */ + hb_p_default, /* HB_P_PUSHDATE */ + /* optimalization of inlined math operations */ + hb_p_default, /* HB_P_PLUSEQPOP */ + hb_p_default, /* HB_P_MINUSEQPOP */ + hb_p_default, /* HB_P_MULTEQPOP */ + hb_p_default, /* HB_P_DIVEQPOP */ + hb_p_default, /* HB_P_PLUSEQ */ + hb_p_default, /* HB_P_MINUSEQ */ + hb_p_default, /* HB_P_MULTEQ */ + hb_p_default, /* HB_P_DIVEQ */ }; void hb_compCodeTraceMarkDead( PFUNCTION pFunc ) diff --git a/harbour/source/compiler/hbfix.c b/harbour/source/compiler/hbfix.c index ff789bc254..8f7371a16e 100644 --- a/harbour/source/compiler/hbfix.c +++ b/harbour/source/compiler/hbfix.c @@ -539,7 +539,15 @@ static HB_FIX_FUNC_PTR s_fixlocals_table[] = NULL, /* HB_P_ENUMPREV */ NULL, /* HB_P_ENUMEND */ NULL, /* HB_P_SWITCH */ - NULL /* HB_P_PUSHDATE */ + NULL, /* HB_P_PUSHDATE */ + NULL, /* HB_P_PLUSEQPOP */ + NULL, /* HB_P_MINUSEQPOP */ + NULL, /* HB_P_MULTEQPOP */ + NULL, /* HB_P_DIVEQPOP */ + NULL, /* HB_P_PLUSEQ */ + NULL, /* HB_P_MINUSEQ */ + NULL, /* HB_P_MULTEQ */ + NULL /* HB_P_DIVEQ */ }; void hb_compFixFuncPCode( PFUNCTION pFunc ) diff --git a/harbour/source/compiler/hbpcode.c b/harbour/source/compiler/hbpcode.c index dbb3ca6714..532380fba8 100644 --- a/harbour/source/compiler/hbpcode.c +++ b/harbour/source/compiler/hbpcode.c @@ -178,7 +178,16 @@ const BYTE hb_comp_pcode_len[] = { 1, /* HB_P_ENUMPREV */ 1, /* HB_P_ENUMEND */ 3, /* HB_P_SWITCH */ - 5 /* HB_P_PUSHDATE, */ + 5, /* HB_P_PUSHDATE, */ + /* optimalization of inlined math operations */ + 1, /* HB_P_PLUSEQPOP, */ + 1, /* HB_P_MINUSEQPOP, */ + 1, /* HB_P_MULTEQPOP, */ + 1, /* HB_P_DIVEQPOP, */ + 1, /* HB_P_PLUSEQ, */ + 1, /* HB_P_MINUSEQ, */ + 1, /* HB_P_MULTEQ, */ + 1 /* HB_P_DIVEQ, */ }; void hb_compPCodeEval( PFUNCTION pFunc, HB_PCODE_FUNC_PTR * pFunctions, void * cargo ) diff --git a/harbour/source/compiler/hbstripl.c b/harbour/source/compiler/hbstripl.c index 39822452fc..95c94da6b6 100644 --- a/harbour/source/compiler/hbstripl.c +++ b/harbour/source/compiler/hbstripl.c @@ -269,7 +269,16 @@ static PHB_STRIP_FUNC s_stripLines_table[] = NULL, /* HB_P_ENUMPREV */ NULL, /* HB_P_ENUMEND */ NULL, /* HB_P_SWITCH */ - NULL /* HB_P_PUSHDATE */ + NULL, /* HB_P_PUSHDATE */ + /* optimalization of inlined math operations */ + NULL, /* HB_P_PLUSEQPOP */ + NULL, /* HB_P_MINUSEQPOP */ + NULL, /* HB_P_MULTEQPOP */ + NULL, /* HB_P_DIVEQPOP */ + NULL, /* HB_P_PLUSEQ */ + NULL, /* HB_P_MINUSEQ */ + NULL, /* HB_P_MULTEQ */ + NULL /* HB_P_DIVEQ */ }; void hb_compStripFuncLines( PFUNCTION pFunc ) diff --git a/harbour/source/macro/macro.y b/harbour/source/macro/macro.y index 818b7648d7..7a367a8418 100644 --- a/harbour/source/macro/macro.y +++ b/harbour/source/macro/macro.y @@ -299,7 +299,7 @@ SelfValue : SELF { $$ = hb_compExprNewSelf(); } /* Literal array */ -Array : '{' ElemList '}' { $$ = hb_compExprNewArray( $2 ); } +Array : '{' ElemList '}' { $$ = hb_compExprNewArray( $2, HB_MACRO_PARAM ); } ; /* Literal array access diff --git a/harbour/source/macro/macroa.c b/harbour/source/macro/macroa.c index 752ee8f69e..3fb658e9fe 100644 --- a/harbour/source/macro/macroa.c +++ b/harbour/source/macro/macroa.c @@ -5,7 +5,7 @@ /* hbexpra.c is also included from ../compiler/expropta.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.17 - ignore this magic number - this is used to force compilation + * 1.18 - ignore this magic number - this is used to force compilation */ #define HB_MACRO_SUPPORT diff --git a/harbour/source/macro/macrob.c b/harbour/source/macro/macrob.c index b0d405692e..49e250028c 100644 --- a/harbour/source/macro/macrob.c +++ b/harbour/source/macro/macrob.c @@ -5,7 +5,7 @@ /* hbexprb.c is also included from ../compiler/exproptb.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.14 - ignore this magic number - this is used to force compilation + * 1.15 - ignore this magic number - this is used to force compilation */ #define HB_MACRO_SUPPORT diff --git a/harbour/source/macro/macroc.c b/harbour/source/macro/macroc.c index 81a8872b18..6bafba2b8e 100644 --- a/harbour/source/macro/macroc.c +++ b/harbour/source/macro/macroc.c @@ -5,7 +5,7 @@ /* hbexprc.c is also included from ../compiler/exproptc.c * However it produces a slighty different code if used in * macro compiler (there is an additional parameter passed to some functions) - * 1.4 - ignore this magic number - this is used to force compilation + * 1.5 - ignore this magic number - this is used to force compilation */ #define HB_MACRO_SUPPORT diff --git a/harbour/source/pp/ppcore.c b/harbour/source/pp/ppcore.c index 9bc5402181..fc1a16f312 100644 --- a/harbour/source/pp/ppcore.c +++ b/harbour/source/pp/ppcore.c @@ -376,7 +376,6 @@ void hb_pp_Free( void ) hb_xfree( (void *)hb_pp_aCondCompile ); hb_pp_aCondCompile = NULL; } - } void hb_pp_Init( void ) diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 559d63a12b..51aa196a9c 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -108,15 +108,15 @@ HB_FUNC_EXTERN( SYSINIT ); /* Operators (mathematical / character / misc) */ static void hb_vmNegate( void ); /* negates (-) the latest value on the stack */ -static void hb_vmPlus( void ); /* sums the latest two values on the stack, removes them and leaves the result */ -static void hb_vmMinus( void ); /* substracts the latest two values on the stack, removes them and leaves the result */ -static void hb_vmMult( void ); /* multiplies the latest two values on the stack, removes them and leaves the result */ -static void hb_vmDivide( void ); /* divides the latest two values on the stack, removes them and leaves the result */ static void hb_vmModulus( void ); /* calculates the modulus of latest two values on the stack, removes them and leaves the result */ static void hb_vmPower( void ); /* power the latest two values on the stack, removes them and leaves the result */ static void hb_vmInc( void ); /* increment the latest numeric value on the stack */ static void hb_vmDec( void ); /* decrements the latest numeric value on the stack */ static void hb_vmFuncPtr( void ); /* pushes a function address pointer. Removes the symbol from the satck */ +static void hb_vmPlus( HB_ITEM_PTR pResult, HB_ITEM_PTR pItem1, HB_ITEM_PTR pItem2, int iPopCnt ); /* sums the latest two values on the stack, removes them and leaves the result */ +static void hb_vmMinus( HB_ITEM_PTR pResult, HB_ITEM_PTR pItem1, HB_ITEM_PTR pItem2, int iPopCnt ); /* substracts the latest two values on the stack, removes them and leaves the result */ +static void hb_vmMult( HB_ITEM_PTR pResult, HB_ITEM_PTR pItem1, HB_ITEM_PTR pItem2, int iPopCnt ); /* multiplies the latest two values on the stack, removes them and leaves the result */ +static void hb_vmDivide( HB_ITEM_PTR pResult, HB_ITEM_PTR pItem1, HB_ITEM_PTR pItem2, int iPopCnt ); /* divides the latest two values on the stack, removes them and leaves the result */ /* Operators (relational) */ static void hb_vmEqual( BOOL bExact ); /* checks if the two latest values on the stack are equal, removes both and leaves result */ @@ -146,7 +146,7 @@ static void hb_vmArrayGen( ULONG ulElements ); /* generates an ulElements Arr static void hb_vmArrayNew( HB_ITEM_PTR, USHORT ); /* creates array */ /* Object */ -static void hb_vmOperatorCall( PHB_ITEM, PHB_ITEM, char * ); /* call an overloaded operator */ +static void hb_vmOperatorCall( HB_ITEM_PTR, PHB_ITEM, PHB_ITEM, char * ); /* call an overloaded operator */ static void hb_vmOperatorCallUnary( PHB_ITEM, char * ); /* call an overloaded unary operator */ /* Database */ @@ -660,24 +660,119 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) break; case HB_P_PLUS: - hb_vmPlus(); + hb_vmPlus( hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -1 ), 1 ); w++; break; + case HB_P_PLUSEQ: + { + HB_ITEM_PTR pResult; + pResult = hb_itemUnRef( hb_stackItemFromTop( -2 ) ); + hb_vmPlus( pResult, pResult, hb_itemUnRef( hb_stackItemFromTop( -1 ) ), 2 ); + hb_itemCopy( hb_stackTopItem(), pResult ); + hb_stackPush(); + } + w++; + break; + + case HB_P_PLUSEQPOP: + { + HB_ITEM_PTR pResult; + pResult = hb_itemUnRef( hb_stackItemFromTop( -2 ) ); + hb_vmPlus( pResult, pResult, hb_itemUnRef( hb_stackItemFromTop( -1 ) ), 2 ); + } + w++; + break; +/* case HB_P_MINUS: hb_vmMinus(); w++; break; +*/ + case HB_P_MINUS: + hb_vmMinus( hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -1 ), 1 ); + w++; + break; + case HB_P_MINUSEQ: + { + HB_ITEM_PTR pResult; + pResult = hb_itemUnRef( hb_stackItemFromTop( -2 ) ); + hb_vmMinus( pResult, pResult, hb_itemUnRef( hb_stackItemFromTop( -1 ) ), 2 ); + hb_itemCopy( hb_stackTopItem(), pResult ); + hb_stackPush(); + } + w++; + break; + + case HB_P_MINUSEQPOP: + { + HB_ITEM_PTR pResult; + pResult = hb_itemUnRef( hb_stackItemFromTop( -2 ) ); + hb_vmMinus( pResult, pResult, hb_itemUnRef( hb_stackItemFromTop( -1 ) ), 2 ); + } + w++; + break; +/* case HB_P_MULT: hb_vmMult(); w++; break; +*/ + case HB_P_MULT: + hb_vmMult( hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -1 ), 1 ); + w++; + break; + case HB_P_MULTEQ: + { + HB_ITEM_PTR pResult; + pResult = hb_itemUnRef( hb_stackItemFromTop( -2 ) ); + hb_vmMult( pResult, pResult, hb_itemUnRef( hb_stackItemFromTop( -1 ) ), 2 ); + hb_itemCopy( hb_stackTopItem(), pResult ); + hb_stackPush(); + } + w++; + break; + + case HB_P_MULTEQPOP: + { + HB_ITEM_PTR pResult; + pResult = hb_itemUnRef( hb_stackItemFromTop( -2 ) ); + hb_vmMult( pResult, pResult, hb_itemUnRef( hb_stackItemFromTop( -1 ) ), 2 ); + } + w++; + break; +/* case HB_P_DIVIDE: hb_vmDivide(); w++; break; +*/ + case HB_P_DIVIDE: + hb_vmDivide( hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -2 ), hb_stackItemFromTop( -1 ), 1 ); + w++; + break; + + case HB_P_DIVEQ: + { + HB_ITEM_PTR pResult; + pResult = hb_itemUnRef( hb_stackItemFromTop( -2 ) ); + hb_vmDivide( pResult, pResult, hb_itemUnRef( hb_stackItemFromTop( -1 ) ), 2 ); + hb_itemCopy( hb_stackTopItem(), pResult ); + hb_stackPush(); + } + w++; + break; + + case HB_P_DIVEQPOP: + { + HB_ITEM_PTR pResult; + pResult = hb_itemUnRef( hb_stackItemFromTop( -2 ) ); + hb_vmDivide( pResult, pResult, hb_itemUnRef( hb_stackItemFromTop( -1 ) ), 2 ); + } + w++; + break; case HB_P_MODULUS: hb_vmModulus(); @@ -1998,15 +2093,9 @@ static void hb_vmNegate( void ) } } -static void hb_vmPlus( void ) +static void hb_vmPlus( HB_ITEM_PTR pResult, HB_ITEM_PTR pItem1, HB_ITEM_PTR pItem2, int iPopCnt ) { - PHB_ITEM pItem1; - PHB_ITEM pItem2; - - HB_TRACE(HB_TR_DEBUG, ("hb_vmPlus()")); - - pItem1 = hb_stackItemFromTop( -2 ); - pItem2 = hb_stackItemFromTop( -1 ); + HB_TRACE(HB_TR_DEBUG, ("hb_vmPlus(%p,%p,%p,%i)", pResult, pItem1, pItem2, iPopCnt)); if( HB_IS_NUMINT( pItem1 ) && HB_IS_NUMINT( pItem2 ) ) { @@ -2014,26 +2103,30 @@ static void hb_vmPlus( void ) HB_LONG lNumber2 = HB_ITEM_GET_NUMINTRAW( pItem2 ); HB_LONG lResult = lNumber1 + lNumber2; - hb_stackDec(); - pItem2->type = HB_IT_NIL; - if ( lNumber2 >= 0 ? lResult >= lNumber1 : lResult < lNumber1 ) { - HB_ITEM_PUT_NUMINTRAW( pItem1, lResult ); + hb_itemPutNInt( pResult, lResult ); } else + { + hb_itemPutNDDec( pResult, ( double ) lNumber1 + ( double ) lNumber2, 0 ); + } + while( iPopCnt-- > 0 ) { hb_stackDec(); - hb_vmPushDouble( ( double ) lNumber1 + ( double ) lNumber2, 0 ); } } else if( HB_IS_NUMERIC( pItem1 ) && HB_IS_NUMERIC( pItem2 ) ) { int iDec2, iDec1, iType2 = pItem2->type, iType1 = pItem2->type; - double dNumber2 = hb_vmPopDouble( &iDec2 ); - double dNumber1 = hb_vmPopDouble( &iDec1 ); + double dNumber1 = hb_itemGetNDDec( pItem1, &iDec1 ); + double dNumber2 = hb_itemGetNDDec( pItem2, &iDec2 ); - hb_vmPushNumType( dNumber1 + dNumber2, ( ( iDec1 > iDec2 ) ? iDec1 : iDec2 ), iType1, iType2 ); + hb_itemPutNumType( pResult, dNumber1 + dNumber2, ( ( iDec1 > iDec2 ) ? iDec1 : iDec2 ), iType1, iType2 ); + while( iPopCnt-- > 0 ) + { + hb_stackDec(); + } } else if( HB_IS_STRING( pItem1 ) && HB_IS_STRING( pItem2 ) ) { @@ -2046,52 +2139,60 @@ static void hb_vmPlus( void ) hb_xmemcpy( szNewString, pItem1->item.asString.value, ulLen1 ); hb_xmemcpy( szNewString + ulLen1, pItem2->item.asString.value, ulLen2 ); - hb_itemPutCPtr( pItem1, szNewString, ulLen1 + ulLen2 ); - hb_stackPop(); + hb_itemPutCPtr( pResult, szNewString, ulLen1 + ulLen2 ); + while( iPopCnt-- > 0 ) + { + hb_stackPop(); + } } else hb_errRT_BASE( EG_STROVERFLOW, 1209, NULL, "+", 2, pItem1, pItem2 ); } else if( HB_IS_DATE( pItem1 ) && HB_IS_DATE( pItem2 ) ) { - long lDate2 = hb_vmPopDate(); - long lDate1 = hb_vmPopDate(); - /* NOTE: This is not a bug. CA-Cl*pper does exactly that. */ - hb_vmPushDate( lDate1 + lDate2 ); + hb_itemPutDL( pResult, ( long ) hb_itemGetND( pItem1 ) + ( long ) hb_itemGetND( pItem2 ) ); + while( iPopCnt-- > 0 ) + { + hb_stackDec(); + } } else if( HB_IS_DATE( pItem1 ) && HB_IS_NUMERIC( pItem2 ) ) { - long lNumber2 = ( long ) hb_vmPopNumber(); - long lDate1 = hb_vmPopDate(); - - hb_vmPushDate( lDate1 + lNumber2 ); + hb_itemPutND( pResult, ( long ) hb_itemGetND( pItem1 ) + ( long ) hb_itemGetND( pItem1 ) ); + while( iPopCnt-- > 0 ) + { + hb_stackDec(); + } } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpPlus" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPPLUS" ); - else { - PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1081, NULL, "+", 2, pItem1, pItem2 ); - - if( pResult ) + hb_vmOperatorCall( pResult, pItem1, pItem2, "__OPPLUS" ); + --iPopCnt; /* hb_vmOperatorCall pops pItem2 */ + while( iPopCnt-- > 0 ) { hb_stackPop(); + } + } + else + { + PHB_ITEM pSubst = hb_errRT_BASE_Subst( EG_ARG, 1081, NULL, "+", 2, pItem1, pItem2 ); + + if( pSubst ) + { + hb_itemForwardValue( pResult, pSubst ); + hb_itemRelease( pSubst ); + } + while( iPopCnt-- > 0 ) + { hb_stackPop(); - hb_vmPush( pResult ); - hb_itemRelease( pResult ); } } } -static void hb_vmMinus( void ) +static void hb_vmMinus( HB_ITEM_PTR pResult, HB_ITEM_PTR pItem1, HB_ITEM_PTR pItem2, int iPopCnt ) { - PHB_ITEM pItem1; - PHB_ITEM pItem2; - - HB_TRACE(HB_TR_DEBUG, ("hb_vmMinus()")); - - pItem1 = hb_stackItemFromTop( -2 ); - pItem2 = hb_stackItemFromTop( -1 ); + HB_TRACE(HB_TR_DEBUG, ("hb_vmMinus(%p,%p,%p,%i)", pResult, pItem1, pItem2, iPopCnt)); if( HB_IS_NUMINT( pItem1 ) && HB_IS_NUMINT( pItem2 ) ) { @@ -2099,40 +2200,46 @@ static void hb_vmMinus( void ) HB_LONG lNumber2 = HB_ITEM_GET_NUMINTRAW( pItem2 ); HB_LONG lResult = lNumber1 - lNumber2; - hb_stackDec(); - pItem2->type = HB_IT_NIL; - - if ( lNumber2 <= 0 ? lResult >= lNumber1 : lResult < lNumber1 ) + if ( lNumber2 >= 0 ? lResult >= lNumber1 : lResult < lNumber1 ) { - HB_ITEM_PUT_NUMINTRAW( pItem1, lResult ); + hb_itemPutNInt( pResult, lResult ); } else + { + hb_itemPutNDDec( pResult, ( double ) lNumber1 - ( double ) lNumber2, 0 ); + } + while( iPopCnt-- > 0 ) { hb_stackDec(); - hb_vmPushDouble( ( double ) lNumber1 - ( double ) lNumber2, 0 ); } } else if( HB_IS_NUMERIC( pItem1 ) && HB_IS_NUMERIC( pItem2 ) ) { - int iDec2, iDec1, iType2 = pItem2->type, iType1 = pItem1->type; - double dNumber2 = hb_vmPopDouble( &iDec2 ); - double dNumber1 = hb_vmPopDouble( &iDec1 ); + int iDec2, iDec1, iType2 = pItem2->type, iType1 = pItem2->type; + double dNumber1 = hb_itemGetNDDec( pItem1, &iDec1 ); + double dNumber2 = hb_itemGetNDDec( pItem2, &iDec2 ); - hb_vmPushNumType( dNumber1 - dNumber2, ( ( iDec1 > iDec2 ) ? iDec1 : iDec2 ), iType1, iType2 ); + hb_itemPutNumType( pResult, dNumber1 - dNumber2, ( ( iDec1 > iDec2 ) ? iDec1 : iDec2 ), iType1, iType2 ); + while( iPopCnt-- > 0 ) + { + hb_stackDec(); + } } else if( HB_IS_DATE( pItem1 ) && HB_IS_DATE( pItem2 ) ) { - long lDate2 = hb_vmPopDate(); - long lDate1 = hb_vmPopDate(); - - hb_vmPushNumInt( lDate1 - lDate2 ); + hb_itemPutNInt( pResult, ( long ) hb_itemGetND( pItem1 ) - ( long ) hb_itemGetND( pItem2 ) ); + while( iPopCnt-- > 0 ) + { + hb_stackDec(); + } } else if( HB_IS_DATE( pItem1 ) && HB_IS_NUMERIC( pItem2 ) ) { - long lNumber2 = ( long ) hb_vmPopNumber(); - long lDate1 = hb_vmPopDate(); - - hb_vmPushDate( lDate1 - lNumber2 ); + hb_itemPutND( pResult, ( long ) hb_itemGetND( pItem1 ) - ( long ) hb_itemGetND( pItem1 ) ); + while( iPopCnt-- > 0 ) + { + hb_stackDec(); + } } else if( HB_IS_STRING( pItem1 ) && HB_IS_STRING( pItem2 ) ) { @@ -2150,37 +2257,43 @@ static void hb_vmMinus( void ) hb_xmemcpy( szNewString, pItem1->item.asString.value, ulLen1 ); hb_xmemcpy( szNewString + ulLen1, pItem2->item.asString.value, ulLen2 ); hb_xmemset( szNewString + ulLen1 + ulLen2, ' ', pItem1->item.asString.length - ulLen1 ); - hb_itemPutCPtr( pItem1, szNewString, ulNewLen ); - hb_stackPop(); + hb_itemPutCPtr( pResult, szNewString, ulNewLen ); + while( iPopCnt-- > 0 ) + { + hb_stackPop(); + } } else hb_errRT_BASE( EG_STROVERFLOW, 1210, NULL, "-", 2, pItem1, pItem2 ); } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpMinus" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPMINUS" ); - else { - PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1082, NULL, "-", 2, pItem1, pItem2 ); - - if( pResult ) + hb_vmOperatorCall( pResult, pItem1, pItem2, "__OPMINUS" ); + --iPopCnt; /* hb_vmOperatorCall pops pItem2 */ + while( iPopCnt-- > 0 ) { hb_stackPop(); + } + } + else + { + PHB_ITEM pSubst = hb_errRT_BASE_Subst( EG_ARG, 1082, NULL, "-", 2, pItem1, pItem2 ); + + if( pSubst ) + { + hb_itemForwardValue( pResult, pSubst ); + hb_itemRelease( pSubst ); + } + while( iPopCnt-- > 0 ) + { hb_stackPop(); - hb_vmPush( pResult ); - hb_itemRelease( pResult ); } } } -static void hb_vmMult( void ) +static void hb_vmMult( HB_ITEM_PTR pResult, HB_ITEM_PTR pItem1, HB_ITEM_PTR pItem2, int iPopCnt ) { - PHB_ITEM pItem1; - PHB_ITEM pItem2; - - HB_TRACE(HB_TR_DEBUG, ("hb_vmMult()")); - - pItem1 = hb_stackItemFromTop( -2 ); - pItem2 = hb_stackItemFromTop( -1 ); + HB_TRACE(HB_TR_DEBUG, ("hb_vmMinus(%p,%p,%p,%i)", pResult, pItem1, pItem2, iPopCnt)); /* if( HB_IS_NUMINT( pItem1 ) && HB_IS_NUMINT( pItem2 ) ) { @@ -2194,38 +2307,45 @@ static void hb_vmMult( void ) } else */ if( HB_IS_NUMERIC( pItem1 ) && HB_IS_NUMERIC( pItem2 ) ) { - int iDec2, iDec1, iType2 = pItem2->type, iType1 = pItem1->type; - double d2 = hb_vmPopDouble( &iDec2 ); - double d1 = hb_vmPopDouble( &iDec1 ); + int iDec2, iDec1, iType2 = pItem2->type, iType1 = pItem2->type; + double dNumber1 = hb_itemGetNDDec( pItem1, &iDec1 ); + double dNumber2 = hb_itemGetNDDec( pItem2, &iDec2 ); - hb_vmPushNumType( d1 * d2, iDec1 + iDec2, iType1, iType2 ); + hb_itemPutNumType( pResult, dNumber1 * dNumber2, iDec1 + iDec2, iType1, iType2 ); + while( iPopCnt-- > 0 ) + { + hb_stackDec(); + } } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpMult" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPMULT" ); - else { - PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1083, NULL, "*", 2, pItem1, pItem2 ); - - if( pResult ) + hb_vmOperatorCall( pResult, pItem1, pItem2, "__OPMULT" ); + --iPopCnt; /* hb_vmOperatorCall pops pItem2 */ + while( iPopCnt-- > 0 ) { hb_stackPop(); + } + } + else + { + PHB_ITEM pSubst = hb_errRT_BASE_Subst( EG_ARG, 1083, NULL, "*", 2, pItem1, pItem2 ); + + if( pSubst ) + { + hb_itemForwardValue( pResult, pSubst ); + hb_itemRelease( pSubst ); + } + while( iPopCnt-- > 0 ) + { hb_stackPop(); - hb_vmPush( pResult ); - hb_itemRelease( pResult ); } } } -static void hb_vmDivide( void ) +static void hb_vmDivide( HB_ITEM_PTR pResult, HB_ITEM_PTR pItem1, HB_ITEM_PTR pItem2, int iPopCnt ) { - PHB_ITEM pItem1; - PHB_ITEM pItem2; - - HB_TRACE(HB_TR_DEBUG, ("hb_vmDivide()")); - - pItem1 = hb_stackItemFromTop( -2 ); - pItem2 = hb_stackItemFromTop( -1 ); + HB_TRACE(HB_TR_DEBUG, ("hb_vmDivide(%p,%p,%p,%i)", pResult, pItem1, pItem2, iPopCnt)); /* * This code is commented out for Clipper compatibility. @@ -2237,29 +2357,26 @@ static void hb_vmDivide( void ) if ( lDivisor == 0 ) { - PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ZERODIV, 1340, NULL, "/", 2, pItem1, pItem2 ); + PHB_ITEM pSubst = hb_errRT_BASE_Subst( EG_ZERODIV, 1340, NULL, "/", 2, pItem1, pItem2 ); - if( pResult ) + if( pSubst ) + { + hb_itemForwardValue( pResult, pSubst ); + hb_itemRelease( pSubst ); + } + while( iPopCnt-- > 0 ) { hb_stackPop(); - hb_stackPop(); - hb_vmPush( pResult ); - hb_itemRelease( pResult ); } } else { - hb_stackPop(); /* pop divisor from the stack */ - /* commented out see note below + HB_LONG lNumber1 = HB_ITEM_GET_NUMINTRAW( pItem1 ); + hb_itemPutNDDec( pResult, ( double ) lNumber1 / ( double ) lDivisor, hb_set.HB_SET_DECIMALS ); + while( iPopCnt-- > 0 ) { - HB_LONG lDivided = hb_vmPopHBLong(); - if ( hb_set.HB_SET_DECIMALS == 0 && lDivided % lDivisor == 0 ) - hb_vmPushNumInt( lDivided / lDivisor ); - else - hb_vmPushDouble( ( double ) lDivided / ( double ) lDivisor, hb_set.HB_SET_DECIMALS ); + hb_stackDec(); } - */ - hb_vmPushDouble( hb_vmPopNumber() / ( double ) lDivisor, hb_set.HB_SET_DECIMALS ); } } else if( HB_IS_NUMERIC( pItem1 ) && HB_IS_NUMERIC( pItem2 ) ) @@ -2268,45 +2385,57 @@ static void hb_vmDivide( void ) if( dDivisor == 0.0 ) { - PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ZERODIV, 1340, NULL, "/", 2, pItem1, pItem2 ); + PHB_ITEM pSubst = hb_errRT_BASE_Subst( EG_ZERODIV, 1340, NULL, "/", 2, pItem1, pItem2 ); - if( pResult ) + if( pSubst ) + { + hb_itemForwardValue( pResult, pSubst ); + hb_itemRelease( pSubst ); + } + while( iPopCnt-- > 0 ) { hb_stackPop(); - hb_stackPop(); - hb_vmPush( pResult ); - hb_itemRelease( pResult ); } } else { - hb_stackPop(); /* pop divisor from the stack */ - /* If all both operand was integer and the result is an integer, too, push the number without decimals. Clipper compatible. Actually, this is not Clipper compatible. The only time Clipper returns 0 decimal places is for compiler optimized integer division with an integer result. Therefore this code is not needed and has been removed - David G. Holm - if( bIntegerOperands && fmod( hb_vmTopNumber() / dDivisor ) == 0.0 ) - hb_vmPushNumber( hb_vmPopNumber() / dDivisor, 0 ); - else */ - hb_vmPushDouble( hb_vmPopNumber() / dDivisor, hb_set.HB_SET_DECIMALS ); + double dNumber1 = hb_itemGetND( pItem1 ); + + hb_itemPutNDDec( pResult, dNumber1 / dDivisor, hb_set.HB_SET_DECIMALS ); + while( iPopCnt-- > 0 ) + { + hb_stackDec(); + } } } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpDivide" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPDIVIDE" ); - else { - PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1084, NULL, "/", 2, pItem1, pItem2 ); - - if( pResult ) + hb_vmOperatorCall( pResult, pItem1, pItem2, "__OPDIVIDE" ); + --iPopCnt; /* hb_vmOperatorCall pops pItem2 */ + while( iPopCnt-- > 0 ) { hb_stackPop(); + } + } + else + { + PHB_ITEM pSubst = hb_errRT_BASE_Subst( EG_ARG, 1084, NULL, "/", 2, pItem1, pItem2 ); + + if( pSubst ) + { + hb_itemForwardValue( pResult, pSubst ); + hb_itemRelease( pSubst ); + } + while( iPopCnt-- > 0 ) + { hb_stackPop(); - hb_vmPush( pResult ); - hb_itemRelease( pResult ); } } } @@ -2376,7 +2505,7 @@ static void hb_vmModulus( void ) } } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpMod" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPMOD" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPMOD" ); else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1085, NULL, "%", 2, pItem1, pItem2 ); @@ -2411,7 +2540,7 @@ static void hb_vmPower( void ) hb_vmPushDouble( pow( d1, d2 ), hb_set.HB_SET_DECIMALS ); } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpPower" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPPOWER" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPPOWER" ); else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1088, NULL, "^", 2, pItem1, pItem2 ); @@ -2584,7 +2713,7 @@ static void hb_vmEqual( BOOL bExact ) else if( HB_IS_LOGICAL( pItem1 ) && HB_IS_LOGICAL( pItem2 ) ) hb_vmPushLogical( hb_vmPopLogical() == hb_vmPopLogical() ); else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpEqual" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPEQUAL" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPEQUAL" ); else if( bExact && HB_IS_ARRAY( pItem1 ) && HB_IS_ARRAY( pItem2 ) ) { BOOL bResult = ( pItem1->item.asArray.value == pItem2->item.asArray.value ); @@ -2659,7 +2788,7 @@ static void hb_vmNotEqual( void ) else if( HB_IS_LOGICAL( pItem1 ) && HB_IS_LOGICAL( pItem2 ) ) hb_vmPushLogical( hb_vmPopLogical() != hb_vmPopLogical() ); else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpNotEqual" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPNOTEQUAL" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPNOTEQUAL" ); else if( pItem1->type != pItem2->type || ( HB_IS_BLOCK( pItem1 ) && HB_IS_BLOCK( pItem2 ) ) || ( HB_IS_ARRAY( pItem1 ) && HB_IS_ARRAY( pItem2 ) ) ) @@ -2724,7 +2853,7 @@ static void hb_vmLess( void ) hb_vmPushLogical( bLogical1 < bLogical2 ); } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpLess" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPLESS" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPLESS" ); else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1073, NULL, "<", 2, pItem1, pItem2 ); @@ -2781,7 +2910,7 @@ static void hb_vmLessEqual( void ) hb_vmPushLogical( bLogical1 <= bLogical2 ); } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpLessEqual" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPLESSEQUAL" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPLESSEQUAL" ); else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1074, NULL, "<=", 2, pItem1, pItem2 ); @@ -2838,7 +2967,7 @@ static void hb_vmGreater( void ) hb_vmPushLogical( bLogical1 > bLogical2 ); } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpGreater" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPGREATER" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPGREATER" ); else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1075, NULL, ">", 2, pItem1, pItem2 ); @@ -2895,7 +3024,7 @@ static void hb_vmGreaterEqual( void ) hb_vmPushLogical( bLogical1 >= bLogical2 ); } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpGreaterEqual" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPGREATEREQUAL" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPGREATEREQUAL" ); else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1076, NULL, ">=", 2, pItem1, pItem2 ); @@ -2929,7 +3058,7 @@ static void hb_vmInstring( void ) hb_vmPushLogical( bResult ); } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpInstring" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPINSTRING" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPINSTRING" ); else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1109, NULL, "$", 2, pItem1, pItem2 ); @@ -3399,7 +3528,7 @@ static void hb_vmAnd( void ) hb_stackDec(); } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpAnd" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPAND" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPAND" ); else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1078, NULL, ".AND.", 2, pItem1, pItem2 ); @@ -3431,7 +3560,7 @@ static void hb_vmOr( void ) hb_stackDec(); } else if( HB_IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "__OpOr" ) ) - hb_vmOperatorCall( pItem1, pItem2, "__OPOR" ); + hb_vmOperatorCall( pItem1, pItem1, pItem2, "__OPOR" ); else { PHB_ITEM pResult = hb_errRT_BASE_Subst( EG_ARG, 1079, NULL, ".OR.", 2, pItem1, pItem2 ); @@ -3505,7 +3634,7 @@ static void hb_vmArrayPush( void ) if( HB_IS_OBJECT( pArray ) && hb_objHasMsg( pArray, "__OpArrayIndex" ) ) { - hb_vmOperatorCall( pArray, pIndex, "__OPARRAYINDEX" ); + hb_vmOperatorCall( pArray, pArray, pIndex, "__OPARRAYINDEX" ); return; } @@ -3699,14 +3828,14 @@ static void hb_vmArrayNew( HB_ITEM_PTR pArray, USHORT uiDimension ) /* Object */ /* ------------------------------- */ -static void hb_vmOperatorCall( PHB_ITEM pObjItem, PHB_ITEM pMsgItem, char * szSymbol ) +static void hb_vmOperatorCall( HB_ITEM_PTR pResult, PHB_ITEM pObjItem, PHB_ITEM pMsgItem, char * szSymbol ) { /* NOTE: There is no need to test if specified symbol exists. It is checked * by the caller (if HB_IS_OBJECT() && HAS_METHOD() ) */ HB_ITEM ItemMsg; - HB_TRACE(HB_TR_DEBUG, ("hb_vmOperatorCall(%p, %p, %s)", pObjItem, pMsgItem, szSymbol)); + HB_TRACE(HB_TR_DEBUG, ("hb_vmOperatorCall(%p, %p, %p, %s)", pResult, pObjItem, pMsgItem, szSymbol)); ItemMsg.type = HB_IT_SYMBOL; ItemMsg.item.asSymbol.value = hb_dynsymFind( szSymbol )->pSymbol; @@ -3726,7 +3855,7 @@ static void hb_vmOperatorCall( PHB_ITEM pObjItem, PHB_ITEM pMsgItem, char * szSy * NOTE: for performance reason we don't pop the second argument. * We can replace the second argument with the return value. */ - hb_itemCopy( pObjItem, &hb_stack.Return ); + hb_itemCopy( pResult, &hb_stack.Return ); } static void hb_vmOperatorCallUnary( PHB_ITEM pObjItem, char * szSymbol ) @@ -5500,7 +5629,7 @@ static void hb_vmPopLocal( SHORT iLocal ) hb_itemInit( &item ); hb_itemCopy( &item, hb_stackTopItem() ); - hb_vmOperatorCall( pLocal, &item, "__OPASSIGN" ); + hb_vmOperatorCall( pLocal, pLocal, &item, "__OPASSIGN" ); hb_itemClear( &item ); hb_stackPush(); return; @@ -5535,7 +5664,7 @@ static void hb_vmPopStatic( USHORT uiStatic ) hb_itemInit( &item ); hb_itemCopy( &item, hb_stackTopItem() ); - hb_vmOperatorCall( pStatic, &item, "__OPASSIGN" ); + hb_vmOperatorCall( pStatic, pStatic, &item, "__OPASSIGN" ); hb_itemClear( &item ); hb_stackPush(); return; diff --git a/harbour/source/vm/itemapi.c b/harbour/source/vm/itemapi.c index f7476b4b5f..3e9f36edaa 100644 --- a/harbour/source/vm/itemapi.c +++ b/harbour/source/vm/itemapi.c @@ -893,6 +893,76 @@ HB_EXPORT PHB_ITEM hb_itemPutNDLen( PHB_ITEM pItem, double dNumber, int iWidth, return pItem; } +HB_EXPORT PHB_ITEM hb_itemPutNDDec( PHB_ITEM pItem, double dNumber, int iDec ) +{ + HB_TRACE_STEALTH(HB_TR_DEBUG, ("hb_itemPutNDDec(%p, %lf, %i)", pItem, dNumber, iDec)); + + if( pItem ) + { + if( HB_IS_COMPLEX( pItem ) ) + { + hb_itemClear( pItem ); + } + } + else + { + pItem = hb_itemNew( NULL ); + } + + pItem->type = HB_IT_DOUBLE; + pItem->item.asDouble.length = HB_DBL_LENGTH( dNumber ); + + if( iDec == HB_DEFAULT_DECIMALS ) + { + pItem->item.asDouble.decimal = hb_set.HB_SET_DECIMALS; + } + else + { + pItem->item.asDouble.decimal = iDec; + } + + pItem->item.asDouble.value = dNumber; + + return pItem; +} + +HB_EXPORT double hb_itemGetNDDec( PHB_ITEM pItem, int * piDec ) +{ + double dNumber; + + HB_TRACE(HB_TR_DEBUG, ("hb_itemGetNDDec(%p,p%)", pItem, piDec)); + + switch( pItem->type ) + { + case HB_IT_INTEGER: + dNumber = ( double ) pItem->item.asInteger.value; + *piDec = 0; + break; + + case HB_IT_LONG: + dNumber = ( double ) pItem->item.asLong.value; + *piDec = 0; + break; + + case HB_IT_DOUBLE: + dNumber = pItem->item.asDouble.value; + *piDec = pItem->item.asDouble.decimal; + break; + + case HB_IT_DATE: + dNumber = (double) pItem->item.asDate.value; + *piDec = 0; + break; + + default: + dNumber = 0; /* To avoid GCC -O2 warning */ + break; + } + + return dNumber; +} + + HB_EXPORT PHB_ITEM hb_itemPutNILen( PHB_ITEM pItem, int iNumber, int iWidth ) { HB_TRACE(HB_TR_DEBUG, ("hb_itemPutNILen(%p, %d, %d)", pItem, iNumber, iWidth)); @@ -979,6 +1049,51 @@ HB_EXPORT PHB_ITEM hb_itemPutNLLLen( PHB_ITEM pItem, LONGLONG llNumber, int iWid } #endif +HB_EXPORT PHB_ITEM hb_itemPutHBLong( PHB_ITEM pItem, HB_LONG lNumber ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_itemPutHBLong( %p, %" PFHL "d)", pItem, lNumber)); + + if( pItem ) + { + if( HB_IS_COMPLEX( pItem ) ) + { + hb_itemClear( pItem ); + } + } + else + { + pItem = hb_itemNew( NULL ); + } + + pItem->type = HB_IT_LONG; + pItem->item.asLong.value = lNumber; + pItem->item.asLong.length = HB_LONG_LENGTH( lNumber ); + + return pItem; +} + +HB_EXPORT PHB_ITEM hb_itemPutNumType( PHB_ITEM pItem, double dNumber, int iDec, int iType1, int iType2 ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_itemPutNumType( %p, %lf, %d, %i, %i)", pItem, dNumber, iDec, iType1, iType2)); + + if( iDec || iType1 & HB_IT_DOUBLE || iType2 & HB_IT_DOUBLE ) + { + return hb_itemPutNDDec( pItem, dNumber, iDec ); + } + else if ( HB_DBL_LIM_INT( dNumber ) ) + { + return hb_itemPutNI( pItem, ( int ) dNumber ); + } + else if ( HB_DBL_LIM_LONG( dNumber ) ) + { + return hb_itemPutHBLong( pItem, ( HB_LONG ) dNumber ); + } + else + { + return hb_itemPutND( pItem, dNumber ); + } +} + HB_EXPORT PHB_ITEM hb_itemPutPtr( PHB_ITEM pItem, void * pValue ) { HB_TRACE(HB_TR_DEBUG, ("hb_itemPutPtr(%p, %p)", pItem, pValue));