msvcrt: Use parse_double for scanf floats.

Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Erich E. Hoover 2020-01-02 19:01:56 +01:00 committed by Alexandre Julliard
parent 66c9c358ae
commit f99d307a3e
3 changed files with 91 additions and 113 deletions

View File

@ -100,15 +100,6 @@ static int wchar2digit(MSVCRT_wchar_t c, int base) {
/* vsnscanf_s_l */
#define SECURE
#include "scanf.h"
/* vsnwscanf_l */
#define WIDE_SCANF 1
#undef SECURE
#include "scanf.h"
/* vsnwscanf_s_l */
#define SECURE 1
#include "scanf.h"
#undef STRING_LEN
/* vswscanf_l */
@ -118,6 +109,15 @@ static int wchar2digit(MSVCRT_wchar_t c, int base) {
#undef SECURE
#include "scanf.h"
/* vsnwscanf_l */
#define STRING_LEN 1
#include "scanf.h"
/* vsnwscanf_s_l */
#define SECURE 1
#include "scanf.h"
#undef STRING_LEN
/* vswscanf_s_l */
#define SECURE 1
#include "scanf.h"

View File

@ -46,6 +46,9 @@
#endif /* WIDE_SCANF */
#ifdef CONSOLE
#define _GETC_FUNC_(file) _getch()
#define _UNGETC_FUNC_(nch, file) _ungetch(nch)
#define _STRTOD_NAME_(func) console_ ## func
#define _GETC_(file) (consumed++, _getch())
#define _UNGETC_(nch, file) do { _ungetch(nch); consumed--; } while(0)
#define _LOCK_FILE_(file) MSVCRT__lock_file(MSVCRT_stdin)
@ -67,6 +70,13 @@
#ifdef STRING
#undef _EOF_
#define _EOF_ 0
#define _GETC_FUNC_(file) (*file++)
#define _UNGETC_FUNC_(nch, file) do { file--; } while(0)
#ifdef WIDE_SCANF
#define _STRTOD_NAME_(func) wstr_ ## func
#else
#define _STRTOD_NAME_(func) str_ ## func
#endif
#ifdef STRING_LEN
#ifdef WIDE_SCANF
#define _GETC_(file) (consumed==length ? '\0' : (consumed++, *file++))
@ -114,6 +124,9 @@
#endif /* STRING_LEN */
#else /* STRING */
#ifdef WIDE_SCANF
#define _GETC_FUNC_(file) MSVCRT_fgetwc(file)
#define _UNGETC_FUNC_(nch, file) MSVCRT_ungetwc(nch, file)
#define _STRTOD_NAME_(func) filew_ ## func
#define _GETC_(file) (consumed++, MSVCRT_fgetwc(file))
#define _UNGETC_(nch, file) do { MSVCRT_ungetwc(nch, file); consumed--; } while(0)
#define _LOCK_FILE_(file) MSVCRT__lock_file(file)
@ -124,6 +137,9 @@
#define _FUNCTION_ static int MSVCRT_vfwscanf_l(MSVCRT_FILE* file, const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list ap)
#endif /* SECURE */
#else /* WIDE_SCANF */
#define _GETC_FUNC_(file) MSVCRT_fgetc(file)
#define _UNGETC_FUNC_(nch, file) MSVCRT_ungetc(nch, file)
#define _STRTOD_NAME_(func) file_ ## func
#define _GETC_(file) (consumed++, MSVCRT_fgetc(file))
#define _UNGETC_(nch, file) do { MSVCRT_ungetc(nch, file); consumed--; } while(0)
#define _LOCK_FILE_(file) MSVCRT__lock_file(file)
@ -137,6 +153,44 @@
#endif /* STRING */
#endif /* CONSOLE */
#if (!defined(SECURE) && !defined(STRING_LEN) && (!defined(CONSOLE) || !defined(WIDE_SCANF)))
struct _STRTOD_NAME_(strtod_scanf_ctx) {
MSVCRT_pthreadlocinfo locinfo;
#ifdef STRING
const _CHAR_ *file;
#else
MSVCRT_FILE *file;
#endif
int length;
int read;
_CHAR_ unget_buf[8];
};
static MSVCRT_wchar_t _STRTOD_NAME_(strtod_scanf_get)(void *ctx)
{
struct _STRTOD_NAME_(strtod_scanf_ctx) *context = ctx;
int c;
if (!context->length) return MSVCRT_WEOF;
c = _GETC_FUNC_(context->file);
if (c == _EOF_) return MSVCRT_WEOF;
if (context->length > 0) context->length--;
context->unget_buf[context->read % ARRAY_SIZE(context->unget_buf)] = c;
context->read++;
return c;
}
static void _STRTOD_NAME_(strtod_scanf_unget)(void *ctx)
{
struct _STRTOD_NAME_(strtod_scanf_ctx) *context = ctx;
if (context->length >= 0) context->length++;
context->read--;
_UNGETC_FUNC_(context->unget_buf[context->read % ARRAY_SIZE(context->unget_buf)], context->file);
}
#endif
_FUNCTION_ {
MSVCRT_pthreadlocinfo locinfo;
int rd = 0, consumed = 0;
@ -322,116 +376,34 @@ _FUNCTION_ {
case 'f':
case 'g':
case 'G': { /* read a float */
long double cur = 1, expcnt = 10;
ULONGLONG d, hlp;
int exp = 0, negative = 0;
unsigned fpcontrol;
BOOL negexp;
#ifdef CONSOLE
struct _STRTOD_NAME_(strtod_scanf_ctx) ctx = {locinfo, 0, width};
#else
struct _STRTOD_NAME_(strtod_scanf_ctx) ctx = {locinfo, file, width};
#endif
int negative = 0;
double cur;
/* skip initial whitespace */
while ((nch!=_EOF_) && _ISSPACE_(nch))
nch = _GETC_(file);
if (nch != _EOF_) _UNGETC_(nch, file);
#ifdef STRING
ctx.file = file;
#endif
#ifdef STRING_LEN
if(ctx.length > length-consumed) ctx.length = length-consumed;
#endif
/* get sign. */
if (nch == '-' || nch == '+') {
negative = (nch=='-');
if (width>0) width--;
if (width==0) break;
nch = _GETC_(file);
}
cur = parse_double(_STRTOD_NAME_(strtod_scanf_get),
_STRTOD_NAME_(strtod_scanf_unget), &ctx, locinfo, NULL);
if(!ctx.read) break;
consumed += ctx.read;
#ifdef STRING
file = ctx.file;
#endif
/* get first digit. */
if (*locinfo->lconv->decimal_point != nch) {
if (!_ISDIGIT_(nch)) break;
d = nch - '0';
nch = _GETC_(file);
if (width>0) width--;
/* read until no more digits */
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
hlp = d*10 + nch - '0';
nch = _GETC_(file);
if (width>0) width--;
if(d > (ULONGLONG)-1/10 || hlp<d) {
exp++;
break;
}
else
d = hlp;
}
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
exp++;
nch = _GETC_(file);
if (width>0) width--;
}
} else {
d = 0; /* Fix: .8 -> 0.8 */
}
/* handle decimals */
if (width!=0 && nch == *locinfo->lconv->decimal_point) {
nch = _GETC_(file);
if (width>0) width--;
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
hlp = d*10 + nch - '0';
nch = _GETC_(file);
if (width>0) width--;
if(d > (ULONGLONG)-1/10 || hlp<d)
break;
d = hlp;
exp--;
}
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
nch = _GETC_(file);
if (width>0) width--;
}
}
/* handle exponent */
if (width!=0 && (nch == 'e' || nch == 'E')) {
int sign = 1, e = 0;
nch = _GETC_(file);
if (width>0) width--;
if (width!=0 && (nch=='+' || nch=='-')) {
if(nch == '-')
sign = -1;
nch = _GETC_(file);
if (width>0) width--;
}
/* exponent digits */
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
if(e > INT_MAX/10 || (e = e*10 + nch - '0')<0)
e = INT_MAX;
nch = _GETC_(file);
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);
nch = _GETC_(file);
st = 1;
if (!suppress) {
@ -739,6 +711,9 @@ _FUNCTION_ {
#undef _CHAR2SUPPORTED_
#undef _WIDE2SUPPORTED_
#undef _CHAR2DIGIT_
#undef _GETC_FUNC_
#undef _UNGETC_FUNC_
#undef _STRTOD_NAME_
#undef _GETC_
#undef _UNGETC_
#undef _LOCK_FILE_

View File

@ -776,6 +776,7 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
e = INT_MAX;
nch = get(ctx);
}
if(nch != MSVCRT_WEOF) unget(ctx);
e *= s;
if(exp<0 && e<0 && exp+e>=0) exp = INT_MIN;
@ -786,6 +787,8 @@ double parse_double(MSVCRT_wchar_t (*get)(void *ctx), void (*unget)(void *ctx),
if(found_sign) unget(ctx);
unget(ctx);
}
} else if(nch != MSVCRT_WEOF) {
unget(ctx);
}
if(!err) err = MSVCRT__errno();