[PATCH 1/1] Add _atoflt and _atoflt_l implementations

Nikolay Sivov nsivov at codeweavers.com
Tue Jan 18 10:06:07 CST 2011


---
 dlls/msvcr100/msvcr100.spec  |    4 +-
 dlls/msvcr80/msvcr80.spec    |    4 +-
 dlls/msvcr90/msvcr90.c       |    8 +++
 dlls/msvcr90/msvcr90.spec    |    4 +-
 dlls/msvcr90/tests/msvcr90.c |   65 ++++++++++++++++++++++++++
 dlls/msvcrt/msvcrt.h         |    8 +++
 dlls/msvcrt/msvcrt.spec      |    2 +-
 dlls/msvcrt/string.c         |  105 ++++++++++++++++++++++++++++++++++++++++++
 dlls/msvcrt/tests/headers.c  |    3 +
 include/msvcrt/crtdefs.h     |   54 +++++++++++++++++++++
 include/msvcrt/stdlib.h      |    1 +
 11 files changed, 251 insertions(+), 7 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 0d1ffa1..a07400e 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -505,8 +505,8 @@
 @ stub _atodbl
 @ stub _atodbl_l
 @ cdecl _atof_l(str ptr) msvcrt._atof_l
-@ stub _atoflt
-@ stub _atoflt_l
+@ cdecl _atoflt(ptr str) msvcr90._atoflt
+@ cdecl _atoflt_l(ptr str ptr) msvcrt._atoflt_l
 @ cdecl -ret64 _atoi64(str) msvcrt._atoi64
 @ stub _atoi64_l
 @ stub _atoi_l
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index 63d8f14..f983944 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -344,8 +344,8 @@
 @ stub _atodbl
 @ stub _atodbl_l
 @ cdecl _atof_l(str ptr) msvcrt._atof_l
-@ stub _atoflt
-@ stub _atoflt_l
+@ cdecl _atoflt(ptr str) msvcr90._atoflt
+@ cdecl _atoflt_l(ptr str ptr) msvcrt._atoflt_l
 @ cdecl -ret64 _atoi64(str) msvcrt._atoi64
 @ stub _atoi64_l
 @ stub _atoi_l
diff --git a/dlls/msvcr90/msvcr90.c b/dlls/msvcr90/msvcr90.c
index dbe528f..523ceec 100644
--- a/dlls/msvcr90/msvcr90.c
+++ b/dlls/msvcr90/msvcr90.c
@@ -192,3 +192,11 @@ int CDECL _wstat64i32(const wchar_t *path, struct _stat64i32 *buf)
         msvcrt_stat64_to_stat64i32(&buf64, buf);
     return ret;
 }
+
+/*********************************************************************
+ *		_atoflt  (MSVCR90.@)
+ */
+int CDECL _atoflt( _CRT_FLOAT *value, char *str )
+{
+    return _atoflt_l( value, str, NULL );
+}
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index 3e8f0bf..fb9073d 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -336,8 +336,8 @@
 @ stub _atodbl
 @ stub _atodbl_l
 @ cdecl _atof_l(str ptr) msvcrt._atof_l
-@ stub _atoflt
-@ stub _atoflt_l
+@ cdecl _atoflt(ptr str)
+@ cdecl _atoflt_l(ptr str ptr) msvcrt._atoflt_l
 @ cdecl -ret64 _atoi64(str) msvcrt._atoi64
 @ stub _atoi64_l
 @ stub _atoi_l
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index 24a6517..40caa05 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -19,6 +19,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <math.h>
 
 #include <windef.h>
 #include <winbase.h>
@@ -67,12 +68,18 @@ static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
 static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
 static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *);
 static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int);
+static int (__cdecl *p_atoflt)(_CRT_FLOAT *, char *);
 
 static void* (WINAPI *pEncodePointer)(void *);
 
 static int cb_called[4];
 static int g_qsort_s_context_counter;
 
+static inline int almost_equal_f(float f1, float f2)
+{
+    return f1-f2 > -1e-30 && f1-f2 < 1e-30;
+}
+
 /* ########## */
 
 static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
@@ -617,6 +624,62 @@ static void test_controlfp_s(void)
     ok( cur != 0xdeadbeef, "value not set\n" );
 }
 
+typedef struct
+{
+    const char *str;
+    float flt;
+    int ret;
+} _atoflt_test;
+
+static const _atoflt_test _atoflt_testdata[] = {
+    { "12.1", 12.1, 0 },
+    { "-13.721", -13.721, 0 },
+    { "INF", 0.0, 0 },
+    { ".21e12", 0.21e12, 0 },
+    { "214353e-3", 214.353, 0 },
+    { "1d9999999999999999999", 0.0, _OVERFLOW },
+    { "  d10", 0.0, 0 },
+    /* more significant digits */
+    { "1.23456789", 1.23456789, 0 },
+    { "1.23456789e1", 12.3456789, 0 },
+    { "1e39", 0.0, _OVERFLOW },
+    { "1e-39", 0.0, _UNDERFLOW },
+    { NULL }
+};
+
+static void test__atoflt(void)
+{
+    _CRT_FLOAT flt;
+    int ret, i = 0;
+
+    if (!p_atoflt)
+    {
+        win_skip("_atoflt not found\n");
+        return;
+    }
+
+if (0)
+{
+    /* crashes on native */
+    ret = p_atoflt(NULL, NULL);
+    ret = p_atoflt(NULL, (char*)_atoflt_testdata[0].str);
+    ret = p_atoflt(&flt, NULL);
+}
+
+    while (_atoflt_testdata[i].str)
+    {
+        ret = p_atoflt(&flt, (char*)_atoflt_testdata[i].str);
+        ok(ret == _atoflt_testdata[i].ret, "got ret %d, expected ret %d, for %s\n", ret,
+            _atoflt_testdata[i].ret, _atoflt_testdata[i].str);
+
+        if (ret == 0)
+          ok(almost_equal_f(flt.f, _atoflt_testdata[i].flt), "got %f, expected %f, for %s\n", flt.f,
+              _atoflt_testdata[i].flt, _atoflt_testdata[i].str);
+
+        i++;
+    }
+}
+
 START_TEST(msvcr90)
 {
     HMODULE hcrt;
@@ -648,6 +711,7 @@ START_TEST(msvcr90)
     p_wcsncat_s = (void *)GetProcAddress( hcrt,"wcsncat_s" );
     p_qsort_s = (void *) GetProcAddress(hcrt, "qsort_s");
     p_controlfp_s = (void *) GetProcAddress(hcrt, "_controlfp_s");
+    p_atoflt = (void* )GetProcAddress(hcrt, "_atoflt");
 
     hkernel32 = GetModuleHandleA("kernel32.dll");
     pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
@@ -660,4 +724,5 @@ START_TEST(msvcr90)
     test_wcsncat_s();
     test_qsort_s();
     test_controlfp_s();
+    test__atoflt();
 }
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 4ca3e3e..9e29d31 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -890,4 +890,12 @@ typedef struct pf_output_t
 int pf_vsnprintf( pf_output *out, const WCHAR *format,
                   MSVCRT__locale_t locale, BOOL valid, __ms_va_list valist );
 
+#define MSVCRT__OVERFLOW  3
+#define MSVCRT__UNDERFLOW 4
+
+typedef struct
+{
+    float f;
+} MSVCRT__CRT_FLOAT;
+
 #endif /* __WINE_MSVCRT_H */
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index efec11f..a6160a4 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -303,7 +303,7 @@
 @ stub _atodbl #(ptr str)
 # stub _atodbl_l
 @ cdecl _atof_l(str ptr) MSVCRT__atof_l
-# stub _atoflt_l
+@ cdecl _atoflt_l(ptr str ptr) MSVCRT__atoflt_l
 @ cdecl -ret64 _atoi64(str) ntdll._atoi64
 # stub _atoi64_l
 # stub _atoi_l
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index 6be2237..031c3d0 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -333,6 +333,111 @@ double CDECL MSVCRT__atof_l( const char *str, MSVCRT__locale_t locale)
 }
 
 /*********************************************************************
+ *		_atoflt_l  (MSVCRT.@)
+ */
+int CDECL MSVCRT__atoflt_l( MSVCRT__CRT_FLOAT *value, char *str, MSVCRT__locale_t locale)
+{
+    unsigned __int64 d=0, hlp;
+    unsigned fpcontrol;
+    int exp=0, sign=1;
+    const char *p;
+    int ret=0;
+    BOOL found_digit = FALSE;
+
+    if(!locale)
+        locale = get_locale();
+
+    /* FIXME: use *_l functions */
+    p = str;
+    while(isspace(*p))
+        p++;
+
+    if(*p == '-') {
+        sign = -1;
+        p++;
+    } else if(*p == '+')
+        p++;
+
+    while(isdigit(*p)) {
+        found_digit = TRUE;
+        hlp = d*10+*(p++)-'0';
+        if(d>MSVCRT_UI64_MAX/10 || hlp<d) {
+            exp++;
+            break;
+        } else
+            d = hlp;
+    }
+    while(isdigit(*p)) {
+        exp++;
+        p++;
+    }
+
+    if(*p == *locale->locinfo->lconv->decimal_point)
+        p++;
+
+    while(isdigit(*p)) {
+        found_digit = TRUE;
+        hlp = d*10+*(p++)-'0';
+        if(d>MSVCRT_UI64_MAX/10 || hlp<d)
+            break;
+
+        d = hlp;
+        exp--;
+    }
+    while(isdigit(*p))
+        p++;
+
+    if(!found_digit) {
+        value->f = 0.0;
+        return 0;
+    }
+
+    if(*p=='e' || *p=='E' || *p=='d' || *p=='D') {
+        int e=0, s=1;
+
+        p++;
+        if(*p == '-') {
+            s = -1;
+            p++;
+        } else if(*p == '+')
+            p++;
+
+        if(isdigit(*p)) {
+            while(isdigit(*p)) {
+                if(e>INT_MAX/10 || (e=e*10+*p-'0')<0)
+                    e = INT_MAX;
+                p++;
+            }
+            e *= s;
+
+            if(exp<0 && e<0 && exp+e>=0) exp = INT_MIN;
+            else if(exp>0 && e>0 && exp+e<0) exp = INT_MAX;
+            else exp += e;
+        } else {
+            if(*p=='-' || *p=='+')
+                p--;
+            p--;
+        }
+    }
+
+    fpcontrol = _control87(0, 0);
+    _control87(MSVCRT__EM_DENORMAL|MSVCRT__EM_INVALID|MSVCRT__EM_ZERODIVIDE
+            |MSVCRT__EM_OVERFLOW|MSVCRT__EM_UNDERFLOW|MSVCRT__EM_INEXACT, 0xffffffff);
+
+    if(exp>0)
+        value->f = (float)sign*d*powf(10, exp);
+    else
+        value->f = (float)sign*d/powf(10, -exp);
+
+    _control87(fpcontrol, 0xffffffff);
+
+    if((d && value->f==0.0) || isinf(value->f))
+        ret = exp > 0 ? MSVCRT__OVERFLOW : MSVCRT__UNDERFLOW;
+
+    return ret;
+}
+
+/*********************************************************************
  *		strcoll (MSVCRT.@)
  */
 int CDECL MSVCRT_strcoll( const char* str1, const char* str2 )
diff --git a/dlls/msvcrt/tests/headers.c b/dlls/msvcrt/tests/headers.c
index ef6e37d..829fe47 100644
--- a/dlls/msvcrt/tests/headers.c
+++ b/dlls/msvcrt/tests/headers.c
@@ -260,6 +260,7 @@ static void test_structs(void)
     CHECK_FIELD(_stat64, st_atime);
     CHECK_FIELD(_stat64, st_mtime);
     CHECK_FIELD(_stat64, st_ctime);
+    CHECK_SIZE(_CRT_FLOAT);
 }
 
 /************* Checking defines ***************/
@@ -450,6 +451,8 @@ static void test_defines(void)
     CHECK_DEF(_DN_FLUSH_OPERANDS_SAVE_RESULTS);
     CHECK_DEF(_DN_SAVE_OPERANDS_FLUSH_RESULTS);
     CHECK_DEF(_EM_AMBIGUOUS);
+    CHECK_DEF(_OVERFLOW);
+    CHECK_DEF(_UNDERFLOW);
 }
 
 #endif /* __WINE_USE_MSVCRT */
diff --git a/include/msvcrt/crtdefs.h b/include/msvcrt/crtdefs.h
index 0e43dd5..5232e80 100644
--- a/include/msvcrt/crtdefs.h
+++ b/include/msvcrt/crtdefs.h
@@ -18,6 +18,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#ifndef __WINE_CRTDEFS_H
+#define __WINE_CRTDEFS_H
+
 #ifndef __WINE_USE_MSVCRT
 #define __WINE_USE_MSVCRT
 #endif
@@ -181,3 +184,54 @@ typedef unsigned short  wctype_t;
 typedef int errno_t;
 #define _ERRNO_T_DEFINED
 #endif
+
+struct threadlocaleinfostruct;
+struct threadmbcinfostruct;
+typedef struct threadlocaleinfostruct *pthreadlocinfo;
+typedef struct threadmbcinfostruct *pthreadmbcinfo;
+
+typedef struct localeinfo_struct
+{
+    pthreadlocinfo locinfo;
+    pthreadmbcinfo mbcinfo;
+} _locale_tstruct, *_locale_t;
+
+#ifndef _TAGLC_ID_DEFINED
+typedef struct tagLC_ID {
+    unsigned short wLanguage;
+    unsigned short wCountry;
+    unsigned short wCodePage;
+} LC_ID, *LPLC_ID;
+#define _TAGLC_ID_DEFINED
+#endif
+
+#ifndef _THREADLOCALEINFO
+typedef struct threadlocaleinfostruct {
+    int refcount;
+    unsigned int lc_codepage;
+    unsigned int lc_collate_cp;
+    unsigned long lc_handle[6];
+    LC_ID lc_id[6];
+    struct {
+        char *locale;
+        wchar_t *wlocale;
+        int *refcount;
+        int *wrefcount;
+    } lc_category[6];
+    int lc_clike;
+    int mb_cur_max;
+    int *lconv_intl_refcount;
+    int *lconv_num_refcount;
+    int *lconv_mon_refcount;
+    struct lconv *lconv;
+    int *ctype1_refcount;
+    unsigned short *ctype1;
+    const unsigned short *pctype;
+    const unsigned char *pclmap;
+    const unsigned char *pcumap;
+    struct __lc_time_data *lc_time_curr;
+} threadlocinfo;
+#define _THREADLOCALEINFO
+#endif
+
+#endif /* __WINE_CRTDEFS_H */
diff --git a/include/msvcrt/stdlib.h b/include/msvcrt/stdlib.h
index 49783c0..d30e483 100644
--- a/include/msvcrt/stdlib.h
+++ b/include/msvcrt/stdlib.h
@@ -138,6 +138,7 @@ typedef int (__cdecl *_onexit_t)(void);
 
 int           __cdecl _atodbl(_CRT_DOUBLE*,char*);
 int           __cdecl _atoflt(_CRT_FLOAT*,char*);
+int           __cdecl _atoflt_l(_CRT_FLOAT*,char*,_locale_t);
 __int64       __cdecl _atoi64(const char*);
 long double   __cdecl _atold(const char*);
 int           __cdecl _atoldbl(_LDOUBLE*,char*);
-- 
1.5.6.5


--------------090704070903080501080506--



More information about the wine-patches mailing list