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@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Erich E. Hoover 2019-12-21 17:53:57 -07:00 committed by Alexandre Julliard
parent 2ba39c8901
commit 94675cd8e3
2 changed files with 47 additions and 140 deletions

View File

@ -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

View File

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