Erich E. Hoover : ntdll: Drop support for floating point numbers in sscanf.
Alexandre Julliard
julliard at winehq.org
Mon Dec 23 17:42:11 CST 2019
Module: wine
Branch: master
Commit: 94675cd8e38496c63dc033e015783c589d764193
URL: https://source.winehq.org/git/wine.git/?a=commit;h=94675cd8e38496c63dc033e015783c589d764193
Author: Erich E. Hoover <erich.e.hoover at gmail.com>
Date: Sat Dec 21 17:53:57 2019 -0700
ntdll: Drop support for floating point numbers in sscanf.
Takes care of one more use of "long double".
Signed-off-by: Erich E. Hoover <erich.e.hoover at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/string.c | 140 ----------------------------------------------
dlls/ntdll/tests/string.c | 47 ++++++++++++++++
2 files changed, 47 insertions(+), 140 deletions(-)
diff --git a/dlls/ntdll/string.c b/dlls/ntdll/string.c
index 1d6af8558c..709f0ebdbd 100644
--- a/dlls/ntdll/string.c
+++ b/dlls/ntdll/string.c
@@ -848,7 +848,6 @@ static int NTDLL_vsscanf( const char *str, const char *format, __ms_va_list ap)
int base;
int h_prefix = 0;
BOOLEAN l_prefix = FALSE;
- BOOLEAN L_prefix = FALSE;
BOOLEAN w_prefix = FALSE;
BOOLEAN I64_prefix = FALSE;
BOOLEAN prefix_finished = FALSE;
@@ -881,7 +880,6 @@ static int NTDLL_vsscanf( const char *str, const char *format, __ms_va_list ap)
l_prefix = TRUE;
break;
case 'w': w_prefix = TRUE; break;
- case 'L': L_prefix = TRUE; break;
case 'I':
if (*(format + 1) == '6' &&
*(format + 2) == '4')
@@ -990,144 +988,6 @@ static int NTDLL_vsscanf( const char *str, const char *format, __ms_va_list ap)
}
}
break;
- case 'e':
- case 'E':
- case 'f':
- case 'g':
- case 'G':
- { /* read a float */
- long double cur = 1, expcnt = 10;
- ULONGLONG d, hlp;
- int exp = 0;
- BOOLEAN negative = FALSE;
- /*unsigned fpcontrol;*/
- BOOLEAN negexp;
-
- /* skip initial whitespace */
- while (nch != '\0' && isspace( nch ))
- nch = (consumed++, *str++);
-
- /* get sign */
- if (nch == '-' || nch == '+')
- {
- negative = (nch == '-');
- if (width > 0) width--;
- if (width == 0) break;
- nch = (consumed++, *str++);
- }
-
- /* get first digit */
- if ('.' != nch)
- {
- if (!isdigit( nch )) break;
- d = nch - '0';
- nch = (consumed++, *str++);
- if (width > 0) width--;
- /* read until no more digits */
- while (width != 0 && nch != '\0' && isdigit( nch ))
- {
- hlp = d * 10 + nch - '0';
- nch = (consumed++, *str++);
- if (width > 0) width--;
- if(d > (ULONGLONG)-1/10 || hlp < d)
- {
- exp++;
- break;
- }
- else
- d = hlp;
- }
- while (width != 0 && nch != '\0' && isdigit( nch ))
- {
- exp++;
- nch = (consumed++, *str++);
- if (width > 0) width--;
- }
- }
- else
- d = 0; /* Fix: .8 -> 0.8 */
-
- /* handle decimals */
- if (width != 0 && nch == '.')
- {
- nch = (consumed++, *str++);
- if (width > 0) width--;
-
- while (width != 0 && nch != '\0' && isdigit( nch ))
- {
- hlp = d * 10 + nch - '0';
- nch = (consumed++, *str++);
- if (width > 0) width--;
- if(d > (ULONGLONG)-1/10 || hlp < d)
- break;
-
- d = hlp;
- exp--;
- }
- while (width != 0 && nch != '\0' && isdigit( nch ))
- {
- nch = (consumed++, *str++);
- if (width > 0) width--;
- }
- }
-
- /* handle exponent */
- if (width != 0 && (nch == 'e' || nch == 'E'))
- {
- int sign = 1, e = 0;
-
- nch = (consumed++, *str++);
- if (width > 0) width--;
- if (width != 0 && (nch == '+' || nch == '-'))
- {
- if(nch == '-')
- sign = -1;
- nch = (consumed++, *str++);
- if (width > 0) width--;
- }
-
- /* exponent digits */
- while (width != 0 && nch != '\0' && isdigit( nch ))
- {
- if (e > INT_MAX/10 || (e = e * 10 + nch - '0') < 0)
- e = INT_MAX;
- nch = (consumed++, *str++);
- if (width > 0) width--;
- }
- e *= sign;
-
- if(exp < 0 && e < 0 && e+exp > 0) exp = INT_MIN;
- else if(exp > 0 && e > 0 && e+exp < 0) exp = INT_MAX;
- else exp += e;
- }
-
- /*fpcontrol = _control87(0, 0);
- _control87(MSVCRT__EM_DENORMAL|MSVCRT__EM_INVALID|MSVCRT__EM_ZERODIVIDE
- |MSVCRT__EM_OVERFLOW|MSVCRT__EM_UNDERFLOW|MSVCRT__EM_INEXACT, 0xffffffff);*/
-
- negexp = (exp < 0);
- if (negexp)
- exp = -exp;
- /* update 'cur' with this exponent. */
- while (exp)
- {
- if(exp & 1)
- cur *= expcnt;
- exp /= 2;
- expcnt = expcnt*expcnt;
- }
- cur = (negexp ? d/cur : d*cur);
-
- /*_control87(fpcontrol, 0xffffffff);*/
-
- st = 1;
- if (!suppress)
- {
- if (L_prefix || l_prefix) _SET_NUMBER_( double );
- else _SET_NUMBER_( float );
- }
- }
- break;
/* According to msdn,
* 's' reads a character string in a call to fscanf
* and 'S' a wide character string and vice versa in a
diff --git a/dlls/ntdll/tests/string.c b/dlls/ntdll/tests/string.c
index 5a2d8458c2..12027e8899 100644
--- a/dlls/ntdll/tests/string.c
+++ b/dlls/ntdll/tests/string.c
@@ -67,6 +67,8 @@ static int (__cdecl *p_tolower)(int);
static int (__cdecl *p_toupper)(int);
static int (__cdecl *p__strnicmp)(LPCSTR,LPCSTR,size_t);
+static int (WINAPIV *p_sscanf)(const char *, const char *, ...);
+
static void InitFunctionPtrs(void)
{
hntdll = LoadLibraryA("ntdll.dll");
@@ -109,6 +111,8 @@ static void InitFunctionPtrs(void)
p_tolower = (void *)GetProcAddress(hntdll, "tolower");
p_toupper = (void *)GetProcAddress(hntdll, "toupper");
p__strnicmp = (void *)GetProcAddress(hntdll, "_strnicmp");
+
+ p_sscanf = (void *)GetProcAddress(hntdll, "sscanf");
} /* if */
}
@@ -1455,6 +1459,48 @@ static void test__strnicmp(void)
ok(!ret, "_strnicmp returned %d\n", ret);
}
+static void test_sscanf(void)
+{
+ double d = 0.0;
+ float f = 0.0f;
+ int i = 0;
+ int ret;
+
+ if (!p_sscanf)
+ {
+ win_skip("sscanf tests\n");
+ return;
+ }
+
+ ret = p_sscanf("10", "%d", &i);
+ ok(ret == 1, "ret = %d\n", ret);
+ ok(i == 10, "i = %d\n", i);
+
+ ret = p_sscanf("10", "%f", &f);
+ ok(ret == 0 || broken(ret == 1) /* xp/2003 */, "ret = %d\n", ret);
+ ok(f == 0.0f, "f = %f\n", f);
+
+ ret = p_sscanf("10", "%g", &f);
+ ok(ret == 0 || broken(ret == 1) /* xp/2003 */, "ret = %d\n", ret);
+ ok(f == 0.0f, "f = %f\n", f);
+
+ ret = p_sscanf("10", "%e", &f);
+ ok(ret == 0 || broken(ret == 1) /* xp/2003 */, "ret = %d\n", ret);
+ ok(f == 0.0f, "f = %f\n", f);
+
+ ret = p_sscanf("10", "%lf", &d);
+ ok(ret == 0 || broken(ret == 1) /* xp/2003 */, "ret = %d\n", ret);
+ ok(d == 0.0, "d = %lf\n", f);
+
+ ret = p_sscanf("10", "%lg", &d);
+ ok(ret == 0 || broken(ret == 1) /* xp/2003 */, "ret = %d\n", ret);
+ ok(d == 0.0, "d = %lf\n", f);
+
+ ret = p_sscanf("10", "%le", &d);
+ ok(ret == 0 || broken(ret == 1) /* xp/2003 */, "ret = %d\n", ret);
+ ok(d == 0.0, "d = %lf\n", f);
+}
+
START_TEST(string)
{
InitFunctionPtrs();
@@ -1498,4 +1544,5 @@ START_TEST(string)
test_tolower();
test_toupper();
test__strnicmp();
+ test_sscanf();
}
More information about the wine-cvs
mailing list