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:
parent
66c9c358ae
commit
f99d307a3e
|
@ -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"
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue