From 9d263b1141270537191a96caeec240aadd4da36b Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Fri, 5 Jan 2007 07:41:20 +0000 Subject: [PATCH] 2007-01-05 08:00 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbcompdf.h + added comment * harbour/include/hbexpra.c * change expression type for = from HB_EO_EQUAL to HB_EO_ASSIGN in hb_compExprGenStatement() function so later we can safely make all optimization in hb_compExprUseEqual() during reduce process - optimization only when PCODE is generated is too late and causes that expressions like: iif( 1 = 1, , ) are not reduces (Clipper reduce them) * do not execute hb_compFunCallCheck() in hb_compExprNewFunCall() to avoid repeating the same error message in hb_compExprUseFunCall() * harbour/include/hbexprb.c * enabled reduction for hb_compExprUseEqual() and generate errors when it's used as statement * harbour/source/common/expropt2.c * added some missing reductions for expressions like: NIL == NIL * harbour/source/common/reserved.c % very basic optimization: use binary search instead of linear scanning for reserved words and shortcuts - it gives noticeable speed improvement in macro compiler * harbour/source/compiler/complex.c * changed the order of special keywords to keep alphabetic sorting * harbour/source/compiler/harbour.c % some minor optimizations in aliased expressions ! added protection in hb_compIsJump() to avoid possible problems when this function is executed after replacing some code with jumps by series of NOOPs in optimizations process * harbour/source/compiler/hbfix.c * better optimization of PCODE generated for logical expressions * harbour/source/compiler/hbfunchk.c % use binary search instead of linear scan * harbour/source/rtl/minmax.c ! fixed GPF when MIN() or MAX() function is called with less then two parameters * harbour/source/vm/itemapi.c * minor optimization and formatting --- harbour/ChangeLog | 49 +++++++++ harbour/include/hbcompdf.h | 2 +- harbour/include/hbexpra.c | 16 ++- harbour/include/hbexprb.c | 108 ++----------------- harbour/source/common/expropt2.c | 101 +++++++++++------- harbour/source/common/reserved.c | 44 ++++---- harbour/source/compiler/complex.c | 24 ++--- harbour/source/compiler/harbour.c | 85 ++++++--------- harbour/source/compiler/hbfix.c | 165 +++++++++++++++++++++-------- harbour/source/compiler/hbfunchk.c | 85 ++++++++------- harbour/source/rtl/minmax.c | 155 ++++++++++++++------------- harbour/source/vm/itemapi.c | 11 +- 12 files changed, 456 insertions(+), 389 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index b43d5edb32..5163ced005 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,55 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2007-01-05 08:00 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbcompdf.h + + added comment + + * harbour/include/hbexpra.c + * change expression type for = from HB_EO_EQUAL + to HB_EO_ASSIGN in hb_compExprGenStatement() function so + later we can safely make all optimization in hb_compExprUseEqual() + during reduce process - optimization only when PCODE is generated + is too late and causes that expressions like: + iif( 1 = 1, , ) + are not reduces (Clipper reduce them) + * do not execute hb_compFunCallCheck() in hb_compExprNewFunCall() + to avoid repeating the same error message in hb_compExprUseFunCall() + + * harbour/include/hbexprb.c + * enabled reduction for hb_compExprUseEqual() and generate errors + when it's used as statement + + * harbour/source/common/expropt2.c + * added some missing reductions for expressions like: NIL == NIL + + * harbour/source/common/reserved.c + % very basic optimization: use binary search instead of linear + scanning for reserved words and shortcuts - it gives noticeable + speed improvement in macro compiler + + * harbour/source/compiler/complex.c + * changed the order of special keywords to keep alphabetic sorting + + * harbour/source/compiler/harbour.c + % some minor optimizations in aliased expressions + ! added protection in hb_compIsJump() to avoid possible problems + when this function is executed after replacing some code with + jumps by series of NOOPs in optimizations process + + * harbour/source/compiler/hbfix.c + * better optimization of PCODE generated for logical expressions + + * harbour/source/compiler/hbfunchk.c + % use binary search instead of linear scan + + * harbour/source/rtl/minmax.c + ! fixed GPF when MIN() or MAX() function is called with less then + two parameters + + * harbour/source/vm/itemapi.c + * minor optimization and formatting + 2006-12-30 22:45 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbcomp.h * harbour/include/hbcompdf.h diff --git a/harbour/include/hbcompdf.h b/harbour/include/hbcompdf.h index f729c4a4f3..35cd689cd1 100644 --- a/harbour/include/hbcompdf.h +++ b/harbour/include/hbcompdf.h @@ -481,7 +481,7 @@ HB_COMMON, * HB_COMMON_PTR; #define HB_COMP_PARAM pMacro #define HB_COMP_DECL HB_MACRO_PTR HB_COMP_PARAM -typedef struct HB_PCODE_INFO_ /* compiled pcode container */ +typedef struct HB_PCODE_INFO_ /* compiled pcode container for macro compiler */ { BYTE * pCode; /* pointer to a memory block where pcode is stored */ ULONG lPCodeSize; /* total memory size for pcode */ diff --git a/harbour/include/hbexpra.c b/harbour/include/hbexpra.c index 3ce0da99c4..b6d7def075 100644 --- a/harbour/include/hbexpra.c +++ b/harbour/include/hbexpra.c @@ -393,17 +393,7 @@ HB_EXPR_PTR hb_compExprNewFunCall( HB_EXPR_PTR pName, HB_EXPR_PTR pParms, HB_COM iCount = ( int ) hb_compExprParamListLen( pParms ); -#ifndef HB_MACRO_SUPPORT - if( ! hb_compFunCallCheck( HB_COMP_PARAM, pName->value.asSymbol, iCount ) ) - { - /* skip any farther modifications which can depend on valid number - of parameters */ - ; - } - else -#endif /* TODO: EMPTY() (not done by Clipper) */ - if( iCount && strcmp( "EVAL", pName->value.asSymbol ) == 0 ) { HB_EXPR_PTR pEval; @@ -935,6 +925,12 @@ HB_EXPR_PTR hb_compExprGenStatement( HB_EXPR_PTR pExpr, HB_COMP_DECL ) HB_TRACE(HB_TR_DEBUG, ("hb_compExprGenStatement(%p)", pExpr)); if( pExpr ) { + if( pExpr->ExprType == HB_EO_EQUAL ) + { + /* NOTE: direct type change */ + pExpr->ExprType = HB_EO_ASSIGN; + } + pExpr = HB_EXPR_USE( pExpr, HB_EA_REDUCE ); HB_EXPR_USE( pExpr, HB_EA_STATEMENT ); } diff --git a/harbour/include/hbexprb.c b/harbour/include/hbexprb.c index 3c9297e8a0..7b1589bd68 100644 --- a/harbour/include/hbexprb.c +++ b/harbour/include/hbexprb.c @@ -2709,13 +2709,15 @@ static HB_EXPR_FUNC( hb_compExprUseEqual ) switch( iMessage ) { case HB_EA_REDUCE: - { - pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_COMP_PARAM ); - pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_COMP_PARAM ); - } + pSelf->value.asOperator.pLeft = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_REDUCE ), HB_COMP_PARAM ); + pSelf->value.asOperator.pRight = hb_compExprListStrip( HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_REDUCE ), HB_COMP_PARAM ); + pSelf = hb_compExprReduceEQ( pSelf, HB_COMP_PARAM ); break; case HB_EA_ARRAY_AT: + hb_compErrorType( HB_COMP_PARAM, pSelf ); + break; + case HB_EA_ARRAY_INDEX: break; @@ -2723,81 +2725,9 @@ static HB_EXPR_FUNC( hb_compExprUseEqual ) hb_compErrorLValue( HB_COMP_PARAM, pSelf ); break; case HB_EA_PUSH_PCODE: - { - /* '=' used in an expression - compare values - */ - /* Try to optimize expression - we cannot optimize in HB_EA_REDUCE - * because it is not decided yet if it is assigment or comparision - */ - HB_EXPR_PTR pLeft, pRight; - - pLeft = pSelf->value.asOperator.pLeft; - pRight = pSelf->value.asOperator.pRight; - - if( pLeft->ExprType == pRight->ExprType ) - switch( pLeft->ExprType ) - { - case HB_ET_LOGICAL: - HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asLogical == pRight->value.asLogical) ); - break; - - case HB_ET_STRING: - /* NOTE: the result depends on SET EXACT setting then it - * cannot be optimized except the case when NULL string are - * compared - the result is always TRUE regardless of EXACT - * setting - */ - if( (pLeft->ulLength | pRight->ulLength) == 0 ) - HB_EXPR_PCODE1( hb_compGenPushLogical, TRUE ); /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ - else - { - HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); - HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_EQUAL ); - } - break; - - case HB_ET_NIL: - /* NOTE: COMPATIBILITY: Clipper doesn't optimize this */ - HB_EXPR_PCODE1( hb_compGenPushLogical, TRUE ); /* NIL = NIL is always TRUE */ - break; - - case HB_ET_NUMERIC: - switch( pLeft->value.asNum.NumType & pRight->value.asNum.NumType ) - { - case HB_ET_LONG: - HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asNum.val.l == pRight->value.asNum.val.l) ); - break; - case HB_ET_DOUBLE: - HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asNum.val.d == pRight->value.asNum.val.d) ); - break; - default: - { - if( pLeft->value.asNum.NumType == HB_ET_LONG ) - HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asNum.val.l == pRight->value.asNum.val.d) ); - else - HB_EXPR_PCODE1( hb_compGenPushLogical, (pLeft->value.asNum.val.d == pRight->value.asNum.val.l) ); - } - break; - } - break; - - default: - { - HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); - HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_EQUAL ); - } - } - else - { - /* TODO: check for incompatible types - */ - HB_EXPR_USE( pLeft, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pRight, HB_EA_PUSH_PCODE ); - HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_EQUAL ); - } - } + HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_PUSH_PCODE ); + HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); + HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_EQUAL ); break; case HB_EA_POP_PCODE: @@ -2820,25 +2750,7 @@ static HB_EXPR_FUNC( hb_compExprUseEqual ) break; case HB_EA_STATEMENT: - /* '=' used standalone in a statement - assign a value - * it assigns a value and removes it from the stack - * */ - if( pSelf->value.asOperator.pLeft->ExprType == HB_ET_SEND ) - { - /* Send messages are implemented as function calls - */ - HB_EXPR_PTR pObj = pSelf->value.asOperator.pLeft; - pObj->value.asMessage.pParms = pSelf->value.asOperator.pRight; - HB_EXPR_USE( pObj, HB_EA_POP_PCODE ); - pObj->value.asMessage.pParms = NULL; /* to suppress duplicated releasing */ - /* Remove the return value */ - HB_EXPR_PCODE1( hb_compGenPCode1, HB_P_POP ); - } - else - { - HB_EXPR_USE( pSelf->value.asOperator.pRight, HB_EA_PUSH_PCODE ); - HB_EXPR_USE( pSelf->value.asOperator.pLeft, HB_EA_POP_PCODE ); - } + hb_compErrorSyntax( HB_COMP_PARAM, pSelf ); break; case HB_EA_DELETE: diff --git a/harbour/source/common/expropt2.c b/harbour/source/common/expropt2.c index f816ee6034..6180ad2eab 100644 --- a/harbour/source/common/expropt2.c +++ b/harbour/source/common/expropt2.c @@ -571,6 +571,7 @@ HB_EXPR_PTR hb_compExprReduceNE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) pRight = pSelf->value.asOperator.pRight; if( pLeft->ExprType == pRight->ExprType ) + { switch( pLeft->ExprType ) { case HB_ET_LOGICAL: @@ -581,8 +582,8 @@ HB_EXPR_PTR hb_compExprReduceNE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) * .T. != .F. = .T. */ BOOL bResult = ( pLeft->value.asLogical != pRight->value.asLogical ); - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -595,10 +596,10 @@ HB_EXPR_PTR hb_compExprReduceNE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) * compared - "" != "" is always FALSE regardless of EXACT * setting */ - if( (pLeft->ulLength | pRight->ulLength) == 0 ) + if( ( pLeft->ulLength | pRight->ulLength ) == 0 ) { - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = FALSE; @@ -628,15 +629,23 @@ HB_EXPR_PTR hb_compExprReduceNE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; } - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; + case HB_ET_NIL: + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = FALSE; + break; } + } /* TODO: add checking of incompatible types else { @@ -663,8 +672,8 @@ HB_EXPR_PTR hb_compExprReduceGE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) * .F. >= .T. = .f. */ BOOL bResult = ! ( ! pLeft->value.asLogical && pRight->value.asLogical ); - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -692,8 +701,8 @@ HB_EXPR_PTR hb_compExprReduceGE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; } - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -727,8 +736,8 @@ HB_EXPR_PTR hb_compExprReduceLE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) * .F. <= .T. = .T. */ BOOL bResult = ! ( pLeft->value.asLogical && ! pRight->value.asLogical ); - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -756,8 +765,8 @@ HB_EXPR_PTR hb_compExprReduceLE( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; } - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -791,8 +800,8 @@ HB_EXPR_PTR hb_compExprReduceGT( HB_EXPR_PTR pSelf, HB_COMP_DECL ) * .F. > .T. = .F. */ BOOL bResult = ( pLeft->value.asLogical && ! pRight->value.asLogical ); - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -820,8 +829,8 @@ HB_EXPR_PTR hb_compExprReduceGT( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; } - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -855,8 +864,8 @@ HB_EXPR_PTR hb_compExprReduceLT( HB_EXPR_PTR pSelf, HB_COMP_DECL ) * .T. < .F. = .F. */ BOOL bResult = ( ! pLeft->value.asLogical && pRight->value.asLogical ); - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -884,8 +893,8 @@ HB_EXPR_PTR hb_compExprReduceLT( HB_EXPR_PTR pSelf, HB_COMP_DECL ) } break; } - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -917,8 +926,8 @@ HB_EXPR_PTR hb_compExprReduceEQ( HB_EXPR_PTR pSelf, HB_COMP_DECL ) case HB_ET_LOGICAL: { BOOL bResult = ( pLeft->value.asLogical == pRight->value.asLogical ); - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -926,13 +935,21 @@ HB_EXPR_PTR hb_compExprReduceEQ( HB_EXPR_PTR pSelf, HB_COMP_DECL ) break; case HB_ET_STRING: + /* NOTE: when not exact comparison (==) is used + * the result depends on SET EXACT setting then it + * cannot be optimized except the case when NULL string are + * compared - "" = "" is always FALSE regardless of EXACT + * setting + */ + if( pSelf->ExprType == HB_EO_EQ || + ( pLeft->ulLength | pRight->ulLength ) == 0 ) { - BOOL bResult = FALSE; - - if( pLeft->ulLength == pRight->ulLength ) - bResult = ( strcmp( pLeft->value.asString.string, pRight->value.asString.string ) == 0 ); - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + BOOL bResult = pLeft->ulLength == pRight->ulLength && + memcmp( pLeft->value.asString.string, + pRight->value.asString.string, + pLeft->ulLength ) == 0; + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; @@ -952,21 +969,27 @@ HB_EXPR_PTR hb_compExprReduceEQ( HB_EXPR_PTR pSelf, HB_COMP_DECL ) bResult = ( pLeft->value.asNum.val.d == pRight->value.asNum.val.d ); break; default: - { - if( pLeft->value.asNum.NumType == HB_ET_LONG ) - bResult = ( pLeft->value.asNum.val.l == pRight->value.asNum.val.d ); - else - bResult = ( pLeft->value.asNum.val.d == pRight->value.asNum.val.l ); - } + if( pLeft->value.asNum.NumType == HB_ET_LONG ) + bResult = ( pLeft->value.asNum.val.l == pRight->value.asNum.val.d ); + else + bResult = ( pLeft->value.asNum.val.d == pRight->value.asNum.val.l ); break; } - hb_compExprFree( pSelf->value.asOperator.pLeft, HB_COMP_PARAM ); - hb_compExprFree( pSelf->value.asOperator.pRight, HB_COMP_PARAM ); + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); pSelf->ExprType = HB_ET_LOGICAL; pSelf->ValType = HB_EV_LOGICAL; pSelf->value.asLogical = bResult; } break; + + case HB_ET_NIL: + hb_compExprFree( pLeft, HB_COMP_PARAM ); + hb_compExprFree( pRight, HB_COMP_PARAM ); + pSelf->ExprType = HB_ET_LOGICAL; + pSelf->ValType = HB_EV_LOGICAL; + pSelf->value.asLogical = TRUE; + break; } } /* TODO: add checking of incompatible types diff --git a/harbour/source/common/reserved.c b/harbour/source/common/reserved.c index cebe8f9f20..7b9a788b0f 100644 --- a/harbour/source/common/reserved.c +++ b/harbour/source/common/reserved.c @@ -54,8 +54,8 @@ /* Table with reserved functions names * NOTE: THIS TABLE MUST BE SORTED ALPHABETICALLY -*/ -#if(!defined( HB_RESERVED_OFF )) + */ +#if !defined( HB_RESERVED_OFF ) static const char * s_szReservedFun[] = { "AADD" , "ABS" , @@ -128,26 +128,34 @@ static const char * s_szReservedFun[] = { char * hb_compReservedName( char * szName ) { -#if(!defined( HB_RESERVED_OFF )) - unsigned int wNum = 0; - int iFound = 1; +#if !defined( HB_RESERVED_OFF ) + unsigned int uiFirst = 0, uiLast = RESERVED_FUNCTIONS - 1, uiMiddle; + int iLen = ( int ) strlen( szName ), iCmp; - while( wNum < RESERVED_FUNCTIONS && iFound ) + /* Respect 4 or more letters shortcuts + * SECO() is not allowed because of Clipper function SECONDS() + * however SECO32() is a valid name. + */ + if( iLen < 4 ) + iLen = 4; + do { - /* Compare first 4 characters - * If they are the same then compare the whole name - * SECO() is not allowed because of Clipper function SECONDS() - * however SECO32() is a valid name. - */ - iFound = strncmp( szName, s_szReservedFun[ wNum ], 4 ); - if( iFound == 0 ) - iFound = strncmp( szName, s_szReservedFun[ wNum ], strlen( szName ) ); - ++wNum; + uiMiddle = ( uiFirst + uiLast ) >> 1; + iCmp = strncmp( szName, s_szReservedFun[ uiMiddle ], iLen ); + if( iCmp <= 0 ) + uiLast = uiMiddle; + else + uiFirst = uiMiddle + 1; } + while( uiFirst < uiLast ); - return iFound == 0 ? ( char * ) s_szReservedFun[ wNum - 1 ] : NULL; -#else - return NULL; + if( uiFirst != uiMiddle ) + iCmp = strncmp( szName, s_szReservedFun[ uiFirst ], iLen ); + + if( iCmp == 0 ) + return ( char * ) s_szReservedFun[ uiFirst ]; #endif + + return NULL; } diff --git a/harbour/source/compiler/complex.c b/harbour/source/compiler/complex.c index 1b55d150a5..52f68051d0 100644 --- a/harbour/source/compiler/complex.c +++ b/harbour/source/compiler/complex.c @@ -108,27 +108,26 @@ HB_LEX_KEY, * PHB_LEX_KEY; static const HB_LEX_KEY s_keytable[] = { { "ANNOUNCE", 4, 8, ANNOUNCE }, + { "AS", 2, 2, AS_TYPE }, { "BEGIN", 4, 5, BEGINSEQ }, { "BREAK", 4, 5, BREAK }, { "CASE", 4, 4, CASE }, { "DECLARE", 4, 7, DECLARE }, - { "OPTIONAL", 4, 8, OPTIONAL }, - { "DO", 2, 2, DO }, { "DESCEND", 7, 7, DESCEND }, + { "DO", 2, 2, DO }, { "ELSE", 4, 4, ELSE }, { "ELSEIF", 5, 6, ELSEIF }, { "END", 3, 3, END }, - { "ENDIF", 4, 5, ENDIF }, { "ENDCASE", 4, 7, ENDCASE }, { "ENDDO", 4, 5, ENDDO }, + { "ENDIF", 4, 5, ENDIF }, { "EXIT", 4, 4, EXIT }, { "EXTERNAL", 4, 8, EXTERN }, - { "_FIELD", 4, 6, FIELD }, { "FIELD", 4, 5, FIELD }, { "FOR", 3, 3, FOR }, { "FUNCTION", 4, 8, FUNCTION }, - { "IIF", 3, 3, IIF }, { "IF", 2, 2, IF }, + { "IIF", 3, 3, IIF }, { "IN", 2, 2, IN }, { "INIT", 4, 4, INIT }, { "LOCAL", 4, 5, LOCAL }, @@ -136,6 +135,7 @@ static const HB_LEX_KEY s_keytable[] = { "MEMVAR", 4, 6, MEMVAR }, { "NEXT", 4, 4, NEXT }, { "NIL", 3, 3, NIL }, + { "OPTIONAL", 4, 8, OPTIONAL }, { "OTHERWISE", 4, 9, OTHERWISE }, { "PARAMETERS", 4, 10, PARAMETERS }, { "PRIVATE", 4, 7, PRIVATE }, @@ -150,10 +150,10 @@ static const HB_LEX_KEY s_keytable[] = { "TO", 2, 2, TO }, { "WHILE", 4, 5, WHILE }, { "WITH", 4, 4, WITH }, - { "_PROCREQ_", 9, 9, PROCREQ }, - { "AS", 2, 2, AS_TYPE }, + { "_FIELD", 4, 6, FIELD }, { "_HB_CLASS", 9, 9, DECLARE_CLASS }, - { "_HB_MEMBER", 10, 10, DECLARE_MEMBER } + { "_HB_MEMBER", 10, 10, DECLARE_MEMBER }, + { "_PROCREQ_", 9, 9, PROCREQ } }; #define _AS_ARRAY 1 @@ -196,17 +196,17 @@ static const int s_asArrayTypes[] = static const HB_LEX_KEY s_typetable[] = { + { "ANYTYPE", 4, 7, _AS_VARIANT }, { "ARRAY", 4, 5, _AS_ARRAY }, - { "CODEBLOCK", 4, 9, _AS_BLOCK }, - { "STRING", 4, 6, _AS_CHARACTER }, { "CHARACTER", 4, 9, _AS_CHARACTER }, { "CLASS", 4, 5, _AS_CLASS }, + { "CODEBLOCK", 4, 9, _AS_BLOCK }, { "DATE", 4, 4, _AS_DATE }, { "LOGICAL", 4, 7, _AS_LOGICAL }, { "NUMERIC", 4, 7, _AS_NUMERIC }, { "OBJECT", 4, 6, _AS_OBJECT }, - { "USUAL", 4, 5, _AS_VARIANT }, - { "ANYTYPE", 4, 7, _AS_VARIANT } + { "STRING", 4, 6, _AS_CHARACTER }, + { "USUAL", 4, 5, _AS_VARIANT } }; static int hb_comp_asType( PHB_PP_TOKEN pToken, BOOL fArray ) diff --git a/harbour/source/compiler/harbour.c b/harbour/source/compiler/harbour.c index b55c35ffda..143319b23d 100644 --- a/harbour/source/compiler/harbour.c +++ b/harbour/source/compiler/harbour.c @@ -2949,34 +2949,22 @@ void hb_compGenPopAliasedVar( char * szVarName, { if( szAlias ) { - if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) - { /* M->variable */ + int iLen = strlen( szAlias ); + if( szAlias[ 0 ] == 'M' && ( iLen == 1 || + ( iLen >= 4 && iLen <= 6 && + memcmp( szAlias, "MEMVAR", iLen ) == 0 ) ) ) + { /* M->variable or MEMV[A[R]]->variable */ hb_compGenVarPCode( HB_P_POPMEMVAR, szVarName, HB_COMP_PARAM ); } + else if( iLen >= 4 && iLen <= 5 && + memcmp( szAlias, "FIELD", iLen ) == 0 ) + { /* FIEL[D]->variable */ + hb_compGenVarPCode( HB_P_POPFIELD, szVarName, HB_COMP_PARAM ); + } else - { - int iCmp = strncmp( szAlias, "MEMVAR", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( szAlias, "MEMVAR", strlen( szAlias ) ); - if( iCmp == 0 ) - { /* MEMVAR-> or MEMVA-> or MEMV-> */ - hb_compGenVarPCode( HB_P_POPMEMVAR, szVarName, HB_COMP_PARAM ); - } - else - { /* field variable */ - iCmp = strncmp( szAlias, "FIELD", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( szAlias, "FIELD", strlen( szAlias ) ); - if( iCmp == 0 ) - { /* FIELD-> */ - hb_compGenVarPCode( HB_P_POPFIELD, szVarName, HB_COMP_PARAM ); - } - else - { /* database alias */ - hb_compGenPushSymbol( szAlias, FALSE, TRUE, HB_COMP_PARAM ); - hb_compGenVarPCode( HB_P_POPALIASEDFIELD, szVarName, HB_COMP_PARAM ); - } - } + { /* database alias */ + hb_compGenPushSymbol( szAlias, FALSE, TRUE, HB_COMP_PARAM ); + hb_compGenVarPCode( HB_P_POPALIASEDFIELD, szVarName, HB_COMP_PARAM ); } } else @@ -3197,38 +3185,26 @@ void hb_compGenPushAliasedVar( char * szVarName, { if( szAlias ) { + int iLen = strlen( szAlias ); /* myalias->var * FIELD->var * MEMVAR->var */ - if( szAlias[ 0 ] == 'M' && szAlias[ 1 ] == '\0' ) - { /* M->variable */ + if( szAlias[ 0 ] == 'M' && ( iLen == 1 || + ( iLen >= 4 && iLen <= 6 && + memcmp( szAlias, "MEMVAR", iLen ) == 0 ) ) ) + { /* M->variable or MEMV[A[R]]->variable */ hb_compGenVarPCode( HB_P_PUSHMEMVAR, szVarName, HB_COMP_PARAM ); } + else if( iLen >= 4 && iLen <= 5 && + memcmp( szAlias, "FIELD", iLen ) == 0 ) + { /* FIEL[D]->variable */ + hb_compGenVarPCode( HB_P_PUSHFIELD, szVarName, HB_COMP_PARAM ); + } else - { - int iCmp = strncmp( szAlias, "MEMVAR", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( szAlias, "MEMVAR", strlen( szAlias ) ); - if( iCmp == 0 ) - { /* MEMVAR-> or MEMVA-> or MEMV-> */ - hb_compGenVarPCode( HB_P_PUSHMEMVAR, szVarName, HB_COMP_PARAM ); - } - else - { /* field variable */ - iCmp = strncmp( szAlias, "FIELD", 4 ); - if( iCmp == 0 ) - iCmp = strncmp( szAlias, "FIELD", strlen( szAlias ) ); - if( iCmp == 0 ) - { /* FIELD-> */ - hb_compGenVarPCode( HB_P_PUSHFIELD, szVarName, HB_COMP_PARAM ); - } - else - { /* database alias */ - hb_compGenPushSymbol( szAlias, FALSE, TRUE, HB_COMP_PARAM ); - hb_compGenVarPCode( HB_P_PUSHALIASEDFIELD, szVarName, HB_COMP_PARAM ); - } - } + { /* database alias */ + hb_compGenPushSymbol( szAlias, FALSE, TRUE, HB_COMP_PARAM ); + hb_compGenVarPCode( HB_P_PUSHALIASEDFIELD, szVarName, HB_COMP_PARAM ); } } else @@ -3289,7 +3265,6 @@ void hb_compGenPushFunRef( char * szFunName, HB_COMP_DECL ) TRUE, FALSE, HB_COMP_PARAM ); } - /* generates the pcode to push a long number on the virtual machine stack */ void hb_compGenPushLong( HB_LONG lNumber, HB_COMP_DECL ) { @@ -3716,6 +3691,14 @@ BOOL hb_compIsJump( HB_COMP_DECL, PFUNCTION pFunc, ULONG ulPos ) ulJumpAddr += HB_PCODE_MKSHORT( &pFunc->pCode[ ulJumpAddr + 1 ] ); break; + /* Jump can be replaced by series of NOOPs or POP and NOOPs + * and not stripped yet + */ + case HB_P_NOOP: + case HB_P_POP: + ulJumpAddr = ulPos + 1; + break; + default: ulJumpAddr += HB_PCODE_MKINT24( &pFunc->pCode[ ulJumpAddr + 1 ] ); break; diff --git a/harbour/source/compiler/hbfix.c b/harbour/source/compiler/hbfix.c index ca8a64a865..efab484d3e 100644 --- a/harbour/source/compiler/hbfix.c +++ b/harbour/source/compiler/hbfix.c @@ -424,6 +424,89 @@ static HB_FIX_FUNC( hb_p_true ) return 1; } +static HB_FIX_FUNC( hb_p_duplicate ) +{ + HB_COMP_DECL = cargo->HB_COMP_PARAM; + + if( cargo->iNestedCodeblock == 0 && HB_COMP_ISSUPPORTED(HB_COMPFLAG_OPTJUMP) ) + { + switch( pFunc->pCode[ lPCodePos + 1 ] ) + { + case HB_P_JUMPTRUEFAR: + case HB_P_JUMPFALSEFAR: + if( pFunc->pCode[ lPCodePos + 5 ] == HB_P_POP ) + { + BYTE * pAddr = &pFunc->pCode[ lPCodePos + 2 ]; + LONG lOffset = HB_PCODE_MKINT24( pAddr ), lLastOffset = 0; + ULONG ulNewPos = lPCodePos + 1 + lOffset; + BOOL fNot = FALSE, fRepeat = TRUE; + + do + { + if( pFunc->pCode[ ulNewPos ] == HB_P_DUPLICATE ) + { + if( lOffset > 0 ) + hb_p_duplicate( pFunc, ulNewPos, cargo ); + } + + if( pFunc->pCode[ ulNewPos ] == HB_P_NOOP ) + { + ulNewPos++; + lOffset++; + } + else if( pFunc->pCode[ ulNewPos ] == HB_P_NOT ) + { + ulNewPos++; + lOffset++; + fNot = !fNot; + } + else if( pFunc->pCode[ ulNewPos ] == HB_P_DUPLICATE && + ( pFunc->pCode[ ulNewPos + 1 ] == HB_P_JUMPTRUEFAR || + pFunc->pCode[ ulNewPos + 1 ] == HB_P_JUMPFALSEFAR ) ) + { + LONG lJump; + if( pFunc->pCode[ ulNewPos + 1 ] != pFunc->pCode[ lPCodePos + 1 ] ) + fNot = !fNot; + lJump = fNot ? 4 : HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 2 ] ); + lOffset += lJump + 1; + ulNewPos = lPCodePos + 1 + lOffset; + fRepeat = lJump > 0; + } + else + fRepeat = FALSE; + + if( !fNot ) + lLastOffset = lOffset; + } + while( fRepeat ); + + if( ( pFunc->pCode[ ulNewPos ] == HB_P_JUMPTRUEFAR || + pFunc->pCode[ ulNewPos ] == HB_P_JUMPFALSEFAR ) && + !hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 1 ) && + !hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 5 ) ) + { + if( pFunc->pCode[ ulNewPos ] != pFunc->pCode[ lPCodePos + 1 ] ) + fNot = !fNot; + if( fNot ) + lOffset += 4; + else + lOffset += HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 1 ] ); + + HB_PUT_LE_UINT24( pAddr, lOffset ); + hb_compNOOPfill( pFunc, lPCodePos, 1, FALSE, FALSE ); + hb_compNOOPfill( pFunc, lPCodePos + 5, 1, FALSE, FALSE ); + } + else if( lLastOffset ) + { + HB_PUT_LE_UINT24( pAddr, lLastOffset ); + } + } + break; + } + } + return 1; +} + static HB_FIX_FUNC( hb_p_not ) { if( cargo->iNestedCodeblock == 0 ) @@ -453,6 +536,41 @@ static HB_FIX_FUNC( hb_p_not ) case HB_P_JUMPFALSEFAR: opcode = HB_P_JUMPTRUEFAR; break; +/* This optimization will be enabled in the future in a little bit differ form */ +#if 0 + case HB_P_DUPLICATE: + if( ( pFunc->pCode[ lPCodePos + 2 ] == HB_P_JUMPTRUEFAR || + pFunc->pCode[ lPCodePos + 2 ] == HB_P_JUMPFALSEFAR ) && + pFunc->pCode[ lPCodePos + 6 ] == HB_P_POP ) + { + BYTE * pAddr = &pFunc->pCode[ lPCodePos + 3 ]; + LONG lOffset = HB_PCODE_MKINT24( pAddr ); + + if( lOffset > 0 ) + { + hb_p_duplicate( pFunc, lPCodePos + 1, cargo ); + lOffset = HB_PCODE_MKINT24( pAddr ); + } + + if( ( pFunc->pCode[ lPCodePos + 1 ] == HB_P_NOT || + ( pFunc->pCode[ lPCodePos + 1 ] == HB_P_DUPLICATE && + pFunc->pCode[ lPCodePos + lOffset + 2 ] == HB_P_NOT ) ) && + ! hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 1 ) ) + { + hb_compNOOPfill( pFunc, lPCodePos, 1, FALSE, FALSE ); + if( pFunc->pCode[ lPCodePos + 2 ] == HB_P_JUMPTRUEFAR ) + pFunc->pCode[ lPCodePos + 2 ] = HB_P_JUMPFALSEFAR; + else + pFunc->pCode[ lPCodePos + 2 ] = HB_P_JUMPTRUEFAR; + if( pFunc->pCode[ lPCodePos + 1 ] == HB_P_DUPLICATE ) + { + ++lOffset; + HB_PUT_LE_UINT24( pAddr, lOffset ); + } + } + } + /* no break; */ +#endif default: opcode = HB_P_LAST_PCODE; break; @@ -471,53 +589,6 @@ static HB_FIX_FUNC( hb_p_not ) return 1; } -static HB_FIX_FUNC( hb_p_duplicate ) -{ - HB_COMP_DECL = cargo->HB_COMP_PARAM; - - if( cargo->iNestedCodeblock == 0 && HB_COMP_ISSUPPORTED(HB_COMPFLAG_OPTJUMP) ) - { - switch( pFunc->pCode[ lPCodePos + 1 ] ) - { - case HB_P_JUMPTRUEFAR: - case HB_P_JUMPFALSEFAR: - if( pFunc->pCode[ lPCodePos + 5 ] == HB_P_POP ) - { - BYTE * pAddr = &pFunc->pCode[ lPCodePos + 2 ]; - LONG lOffset = HB_PCODE_MKINT24( pAddr ); - ULONG ulNewPos = lPCodePos + 1 + lOffset; - - if( lOffset > 0 && pFunc->pCode[ ulNewPos ] == HB_P_DUPLICATE ) - { - hb_p_duplicate( pFunc, ulNewPos, cargo ); - if( pFunc->pCode[ ulNewPos ] == HB_P_NOOP ) - { - ulNewPos++; - lOffset++; - } - } - - if( ( pFunc->pCode[ ulNewPos ] == HB_P_JUMPTRUEFAR || - pFunc->pCode[ ulNewPos ] == HB_P_JUMPFALSEFAR ) && - !hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 1 ) && - !hb_compIsJump( cargo->HB_COMP_PARAM, pFunc, lPCodePos + 5 ) ) - { - if( pFunc->pCode[ ulNewPos ] == pFunc->pCode[ lPCodePos + 1 ] ) - lOffset += HB_PCODE_MKINT24( &pFunc->pCode[ ulNewPos + 1 ] ); - else - lOffset += 4; - - HB_PUT_LE_UINT24( pAddr, lOffset ); - hb_compNOOPfill( pFunc, lPCodePos, 1, FALSE, FALSE ); - hb_compNOOPfill( pFunc, lPCodePos + 5, 1, FALSE, FALSE ); - } - } - break; - } - } - return 1; -} - static HB_FIX_FUNC( hb_p_jumpfar ) { HB_COMP_DECL = cargo->HB_COMP_PARAM; diff --git a/harbour/source/compiler/hbfunchk.c b/harbour/source/compiler/hbfunchk.c index 466a4c0a2d..b021e68054 100644 --- a/harbour/source/compiler/hbfunchk.c +++ b/harbour/source/compiler/hbfunchk.c @@ -28,7 +28,7 @@ #include "hbcomp.h" -/* NOTE: iMinParam = -1, means no checking +/* NOTE: iMinParam = -1, means no lower limit * iMaxParam = -1, means no upper limit */ @@ -37,8 +37,11 @@ typedef struct char * cFuncName; /* function name */ int iMinParam; /* min no of parms it needs */ int iMaxParam; /* max no of parms need */ -} HB_FUNCINFO, * HB_PFUNCINFO; +} HB_FUNCINFO, * PHB_FUNCINFO; + +/* NOTE: THIS TABLE MUST BE SORTED ALPHABETICALLY + */ static HB_FUNCINFO hb_StdFunc[] = { { "AADD" , 2, 2 }, @@ -111,56 +114,64 @@ static HB_FUNCINFO hb_StdFunc[] = { "VAL" , 1, 1 }, { "VALTYPE" , 1, 1 }, { "WORD" , 1, 1 }, - { "YEAR" , 1, 1 }, - { 0 , 0, 0 } + { "YEAR" , 1, 1 } }; +#define HB_STD_FUNCOUNT sizeof( hb_StdFunc ) / sizeof( HB_FUNCINFO ) + BOOL hb_compFunCallCheck( HB_COMP_DECL, char * szFuncCall, int iArgs ) { - HB_FUNCINFO * f = hb_StdFunc; - int i = 0; - int iPos = -1; - int iCmp; + unsigned int uiFirst = 0, uiLast = HB_STD_FUNCOUNT - 1, uiMiddle; + int iLen = ( int ) strlen( szFuncCall ), iCmp; - while( f[ i ].cFuncName ) + /* Respect 4 or more letters shortcuts + * SECO() is not allowed because of Clipper function SECONDS() + * however SECO32() is a valid name. + */ + if( iLen < 4 ) + iLen = 4; + do { - iCmp = strncmp( szFuncCall, f[ i ].cFuncName, 4 ); - if( iCmp == 0 ) - iCmp = strncmp( szFuncCall, f[ i ].cFuncName, strlen( szFuncCall ) ); - if( iCmp == 0 ) - { - iPos = i; - break; - } + uiMiddle = ( uiFirst + uiLast ) >> 1; + iCmp = strncmp( szFuncCall, hb_StdFunc[ uiMiddle ].cFuncName, iLen ); + if( iCmp <= 0 ) + uiLast = uiMiddle; else - ++i; + uiFirst = uiMiddle + 1; } + while( uiFirst < uiLast ); - if( iPos >= 0 && ( f[ iPos ].iMinParam != -1 ) ) + if( uiFirst != uiMiddle ) + iCmp = strncmp( szFuncCall, hb_StdFunc[ uiFirst ].cFuncName, iLen ); + + if( iCmp == 0 ) { - if( iArgs < f[ iPos ].iMinParam || ( f[ iPos ].iMaxParam != -1 && iArgs > f[ iPos ].iMaxParam ) ) - { - if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_HARBOUR ) ) - { - char szMsg[ 40 ]; + PHB_FUNCINFO pFunc = &hb_StdFunc[ uiFirst ]; - if( f[ iPos ].iMaxParam == -1 ) - snprintf( szMsg, sizeof( szMsg ), "\nPassed: %i, expected: at least %i", iArgs, f[ iPos ].iMinParam ); - else if( f[ iPos ].iMinParam == f[ iPos ].iMaxParam ) - snprintf( szMsg, sizeof( szMsg ), "\nPassed: %i, expected: %i", iArgs, f[ iPos ].iMinParam ); + if( ( pFunc->iMinParam != -1 && iArgs < pFunc->iMinParam ) || + ( pFunc->iMaxParam != -1 && iArgs > pFunc->iMaxParam ) ) + { + char szMsg[ 64 ]; + + if( HB_COMP_ISSUPPORTED( HB_COMPFLAG_HARBOUR ) ) + { + if( pFunc->iMinParam == pFunc->iMaxParam ) + snprintf( szMsg, sizeof( szMsg ), "\nPassed: %i, expected: %i", iArgs, pFunc->iMinParam ); + else if( pFunc->iMaxParam == -1 ) + snprintf( szMsg, sizeof( szMsg ), "\nPassed: %i, expected at least: %i", iArgs, pFunc->iMinParam ); + else if( pFunc->iMinParam == -1 ) + snprintf( szMsg, sizeof( szMsg ), "\nPassed: %i, expected less then: %i", iArgs, pFunc->iMaxParam ); + else + snprintf( szMsg, sizeof( szMsg ), "\nPassed: %i, expected from: %i to: %i", iArgs, pFunc->iMinParam, pFunc->iMaxParam ); + } else - snprintf( szMsg, sizeof( szMsg ), "\nPassed: %i, expected: %i - %i", iArgs, f[ iPos ].iMinParam, f[ iPos ].iMaxParam ); + szMsg[ 0 ] = '\0'; hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_CHECKING_ARGS, szFuncCall, szMsg ); + return FALSE; - } - else - { - /* Clipper way */ - hb_compGenError( HB_COMP_PARAM, hb_comp_szErrors, 'E', HB_COMP_ERR_CHECKING_ARGS, szFuncCall, NULL ); - return FALSE; - } - } + } } + return TRUE; } diff --git a/harbour/source/rtl/minmax.c b/harbour/source/rtl/minmax.c index b8f4f6ff21..c461520730 100644 --- a/harbour/source/rtl/minmax.c +++ b/harbour/source/rtl/minmax.c @@ -60,44 +60,50 @@ HB_FUNC( MAX ) PHB_ITEM p1 = hb_param( 1, HB_IT_ANY ); PHB_ITEM p2 = hb_param( 2, HB_IT_ANY ); - if( HB_IS_NUMINT( p1 ) && HB_IS_NUMINT( p2 ) ) + if( p1 && p2 ) { - HB_LONG l1 = hb_itemGetNInt( p1 ); - HB_LONG l2 = hb_itemGetNInt( p2 ); - - hb_retnint( l1 >= l2 ? l1 : l2 ); + if( HB_IS_NUMINT( p1 ) && HB_IS_NUMINT( p2 ) ) + { + HB_LONG l1 = hb_itemGetNInt( p1 ); + HB_LONG l2 = hb_itemGetNInt( p2 ); + + hb_retnint( l1 >= l2 ? l1 : l2 ); + return; + } + else if( HB_IS_NUMERIC( p1 ) && HB_IS_NUMERIC( p2 ) ) + { + double d1 = hb_itemGetND( p1 ); + double d2 = hb_itemGetND( p2 ); + + int iDec1; + int iDec2; + + hb_itemGetNLen( p1, NULL, &iDec1 ); + hb_itemGetNLen( p2, NULL, &iDec2 ); + + if( d1 >= d2 ) + hb_retndlen( d1, 0, iDec1 ); + else + hb_retndlen( d2, 0, iDec2 ); + return; + } + else if( HB_IS_LOGICAL( p1 ) && HB_IS_LOGICAL( p2 ) ) + { + BOOL b1 = hb_itemGetL( p1 ); + BOOL b2 = hb_itemGetL( p2 ); + + hb_retl( b1 >= b2 ? b1 : b2 ); + return; + } + else if( HB_IS_DATE( p1 ) && HB_IS_DATE( p2 ) ) + { + char szDate[ 9 ]; + + hb_retds( hb_itemGetDL( p1 ) >= hb_itemGetDL( p2 ) ? hb_pardsbuff( szDate, 1 ) : hb_pardsbuff( szDate, 2 ) ); + return; + } } - else if( HB_IS_NUMERIC( p1 ) && HB_IS_NUMERIC( p2 ) ) - { - double d1 = hb_itemGetND( p1 ); - double d2 = hb_itemGetND( p2 ); - - int iDec1; - int iDec2; - - hb_itemGetNLen( p1, NULL, &iDec1 ); - hb_itemGetNLen( p2, NULL, &iDec2 ); - - if( d1 >= d2 ) - hb_retndlen( d1, 0, iDec1 ); - else - hb_retndlen( d2, 0, iDec2 ); - } - else if( HB_IS_LOGICAL( p1 ) && HB_IS_LOGICAL( p2 ) ) - { - BOOL b1 = hb_itemGetL( p1 ); - BOOL b2 = hb_itemGetL( p2 ); - - hb_retl( b1 >= b2 ? b1 : b2 ); - } - else if( HB_IS_DATE( p1 ) && HB_IS_DATE( p2 ) ) - { - char szDate[ 9 ]; - - hb_retds( hb_itemGetDL( p1 ) >= hb_itemGetDL( p2 ) ? hb_pardsbuff( szDate, 1 ) : hb_pardsbuff( szDate, 2 ) ); - } - else - hb_errRT_BASE_SubstR( EG_ARG, 1093, NULL, "MAX", 2, hb_paramError( 1 ), hb_paramError( 2 ) ); + hb_errRT_BASE_SubstR( EG_ARG, 1093, NULL, "MAX", 2, hb_paramError( 1 ), hb_paramError( 2 ) ); } /* returns the minimum of two date or numerics */ @@ -106,43 +112,50 @@ HB_FUNC( MIN ) PHB_ITEM p1 = hb_param( 1, HB_IT_ANY ); PHB_ITEM p2 = hb_param( 2, HB_IT_ANY ); - if( HB_IS_NUMINT( p1 ) && HB_IS_NUMINT( p2 ) ) + if( p1 && p2 ) { - HB_LONG l1 = hb_itemGetNInt( p1 ); - HB_LONG l2 = hb_itemGetNInt( p2 ); - - hb_retnint( l1 <= l2 ? l1 : l2 ); + if( HB_IS_NUMINT( p1 ) && HB_IS_NUMINT( p2 ) ) + { + HB_LONG l1 = hb_itemGetNInt( p1 ); + HB_LONG l2 = hb_itemGetNInt( p2 ); + + hb_retnint( l1 <= l2 ? l1 : l2 ); + return; + } + else if( HB_IS_NUMERIC( p1 ) && HB_IS_NUMERIC( p2 ) ) + { + double d1 = hb_itemGetND( p1 ); + double d2 = hb_itemGetND( p2 ); + + int iDec1; + int iDec2; + + hb_itemGetNLen( p1, NULL, &iDec1 ); + hb_itemGetNLen( p2, NULL, &iDec2 ); + + if( d1 <= d2 ) + hb_retndlen( d1, 0, iDec1 ); + else + hb_retndlen( d2, 0, iDec2 ); + return; + } + else if( HB_IS_LOGICAL( p1 ) && HB_IS_LOGICAL( p2 ) ) + { + BOOL b1 = hb_itemGetL( p1 ); + BOOL b2 = hb_itemGetL( p2 ); + + hb_retl( b1 <= b2 ? b1 : b2 ); + return; + } + else if( HB_IS_DATE( p1 ) && HB_IS_DATE( p2 ) ) + { + char szDate[ 9 ]; + + hb_retds( hb_itemGetDL( p1 ) <= hb_itemGetDL( p2 ) ? hb_pardsbuff( szDate, 1 ) : hb_pardsbuff( szDate, 2 ) ); + return; + } } - else if( HB_IS_NUMERIC( p1 ) && HB_IS_NUMERIC( p2 ) ) - { - double d1 = hb_itemGetND( p1 ); - double d2 = hb_itemGetND( p2 ); - int iDec1; - int iDec2; - - hb_itemGetNLen( p1, NULL, &iDec1 ); - hb_itemGetNLen( p2, NULL, &iDec2 ); - - if( d1 <= d2 ) - hb_retndlen( d1, 0, iDec1 ); - else - hb_retndlen( d2, 0, iDec2 ); - } - else if( HB_IS_LOGICAL( p1 ) && HB_IS_LOGICAL( p2 ) ) - { - BOOL b1 = hb_itemGetL( p1 ); - BOOL b2 = hb_itemGetL( p2 ); - - hb_retl( b1 <= b2 ? b1 : b2 ); - } - else if( HB_IS_DATE( p1 ) && HB_IS_DATE( p2 ) ) - { - char szDate[ 9 ]; - - hb_retds( hb_itemGetDL( p1 ) <= hb_itemGetDL( p2 ) ? hb_pardsbuff( szDate, 1 ) : hb_pardsbuff( szDate, 2 ) ); - } - else - hb_errRT_BASE_SubstR( EG_ARG, 1092, NULL, "MIN", 2, hb_paramError( 1 ), hb_paramError( 2 ) ); + hb_errRT_BASE_SubstR( EG_ARG, 1092, NULL, "MIN", 2, hb_paramError( 1 ), hb_paramError( 2 ) ); } diff --git a/harbour/source/vm/itemapi.c b/harbour/source/vm/itemapi.c index b3e1b6a033..6ae1ce9a44 100644 --- a/harbour/source/vm/itemapi.c +++ b/harbour/source/vm/itemapi.c @@ -1615,7 +1615,8 @@ HB_EXPORT int hb_itemStrCmp( PHB_ITEM pFirst, PHB_ITEM pSecond, BOOL bForceExact if( ulMinLen ) { if( hb_cdp_page->lSort ) - iRet = hb_cdpcmp( szFirst,ulLenFirst,szSecond,ulLenSecond,hb_cdp_page,hb_set.HB_SET_EXACT || bForceExact ); + iRet = hb_cdpcmp( szFirst, ulLenFirst, szSecond, ulLenSecond, + hb_cdp_page, hb_set.HB_SET_EXACT || bForceExact ); else { do @@ -1630,11 +1631,11 @@ HB_EXPORT int hb_itemStrCmp( PHB_ITEM pFirst, PHB_ITEM pSecond, BOOL bForceExact } while( --ulMinLen ); - if( hb_set.HB_SET_EXACT || bForceExact || ulLenSecond > ulLenFirst ) + /* If equal and length is different ! */ + if( !iRet && ulLenFirst != ulLenSecond ) { - /* Force an exact comparison */ - if( !iRet && ulLenFirst != ulLenSecond ) - /* If length is different ! */ + /* Force an exact comparison? */ + if( hb_set.HB_SET_EXACT || bForceExact || ulLenSecond > ulLenFirst ) iRet = ( ulLenFirst < ulLenSecond ) ? -1 : 1; } }