(I forgot some fix in wcstod) Changelog: /home/wine/wine/dlls/msvcrt/wcs.c, string.c, test/string.c: Fix wcstod, implement strtod and atof on top of an adapted copy of wcsto(l)d. Add tests for atof and strtod. This supercedes the patch adding atof todo_wines. Maybe strtod should be implemented by translating the string to a wide string and calling wcstod. Few other msvcrt ascii functions however use MultiByteToWideChar and call the wcs counterpart...
-- Uwe Bonnes [EMAIL PROTECTED] Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt --------- Tel. 06151 162516 -------- Fax. 06151 164321 ---------- Index: wine/dlls/msvcrt/wcs.c =================================================================== RCS file: /home/wine/wine/dlls/msvcrt/wcs.c,v retrieving revision 1.35 diff -u -r1.35 wcs.c --- wine/dlls/msvcrt/wcs.c 14 Jan 2006 17:00:58 -0000 1.35 +++ wine/dlls/msvcrt/wcs.c 22 Jan 2006 23:35:23 -0000 @@ -108,13 +108,13 @@ } /********************************************************************* - * wcstod (MSVCRT.@) + * wcstold (internal) */ -double MSVCRT_wcstod(const MSVCRT_wchar_t* lpszStr, MSVCRT_wchar_t** end) +long double MSVCRT_wcstold(const MSVCRT_wchar_t* lpszStr, MSVCRT_wchar_t** end) { const MSVCRT_wchar_t* str = lpszStr; int negative = 0; - double ret = 0, divisor = 10.0; + long double ret = 0L, divisor = 1L; TRACE("(%s,%p) semi-stub\n", debugstr_w(lpszStr), end); @@ -134,27 +134,32 @@ while (isdigitW(*str)) { - ret = ret * 10.0 + (*str - '0'); + ret = ret * 10L + (*str - '0'); str++; } if (*str == '.') str++; while (isdigitW(*str)) { - ret = ret + (*str - '0') / divisor; - divisor *= 10; + ret = ret + (*str - '0'); + divisor *= 10L; str++; } + ret /= divisor; if (*str == 'E' || *str == 'e' || *str == 'D' || *str == 'd') { int negativeExponent = 0; int exponent = 0; - if (*(++str) == '-') + str++; + if (*str == '-') { negativeExponent = 1; str++; } + else + if (*str == '+') + str++; while (isdigitW(*str)) { exponent = exponent * 10 + (*str - '0'); @@ -163,9 +168,9 @@ if (exponent != 0) { if (negativeExponent) - ret = ret / pow(10.0, exponent); + ret = ret / powl(10L, exponent); else - ret = ret * pow(10.0, exponent); + ret = ret * powl(10L, exponent); } } @@ -175,10 +180,16 @@ if (end) *end = (MSVCRT_wchar_t*)str; - TRACE("returning %g\n", ret); + TRACE("returning %Lg\n", ret); return ret; } - +/********************************************************************* + * wcstod (MSVCRT.@) + */ +double MSVCRT_wcstod(const MSVCRT_wchar_t* lpszStr, MSVCRT_wchar_t** end) +{ + return (double) MSVCRT_wcstold(lpszStr, end); +} typedef struct pf_output_t { Index: wine/dlls/msvcrt/string.c =================================================================== RCS file: /home/wine/wine/dlls/msvcrt/string.c,v retrieving revision 1.15 diff -u -r1.15 string.c --- wine/dlls/msvcrt/string.c 14 Jan 2006 17:01:19 -0000 1.15 +++ wine/dlls/msvcrt/string.c 22 Jan 2006 23:35:23 -0000 @@ -22,6 +22,7 @@ */ #include <stdlib.h> +#include <math.h> #include "msvcrt.h" #include "wine/debug.h" @@ -138,19 +139,104 @@ } /********************************************************************* - * atof (MSVCRT.@) + * strtold (internal) */ -double MSVCRT_atof( const char *str ) +long double MSVCRT_strtold( const char *lpszStr, char **end ) { - return atof( str ); + const char* str = lpszStr; + int negative = 0; + long double ret = 0L, divisor = 1L; + + TRACE("(%s,%p) semi-stub\n", debugstr_a(lpszStr), end); + + /* FIXME: + * - Should set errno on failure + * - Should fail on overflow + * - Need to check which input formats are allowed + */ + while (isspace(*str)) + str++; + + if (*str == '-') + { + negative = 1; + str++; + } + + while (isdigit(*str)) + { + ret = ret * 10L + (*str - '0'); + str++; + } + if (*str == '.') + str++; + while (isdigit(*str)) + { + ret = ret*10L + (*str - '0'); + divisor *= 10L; + str++; + } + + ret /= divisor; + if (*str == 'E' || *str == 'e' || *str == 'D' || *str == 'd') + { + int negativeExponent = 0; + int exponent = 0; + str++; + if (*str == '-') + { + negativeExponent = 1; + str++; + } + else + if (*str == '+') + str++; + while (isdigit(*str)) + { + exponent = exponent * 10 + (*str - '0'); + str++; + } + if (exponent != 0) + { + if (negativeExponent) + ret = ret / powl(10L, exponent); + else + ret = ret * powl(10L, exponent); + } + } + + if (negative) + ret = -ret; + + if (end) + *end = (char*)str; + + TRACE("returning %Lg\n", ret); + return ret; +} + +/********************************************************************* + * strtold (MSVCRT.@) + */ +double MSVCRT_strtod( const char *lpszStr, char **end ) +{ + return (double) MSVCRT_strtold(lpszStr, end); } /********************************************************************* - * strtod (MSVCRT.@) + * atold (MSVCRT.@) */ -double MSVCRT_strtod( const char *str, char **end ) +double MSVCRT_atold( const char *lpszStr) +{ + return MSVCRT_strtold(lpszStr, NULL); +} + +/********************************************************************* + * atof (MSVCRT.@) + */ +double MSVCRT_atof( const char *str ) { - return strtod( str, end ); + return (double) MSVCRT_strtold(str, NULL); } /********************************************************************* Index: wine/dlls/msvcrt/tests/string.c =================================================================== RCS file: /home/wine/wine/dlls/msvcrt/tests/string.c,v retrieving revision 1.6 diff -u -r1.6 string.c --- wine/dlls/msvcrt/tests/string.c 21 Nov 2005 12:03:18 -0000 1.6 +++ wine/dlls/msvcrt/tests/string.c 22 Jan 2006 23:35:23 -0000 @@ -27,6 +27,8 @@ static void* (*pmemcpy)(void *, const void *, size_t n); static int* (*pmemcmp)(void *, const void *, size_t n); +static double (*patof)(const char *); +static double (*pstrtod)(const char *, char ** ); #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y) #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y) @@ -99,6 +101,78 @@ ok( ret==0, "_mbsspn returns %d should be 0\n", ret); } +static void test_atof( void) +{ + char s1[]=" -2309.12E-15"; + char s2[]="7.8912654773d10"; + char s3[]="7.8912654773d210"; + char s4[]=" -9885 pigs"; + char s5[]="98854 dollars"; + char s6[]="7.8912654773d+210"; + double x; + + x = patof( s1 ); + ok(x==-2.309120e-012, "atof(%s) returned %e\n", s1, x ); + + x = patof( s2 ); + ok(x==7.8912654773e10, "atof(%s) returned %2.20e\n", s2, x ); + + x = patof( s3 ); + ok(x==7.8912654773e210, "atof(%s) returned %2.20e\n", s3, x ); + + x = patof( s4 ); + ok(x==-9.885000e+003, "atof(%s) returned %e\n", s4, x ); + + x = patof( s5 ); + ok(x==9.885400e+004, "atof(%s) returned %e\n", s5, x ); + + x = patof( s6 ); + ok(x==7.8912654773e+210, "atof(%s) returned %e\n", s6, x ); + +} + +static void test_strtod( void) +{ + char s1[]=" -2309.12E-15"; + char s2[]="7.8912654773d10"; + char s3[]="7.8912654773d210"; + char s4[]=" -9885 pigs"; + char s5[]="98854 dollars"; + char s6[]="7.8912654773d+210"; + char s7[]="\t7.8912654773d+210"; + char *end; + double x; + + x = pstrtod( s1, &end); + ok(x==-2.309120e-012, "strtod(%s) returned %e\n", s1, x ); + ok(*end == 0, "strtod(%s) unexpected end %s\n", s1, end); + + x = pstrtod( s2, &end ); + ok(x==7.8912654773e10, "strtod(%s) returned %2.20e\n", s2, x ); + ok(*end == 0, "strtod(%s) unexpected end %s\n", s2, end); + + x = pstrtod( s3, &end ); + ok(x==7.8912654773e210, "strtod(%s) returned %2.20e\n", s3, x ); + ok(*end == 0, "strtod(%s) unexpected end %s\n", s3, end); + + x = pstrtod( s4, &end ); + ok(x==-9.885000e+003, "strtod(%s) returned %e\n", s4, x ); + ok(strcmp(end," pigs") == 0, "strtod(%s) unexpected end %s\n", s4, end); + + x = pstrtod( s5, &end ); + ok(x==9.885400e+004, "strtod(%s) returned %e\n", s5, x ); + ok(strcmp(end," dollars") == 0, "strtod(%s) unexpected end %s\n", s5, end); + + x = pstrtod( s6, &end ); + ok(x==7.8912654773e+210, "strtod(%s) returned %e\n", s6, x ); + ok(*end == 0, "strtod(%s) unexpected end %s\n", s6, end); + + x = pstrtod( s7, &end ); + ok(x==7.8912654773e+210, "strtod(%s) returned %e\n", s7, x ); + ok(*end == 0, "strtod(%s) unexpected end %s\n", s7, end); + +} + START_TEST(string) { void *mem; @@ -108,6 +182,8 @@ ok(hMsvcrt != 0, "LoadLibraryA failed\n"); SET(pmemcpy,"memcpy"); SET(pmemcmp,"memcmp"); + SET(patof,"atof"); + SET(pstrtod,"strtod"); /* MSVCRT memcpy behaves like memmove for overlapping moves, MFC42 CString::Insert seems to rely on that behaviour */ @@ -125,4 +201,6 @@ test_ismbblead(); /* test _mbsspn */ test_mbsspn(); + if (patof) test_atof(); + if (pstrtod) test_strtod(); }