[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