diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 72ec7f4099..9f8edc9385 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,25 @@ +19991121-17:33 GMT+1 Victor Szel + * source/compiler/expropt.c + ! $ optimization fixed for strings containing Chr(0), now 4 more RTL_TESTs + pass. + ! "Fixed" CHR() to be bug compatible with Clipper for cases where param + % 256 = 0 but param != 0. + ! "Fixed" $ to be bug compatible with Clipper when an empty string is + searched in a string. + * tests/rtl_test.prg (not yet committed) + + Some failing VAL() tests added. + ! Corrected result for compiler optimized AT(), CHR() and $ operations. + They now test for bug compatibility. + + source/common/hbstr.c (added) + source/common/Makefile + source/rtl/strings.c + * hb_strAt() moved to the common library. + ! WARNING ! Please modify non-GNU make systems. + * source/vm/hvm.c + % Minor optimization in hb_vmInString() + * source/pp/* + ! Fixed some mistyped #undef statements related to tracing. + 19991121-16:10 GMT+1 Bruno Cantero * include/rddapi.h source/rdd/dbcmd.c diff --git a/harbour/source/common/Makefile b/harbour/source/common/Makefile index a78deded89..6dadb34c7d 100644 --- a/harbour/source/common/Makefile +++ b/harbour/source/common/Makefile @@ -6,6 +6,7 @@ ROOT = ../../ C_SOURCES=\ hbfsapi.c \ + hbstr.c \ hbtrace.c \ PRG_SOURCES=\ diff --git a/harbour/source/common/hbstr.c b/harbour/source/common/hbstr.c new file mode 100644 index 0000000000..cb3fbb5206 --- /dev/null +++ b/harbour/source/common/hbstr.c @@ -0,0 +1,63 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * Harbour common string functions (accessed from standalone utilities and the RTL) + * + * Copyright 1999 Victor Szel + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version, with one exception: + * + * The exception is that if you link the Harbour Runtime Library (HRL) + * and/or the Harbour Virtual Machine (HVM) with other files to produce + * an executable, this does not by itself cause the resulting executable + * to be covered by the GNU General Public License. Your use of that + * executable is in no way restricted on account of linking the HRL + * and/or HVM code into it. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit + * their web site at http://www.gnu.org/). + * + */ + +#include "extend.h" + +ULONG hb_strAt( const char * szSub, ULONG ulSubLen, const char * szText, ULONG ulLen ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_strAt(%s, %lu, %s, %lu)", szSub, ulSubLen, szText, ulLen)); + + if( ulSubLen > 0 && ulLen >= ulSubLen ) + { + ULONG ulPos = 0, ulSubPos = 0; + + while( ulPos < ulLen && ulSubPos < ulSubLen ) + { + if( *( szText + ulPos ) == *( szSub + ulSubPos ) ) + { + ulSubPos++; + ulPos++; + } + else if( ulSubPos ) + ulSubPos = 0; + else + ulPos++; + } + return ( ulSubPos < ulSubLen ) ? 0 : ( ulPos - ulSubLen + 1 ); + } + else + return 0; +} + diff --git a/harbour/source/compiler/expropt.c b/harbour/source/compiler/expropt.c index a8801c6c93..4da75515ed 100644 --- a/harbour/source/compiler/expropt.c +++ b/harbour/source/compiler/expropt.c @@ -592,6 +592,11 @@ HB_EXPR_PTR hb_compExprNewFunCall( char *szFunName, HB_EXPR_PTR pParms ) hb_compFunCallCheck( szFunName, iCount ); + /* TODO: AT() (also done by Clipper, already mentioned) + LEN() (also done by Clipper) + ASC() (not done by Clipper) + EMPTY() (not done by Clipper) */ + if( ( strcmp( "CHR", szFunName ) == 0 ) && iCount ) { /* try to change it into a string */ @@ -599,15 +604,36 @@ HB_EXPR_PTR hb_compExprNewFunCall( char *szFunName, HB_EXPR_PTR pParms ) if( pArg->ExprType == HB_ET_NUMERIC ) { + /* NOTE: CA-Cl*pper's compiler optimizer will be wrong for those + CHR() cases where the passed parameter is a constant which + can be divided by 256 but it's not zero, in this case it + will return an empty string instead of a Chr(0). [vszel] */ + pExpr = hb_compExprNew( HB_ET_STRING ); - pExpr->ulLength = 1; - pExpr->ValType = HB_EV_STRING; - pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); + pExpr->ValType = HB_EV_STRING; if( pArg->value.asNum.NumType == HB_ET_LONG ) - pExpr->value.asString[ 0 ] = ( pArg->value.asNum.lVal % 256 ); + { + if( ( pArg->value.asNum.lVal % 256 ) == 0 && pArg->value.asNum.lVal != 0 ) + { + pExpr->value.asString = ( char * ) HB_XGRAB( 1 ); + pExpr->value.asString[ 0 ] = '\0'; + pExpr->ulLength = 0; + } + else + { + pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); + pExpr->value.asString[ 0 ] = ( pArg->value.asNum.lVal % 256 ); + pExpr->value.asString[ 1 ] = '\0'; + pExpr->ulLength = 1; + } + } else - pExpr->value.asString[ 0 ] = ( (long) pArg->value.asNum.dVal % 256 ); - pExpr->value.asString[ 1 ] = '\x0'; + { + pExpr->value.asString = ( char * ) HB_XGRAB( 2 ); + pExpr->value.asString[ 0 ] = ( ( long ) pArg->value.asNum.dVal % 256 ); + pExpr->value.asString[ 1 ] = '\0'; + pExpr->ulLength = 1; + } hb_compExprDelete( pParms ); } } @@ -4003,7 +4029,15 @@ static HB_EXPR_FUNC( hb_compExprUseIN ) */ BOOL bResult; - bResult = ( strstr( pSelf->value.asOperator.pRight->value.asString, pSelf->value.asOperator.pLeft->value.asString ) != NULL ); + /* NOTE: CA-Cl*pper has a bug where the $ operator returns .T. + when an empty string is searched [vszel] */ + + if( pSelf->value.asOperator.pLeft->ulLength == 0 ) + bResult = TRUE; + else + bResult = ( hb_strAt( pSelf->value.asOperator.pLeft->value.asString, pSelf->value.asOperator.pLeft->ulLength, + pSelf->value.asOperator.pRight->value.asString, pSelf->value.asOperator.pRight->ulLength ) != 0 ); + /* NOTE: * "" $ "XXX" = .T. * "" $ "" = .T. diff --git a/harbour/source/pp/hbppint.c b/harbour/source/pp/hbppint.c index 9bd8726895..dc678c3f9e 100644 --- a/harbour/source/pp/hbppint.c +++ b/harbour/source/pp/hbppint.c @@ -38,7 +38,7 @@ */ #if ! defined(HB_TRACE_UTILS) #if defined(HB_TRACE_LEVEL) -#undef HB_TRACE_LEVEL) +#undef HB_TRACE_LEVEL #endif #endif diff --git a/harbour/source/pp/hbpplib.c b/harbour/source/pp/hbpplib.c index 358a7a769c..8988e43221 100644 --- a/harbour/source/pp/hbpplib.c +++ b/harbour/source/pp/hbpplib.c @@ -38,7 +38,7 @@ */ #if ! defined(HB_TRACE_UTILS) #if defined(HB_TRACE_LEVEL) -#undef HB_TRACE_LEVEL) +#undef HB_TRACE_LEVEL #endif #endif diff --git a/harbour/source/pp/stdalone/hbpp.c b/harbour/source/pp/stdalone/hbpp.c index d9afba73a1..8a580a93e0 100644 --- a/harbour/source/pp/stdalone/hbpp.c +++ b/harbour/source/pp/stdalone/hbpp.c @@ -38,7 +38,7 @@ */ #if ! defined(HB_TRACE_UTILS) #if defined(HB_TRACE_LEVEL) -#undef HB_TRACE_LEVEL) +#undef HB_TRACE_LEVEL #endif #endif diff --git a/harbour/source/pp/table.c b/harbour/source/pp/table.c index 739debafed..3f21848485 100644 --- a/harbour/source/pp/table.c +++ b/harbour/source/pp/table.c @@ -38,7 +38,7 @@ */ #if ! defined(HB_TRACE_UTILS) #if defined(HB_TRACE_LEVEL) -#undef HB_TRACE_LEVEL) +#undef HB_TRACE_LEVEL #endif #endif diff --git a/harbour/source/rtl/strings.c b/harbour/source/rtl/strings.c index 5a05f97262..06848862e1 100644 --- a/harbour/source/rtl/strings.c +++ b/harbour/source/rtl/strings.c @@ -535,32 +535,6 @@ HARBOUR HB_PADC( void ) hb_retc( "" ); } -ULONG hb_strAt( const char * szSub, ULONG ulSubLen, const char * szText, ULONG ulLen ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_strAt(%s, %lu, %s, %lu)", szSub, ulSubLen, szText, ulLen)); - - if( ulSubLen > 0 && ulLen >= ulSubLen ) - { - ULONG ulPos = 0, ulSubPos = 0; - - while( ulPos < ulLen && ulSubPos < ulSubLen ) - { - if( *( szText + ulPos ) == *( szSub + ulSubPos ) ) - { - ulSubPos++; - ulPos++; - } - else if( ulSubPos ) - ulSubPos = 0; - else - ulPos++; - } - return ( ulSubPos < ulSubLen ) ? 0 : ( ulPos - ulSubLen + 1 ); - } - else - return 0; -} - /* locates a substring in a string */ /* TEST: QOUT( "at( 'cde', 'abcdefgfedcba' ) = '" + at( 'cde', 'abcsefgfedcba' ) + "'" ) */ HARBOUR HB_AT( void ) diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index e5d19e3eaa..e80294013e 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -1794,11 +1794,11 @@ static void hb_vmInstring( void ) pItem2 = hb_stack.pPos - 1; if( IS_STRING( pItem1 ) && IS_STRING( pItem2 ) ) { - int iResult = hb_strAt( pItem1->item.asString.value, pItem1->item.asString.length, - pItem2->item.asString.value, pItem2->item.asString.length ); + BOOL bResult = ( hb_strAt( pItem1->item.asString.value, pItem1->item.asString.length, + pItem2->item.asString.value, pItem2->item.asString.length ) != 0 ); hb_stackPop(); hb_stackPop(); - hb_vmPushLogical( iResult == 0 ? FALSE : TRUE ); + hb_vmPushLogical( bResult ); } else if( IS_OBJECT( pItem1 ) && hb_objHasMsg( pItem1, "$" ) ) hb_vmOperatorCall( pItem1, pItem2, "$" );