[PATCH 1/1] Add _atoflt and _atoflt_l implementations
Nikolay Sivov
nsivov at codeweavers.com
Thu Jan 13 16:59:52 CST 2011
---
dlls/msvcr100/msvcr100.spec | 4 +-
dlls/msvcr80/msvcr80.spec | 4 +-
dlls/msvcr90/msvcr90.spec | 4 +-
dlls/msvcr90/tests/msvcr90.c | 65 +++++++++++++++++++++++
dlls/msvcrt/msvcrt.h | 8 +++
dlls/msvcrt/msvcrt.spec | 3 +-
dlls/msvcrt/string.c | 117 ++++++++++++++++++++++++++++++++++++++++++
dlls/msvcrt/tests/headers.c | 3 +
8 files changed, 201 insertions(+), 7 deletions(-)
diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 0d1ffa1..3574c57 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) msvcrt._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..b3c950b 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) msvcrt._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.spec b/dlls/msvcr90/msvcr90.spec
index 3e8f0bf..95c777f 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) msvcrt._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/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..80be216 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -303,7 +303,8 @@
@ stub _atodbl #(ptr str)
# stub _atodbl_l
@ cdecl _atof_l(str ptr) MSVCRT__atof_l
-# stub _atoflt_l
+@ cdecl _atoflt(ptr str) MSVCRT__atoflt
+@ 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..f2952ff 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -333,6 +333,123 @@ double CDECL MSVCRT__atof_l( const char *str, MSVCRT__locale_t locale)
}
/*********************************************************************
+ * _atoflt_l (MSVCRT.@)
+ *
+ * Not exported by native 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;
+}
+
+/*********************************************************************
+ * _atoflt (MSVCRT.@)
+ *
+ * Not exported by native msvcrt
+ */
+int CDECL MSVCRT__atoflt( MSVCRT__CRT_FLOAT *value, char *str)
+{
+ return MSVCRT__atoflt_l( value, str, NULL );
+}
+
+/*********************************************************************
* 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 */
--
1.5.6.5
--------------060504050202070108080402--
More information about the wine-patches
mailing list