(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 bon@elektron.ikp.physik.tu-darmstadt.de
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();
}