diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 7ead900b28..ebb691d9e3 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,16 @@ +20000329-16:33 GMT+1 Victor Szakats + + * include/hbapi.h + * source/rtl/val.c + * source/rtl/ampm.c + * source/rtl/sample.c + ! hb_strVal() and VAL() made completely CA-Cl*pper compatible. + Now 21 less test failures in HBTEST. atof() is no longer used. + + * utils/hbtest/rt_str.prg + * utils/hbtest/rt_math.prg + + Added some VAL() related tests. + 20000328-23:04 GMT+1 Victor Szakats * config/dos/global.cf diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index cd831f2dce..094294c97e 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -363,7 +363,7 @@ extern ULONG hb_strAt( const char * szSub, ULONG ulSubLen, const char * szTex extern char * hb_strUpper( char * szText, ULONG ulLen ); extern char * hb_strLower( char * szText, ULONG ulLen ); extern char * hb_strncpyUpper( char * pDest, const char * pSource, ULONG ulLen ); -extern double hb_strVal( const char * szText ); +extern double hb_strVal( const char * szText, ULONG ulLen ); extern char * hb_strLTrim( const char * szText, ULONG * ulLen ); extern ULONG hb_strRTrimLen( const char * szText, ULONG ulLen, BOOL bAnySpace ); diff --git a/harbour/source/rtl/ampm.c b/harbour/source/rtl/ampm.c index 4beb6d1a79..c8ac2ceb0c 100644 --- a/harbour/source/rtl/ampm.c +++ b/harbour/source/rtl/ampm.c @@ -40,7 +40,7 @@ HB_FUNC( AMPM ) char * pszTime = hb_parc( 1 ); ULONG ulTimeLen = hb_parclen( 1 ); char * pszResult = ( char * ) hb_xgrab( HB_MAX( ulTimeLen, 2 ) + 3 + 1 ); - USHORT uiHour = ( USHORT ) hb_strVal( pszTime ); + USHORT uiHour = ( USHORT ) hb_strVal( pszTime, ulTimeLen ); BOOL bAM; memset( pszResult, '\0', 3 ); diff --git a/harbour/source/rtl/samples.c b/harbour/source/rtl/samples.c index dd3008db5e..98e1135f03 100644 --- a/harbour/source/rtl/samples.c +++ b/harbour/source/rtl/samples.c @@ -69,13 +69,13 @@ static ULONG hb_TimeStrToSec( char * pszTime ) ulLen = strlen( pszTime ); if( ulLen >= 1 ) - ulTime += ( ULONG ) hb_strVal( pszTime ) * 3600; + ulTime += ( ULONG ) hb_strVal( pszTime, ulLen ) * 3600; if( ulLen >= 4 ) - ulTime += ( ULONG ) hb_strVal( pszTime + 3 ) * 60; + ulTime += ( ULONG ) hb_strVal( pszTime + 3, ulLen - 3 ) * 60; if( ulLen >= 7 ) - ulTime += ( ULONG ) hb_strVal( pszTime + 6 ); + ulTime += ( ULONG ) hb_strVal( pszTime + 6, ulLen - 6 ); return ulTime; } diff --git a/harbour/source/rtl/val.c b/harbour/source/rtl/val.c index 27c06c6dab..908fb8e11e 100644 --- a/harbour/source/rtl/val.c +++ b/harbour/source/rtl/val.c @@ -6,7 +6,7 @@ * Harbour Project source code: * VAL() function * - * Copyright 1999 Antonio Linares + * Copyright 1999 Victor Szakats * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify @@ -33,16 +33,61 @@ * */ +#include + #include "hbapi.h" #include "hbapiitm.h" #include "hbapierr.h" -/* returns the numeric value of a character string representation of a number */ -double hb_strVal( const char * szText ) +/* returns the numeric value of a character string representation of a number */ +double hb_strVal( const char * szText, ULONG ulLen ) { - HB_TRACE(HB_TR_DEBUG, ("hb_strVal(%s)", szText)); + double dValue = 0.0; + ULONG ulPos; + ULONG ulDecPos = 0; + BOOL bNegative = FALSE; - return atof( szText ); + HB_TRACE(HB_TR_DEBUG, ("hb_strVal(%s, %d)", szText, ulLen)); + + /* Look for sign */ + + for( ulPos = 0; ulPos < ulLen; ulPos++ ) + { + if( szText[ ulPos ] == '-' ) + { + bNegative = TRUE; + ulPos++; + break; + } + else if( szText[ ulPos ] == '+' ) + { + ulPos++; + break; + } + else if( ! HB_ISSPACE( szText[ ulPos ] ) ) + break; + } + + /* Build the number */ + + for(; ulPos < ulLen; ulPos++ ) + { + if( szText[ ulPos ] == '.' && ulDecPos == 0 ) + { + ulDecPos++; + } + else if( szText[ ulPos ] >= '0' && szText[ ulPos ] <= '9' ) + { + if( ulDecPos ) + dValue += ( ( double ) ( szText[ ulPos ] - '0' ) ) / pow( 10.0, ( double ) ulDecPos++ ); + else + dValue = ( dValue * 10 ) + ( ( double ) ( szText[ ulPos ] - '0' ) ); + } + else + break; + } + + return bNegative && dValue != 0.0 ? -dValue : dValue; } /* returns the numeric value of a character string representation of a number */ @@ -52,22 +97,29 @@ HB_FUNC( VAL ) if( pText ) { - int iWidth; + char * szText = hb_itemGetCPtr( pText ); + int iWidth = ( int ) hb_itemGetCLen( pText ); int iDec; - char * ptr = strchr( hb_itemGetCPtr( pText ), '.' ); + double dValue = hb_strVal( szText, hb_itemGetCLen( pText ) ); - if( ptr ) - { - iWidth = ptr - hb_itemGetCPtr( pText ); - iDec = strlen( ptr + 1 ); - } + for( iDec = 0; iDec < iWidth && szText[ iDec ] != '.'; iDec++ ); + + if( iDec >= iWidth - 1 ) + hb_retnlen( dValue, iWidth, 0 ); else { - iWidth = strlen( hb_itemGetCPtr( pText ) ); - iDec = 0; - } + /* NOTE: Kludge Warning! This condition: + "|| ( iDec == 1 && szText[ 0 ] == '-' && dValue != 0.0 )" + may not be the generic way to handle the width of this "-.1" + string. I could not find a matching case which + fails for the same reason, nor a better way to handle it. + The problem is that in this case only, the width is + calculated upon conditions which can only be discovered by + parsing the string, but the parsing is made by a lower level + generic function. [vszakats] */ - hb_retndlen( hb_strVal( hb_itemGetCPtr( pText ) ), iWidth, iDec ); + hb_retnlen( dValue, iDec + ( iDec == 0 || ( iDec == 1 && szText[ 0 ] == '-' && dValue != 0.0 ) ? 1 : 0 ), iWidth - iDec - 1 ); + } } else { @@ -80,4 +132,3 @@ HB_FUNC( VAL ) } } } - diff --git a/harbour/utils/hbtest/rt_math.prg b/harbour/utils/hbtest/rt_math.prg index 9fd4ab4c1b..4625dde747 100644 --- a/harbour/utils/hbtest/rt_math.prg +++ b/harbour/utils/hbtest/rt_math.prg @@ -77,8 +77,19 @@ FUNCTION Main_MATH() #endif TEST_LINE( Abs(Month(sdDate)) , 3 ) TEST_LINE( Abs(-Month(sdDate)) , 3 ) + TEST_LINE( Str(Abs(Year(sdDateE))) , " 0" ) + TEST_LINE( Str(Abs(-Year(sdDateE))) , " 0" ) + TEST_LINE( Str(Abs(Year(sdDate))) , " 1984" ) + TEST_LINE( Str(Abs(-Year(sdDate))) , " 1984" ) TEST_LINE( Str(Abs(Month(sdDate))) , " 3" ) TEST_LINE( Str(Abs(-Month(sdDate))) , " 3" ) + TEST_LINE( Str(Abs(0)) , " 0" ) + TEST_LINE( Str(Abs(0.0)) , " 0.0" ) + TEST_LINE( Str(Abs(-0)) , " 0" ) + TEST_LINE( Str(Abs(150)) , " 150" ) + TEST_LINE( Str(Abs(-150)) , " 150" ) + TEST_LINE( Str(Abs(150.245)) , " 150.245" ) + TEST_LINE( Str(Abs(-150.245)) , " 150.245" ) TEST_LINE( Str(Abs(Val("0"))) , "0" ) TEST_LINE( Str(Abs(Val("-0"))) , " 0" ) TEST_LINE( Str(Abs(Val("150"))) , "150" ) diff --git a/harbour/utils/hbtest/rt_str.prg b/harbour/utils/hbtest/rt_str.prg index 50c0a8a19f..8470969c56 100644 --- a/harbour/utils/hbtest/rt_str.prg +++ b/harbour/utils/hbtest/rt_str.prg @@ -46,13 +46,30 @@ FUNCTION Main_STR() TEST_LINE( Val( 10 ) , "E BASE 1098 Argument error VAL F:S" ) TEST_LINE( Str(Val("")) , " 0" ) + TEST_LINE( Str(Val(" ")) , "0" ) + TEST_LINE( Str(Val("-")) , "0" ) + TEST_LINE( Str(Val("+")) , "0" ) + TEST_LINE( Str(Val("-+")) , " 0" ) + TEST_LINE( Str(Val("+-")) , " 0" ) TEST_LINE( Str(Val(".")) , "0" ) TEST_LINE( Str(Val("..")) , "0.0" ) + TEST_LINE( Str(Val("-.")) , " 0" ) + TEST_LINE( Str(Val("-..")) , "0.0" ) TEST_LINE( Str(Val("1.")) , " 1" ) TEST_LINE( Str(Val("1..")) , "1.0" ) TEST_LINE( Str(Val("1...")) , "1.00" ) + TEST_LINE( Str(Val("-1.")) , " -1" ) + TEST_LINE( Str(Val(" -1.")) , " -1" ) + TEST_LINE( Str(Val(" --1.")) , " 0" ) + TEST_LINE( Str(Val("-1..")) , "-1.0" ) + TEST_LINE( Str(Val("-1...")) , "-1.00" ) TEST_LINE( Str(Val(".1")) , "0.1" ) TEST_LINE( Str(Val("-.1")) , "-0.1" ) + TEST_LINE( Str(Val("-.0")) , "0.0" ) + TEST_LINE( Str(Val(" -.1")) , "-0.1" ) + TEST_LINE( Str(Val(" --.1")) , " 0.0" ) + TEST_LINE( Str(Val("+.1")) , "0.1" ) + TEST_LINE( Str(Val(" .1")) , "0.1" ) TEST_LINE( Str(Val("- .1")) , " 0.0" ) TEST_LINE( Str(Val("+.1")) , "0.1" ) TEST_LINE( Str(Val("- 12")) , " 0" ) @@ -63,11 +80,25 @@ FUNCTION Main_STR() TEST_LINE( Str(Val(" 12 -")) , " 12" ) TEST_LINE( Str(Val(" 13.1.9")) , " 13.100" ) TEST_LINE( Str(Val(" 12")) , " 12" ) + TEST_LINE( Str(Val(" 12"+Chr(0)+"0")) , " 12" ) + TEST_LINE( Str(Val(" 12.1"+Chr(0)+"2")) , " 12.100" ) + TEST_LINE( Str(Val(" 12"+Chr(0)+".2")) , " 12.0" ) + TEST_LINE( Str(Val(" 12.0")) , " 12.0" ) + TEST_LINE( Str(Val(" 12. 0")) , " 12.00" ) + TEST_LINE( Str(Val(" 12 .0")) , " 12.0" ) + TEST_LINE( Str(Val(" 12. 00")) , " 12.000" ) + TEST_LINE( Str(Val(" 12 .00")) , " 12.00" ) + TEST_LINE( Str(Val(" 12. 1")) , " 12.00" ) + TEST_LINE( Str(Val(" 12 .1")) , " 12.0" ) + TEST_LINE( Str(Val(" 12. 10")) , " 12.000" ) + TEST_LINE( Str(Val(" 12 .10")) , " 12.00" ) TEST_LINE( Str(Val("+ 12")) , " 0" ) TEST_LINE( Str(Val(" + 12")) , " 0" ) TEST_LINE( Str(Val(" +12")) , " 12" ) TEST_LINE( Str(Val("+++12")) , " 0" ) TEST_LINE( Str(Val(Chr(9)+"12")) , " 12" ) + TEST_LINE( Str(Val(Chr(10)+"12")) , " 12" ) + TEST_LINE( Str(Val(Chr(13)+"12")) , " 12" ) TEST_LINE( Str(Val("1E2")) , " 1" ) TEST_LINE( Str(Val("+INF")) , " 0" ) TEST_LINE( Str(Val("-INF")) , " 0" )