diff --git a/dlls/msvcrt/scanf.c b/dlls/msvcrt/scanf.c index 09ddf2863f6..04f87077e16 100644 --- a/dlls/msvcrt/scanf.c +++ b/dlls/msvcrt/scanf.c @@ -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" diff --git a/dlls/msvcrt/scanf.h b/dlls/msvcrt/scanf.h index da65bf8a6b2..5f88839c915 100644 --- a/dlls/msvcrt/scanf.h +++ b/dlls/msvcrt/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 || hlp0) 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 || hlp0) 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_ diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index a1a2c05fbb4..796b0134c59 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -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();