[Corrected] Fix (w)strto(l)d family and test for atof

Uwe Bonnes bon at elektron.ikp.physik.tu-darmstadt.de
Sun Jan 22 18:34:44 CST 2006


(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 at 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();
 }



More information about the wine-devel mailing list