[Corrected^2] Fix (w)strto(l)d family and test for atof
Uwe Bonnes
bon at elektron.ikp.physik.tu-darmstadt.de
Mon Jan 23 06:23:21 CST 2006
(First forgot some fix in wcstod and then sent to the wrong list, now with
another test and an additinal fix)
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 bon at elektron.ikp.physik.tu-darmstadt.de
Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
Index: wine/dlls/msvcrt/string.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/string.c,v
retrieving revision 1.15
diff -u -w -r1.15 string.c
--- wine/dlls/msvcrt/string.c 14 Jan 2006 17:01:19 -0000 1.15
+++ wine/dlls/msvcrt/string.c 23 Jan 2006 12:20:02 -0000
@@ -22,6 +22,7 @@
*/
#include <stdlib.h>
+#include <math.h>
#include "msvcrt.h"
#include "wine/debug.h"
@@ -138,19 +139,106 @@
}
/*********************************************************************
- * atof (MSVCRT.@)
+ * strtold (internal)
*/
-double MSVCRT_atof( const char *str )
+long double MSVCRT_strtold( const char *lpszStr, char **end )
+{
+ 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 == '-')
{
- return atof( str );
+ negative = 1;
+ str++;
+ }
+ else
+ if (*str == '+')
+ 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/wcs.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/wcs.c,v
retrieving revision 1.35
diff -u -w -r1.35 wcs.c
--- wine/dlls/msvcrt/wcs.c 14 Jan 2006 17:00:58 -0000 1.35
+++ wine/dlls/msvcrt/wcs.c 23 Jan 2006 12:20:03 -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);
@@ -131,30 +131,38 @@
negative = 1;
str++;
}
+ else
+ if (*str == '+')
+ str++;
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 +171,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 +183,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
{
@@ -248,7 +262,7 @@
int space = out->len - out->used;
if( len < 0 )
- len = strlen( str );
+ len = lstrlenA( str );
if( !out->unicode )
{
LPSTR p = out->buf.A + out->used;
@@ -341,7 +355,7 @@
int r = 0;
if( len < 0 )
- len = strlen( str );
+ len = lstrlenA( str );
if (flags->Precision >= 0 && flags->Precision < len)
len = flags->Precision;
@@ -609,6 +623,7 @@
{
LPCWSTR str = va_arg( valist, const WCHAR * );
+ TRACE("BON: wstr is %s\n",debugstr_w(str));
if( str )
r = pf_output_format_W( out, str, -1, &flags );
else
@@ -622,6 +637,7 @@
{
LPCSTR str = va_arg( valist, const CHAR * );
+ TRACE("BON: str %p is %s\n",str, debugstr_a(str));
if( str )
r = pf_output_format_A( out, str, -1, &flags );
else
@@ -728,6 +744,7 @@
pf_output out;
int r;
+ TRACE("BON:\n");
out.unicode = FALSE;
out.buf.A = str;
out.used = 0;
@@ -755,6 +772,7 @@
int retval;
va_list valist;
va_start(valist, format);
+ TRACE("BON:\n");
retval = MSVCRT_vsnprintf(str, len, format, valist);
va_end(valist);
return retval;
@@ -768,6 +786,7 @@
{
pf_output out;
+ TRACE("BON:\n");
out.unicode = TRUE;
out.buf.W = str;
out.used = 0;
@@ -783,6 +802,7 @@
{
int retval;
va_list valist;
+ TRACE("BON:\n");
va_start(valist, format);
retval = MSVCRT_vsnwprintf(str, len, format, valist);
va_end(valist);
@@ -797,6 +817,7 @@
va_list ap;
int r;
+ TRACE("BON: %s\n", debugstr_a(format));
va_start( ap, format );
r = MSVCRT_vsnprintf( str, INT_MAX, format, ap );
va_end( ap );
@@ -811,6 +832,7 @@
va_list ap;
int r;
+ TRACE("BON:\n");
va_start( ap, format );
r = MSVCRT_vsnwprintf( str, INT_MAX, format, ap );
va_end( ap );
@@ -822,6 +844,7 @@
*/
int MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, va_list args )
{
+ TRACE("BON:\n");
return MSVCRT_vsnwprintf( str, INT_MAX, format, args );
}
@@ -831,6 +854,7 @@
int MSVCRT_wcscoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
{
/* FIXME: handle collates */
+ TRACE("BON:\n");
return strcmpW( str1, str2 );
}
@@ -840,6 +864,7 @@
MSVCRT_wchar_t* MSVCRT_wcspbrk( const MSVCRT_wchar_t* str, const MSVCRT_wchar_t* accept )
{
const MSVCRT_wchar_t* p;
+ TRACE("BON:\n");
while (*str)
{
for (p = accept; *p; p++) if (*p == *str) return (MSVCRT_wchar_t*)str;
@@ -856,6 +881,7 @@
thread_data_t *data = msvcrt_get_thread_data();
MSVCRT_wchar_t *ret;
+ TRACE("BON:\n");
if (!str)
if (!(str = data->wcstok_next)) return NULL;
@@ -874,6 +900,7 @@
*/
INT MSVCRT_wctomb( char *dst, MSVCRT_wchar_t ch )
{
+ TRACE("BON:\n");
return WideCharToMultiByte( CP_ACP, 0, &ch, 1, dst, 6, NULL, NULL );
}
@@ -882,6 +909,7 @@
*/
INT MSVCRT_iswalnum( MSVCRT_wchar_t wc )
{
+ TRACE("BON:\n");
return isalnumW( wc );
}
@@ -890,6 +918,7 @@
*/
INT MSVCRT_iswalpha( MSVCRT_wchar_t wc )
{
+ TRACE("BON:\n");
return isalphaW( wc );
}
@@ -898,6 +927,7 @@
*/
INT MSVCRT_iswcntrl( MSVCRT_wchar_t wc )
{
+ TRACE("BON:\n");
return iscntrlW( wc );
}
Index: wine/dlls/msvcrt/tests/string.c
===================================================================
RCS file: /home/wine/wine/dlls/msvcrt/tests/string.c,v
retrieving revision 1.6
diff -u -w -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 23 Jan 2006 12:20:03 -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,83 @@
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 s8[]="\t+7.8912654773d10";
+ 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);
+
+ x = pstrtod( s8, &end );
+ ok(x==7.8912654773e+10, "strtod(%s) returned %e\n", s8, x );
+ ok(*end == 0, "strtod(%s) unexpected end %s\n", s8, end);
+
+}
+
START_TEST(string)
{
void *mem;
@@ -108,6 +187,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 +206,6 @@
test_ismbblead();
/* test _mbsspn */
test_mbsspn();
+ if (patof) test_atof();
+ if (pstrtod) test_strtod();
}
More information about the wine-patches
mailing list