mirror of
https://github.com/reactos/wine.git
synced 2025-02-09 05:36:56 +00:00
msvcrt: Improved parsing precision of doubles in scanf.
This code is based on doubles parsing in jscript lexer.
This commit is contained in:
parent
bab686e7d1
commit
a9c6113c28
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
@ -305,84 +305,109 @@ _FUNCTION_ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G': { /* read a float */
|
case 'G': { /* read a float */
|
||||||
long double cur = 0;
|
long double cur;
|
||||||
int negative = 0;
|
ULONGLONG d, hlp;
|
||||||
|
int exp = 0, negative = 0;
|
||||||
|
|
||||||
/* skip initial whitespace */
|
/* skip initial whitespace */
|
||||||
while ((nch!=_EOF_) && _ISSPACE_(nch))
|
while ((nch!=_EOF_) && _ISSPACE_(nch))
|
||||||
nch = _GETC_(file);
|
nch = _GETC_(file);
|
||||||
/* get sign. */
|
|
||||||
|
/* get sign. */
|
||||||
if (nch == '-' || nch == '+') {
|
if (nch == '-' || nch == '+') {
|
||||||
negative = (nch=='-');
|
negative = (nch=='-');
|
||||||
if (width>0) width--;
|
if (width>0) width--;
|
||||||
if (width==0) break;
|
if (width==0) break;
|
||||||
nch = _GETC_(file);
|
nch = _GETC_(file);
|
||||||
}
|
}
|
||||||
/* get first digit. */
|
|
||||||
if (*locinfo->lconv->decimal_point != nch) {
|
/* get first digit. */
|
||||||
if (!_ISDIGIT_(nch)) break;
|
if (*locinfo->lconv->decimal_point != nch) {
|
||||||
cur = (nch - '0');
|
if (!_ISDIGIT_(nch)) break;
|
||||||
nch = _GETC_(file);
|
d = nch - '0';
|
||||||
if (width>0) width--;
|
|
||||||
/* read until no more digits */
|
|
||||||
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
|
|
||||||
cur = cur*10 + (nch - '0');
|
|
||||||
nch = _GETC_(file);
|
nch = _GETC_(file);
|
||||||
if (width>0) width--;
|
if (width>0) width--;
|
||||||
}
|
/* read until no more digits */
|
||||||
} else {
|
|
||||||
cur = 0; /* Fix: .8 -> 0.8 */
|
|
||||||
}
|
|
||||||
/* handle decimals */
|
|
||||||
if (width!=0 && nch == *locinfo->lconv->decimal_point) {
|
|
||||||
long double dec = 1;
|
|
||||||
nch = _GETC_(file);
|
|
||||||
if (width>0) width--;
|
|
||||||
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
|
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
|
||||||
dec /= 10;
|
hlp = d*10 + nch - '0';
|
||||||
cur += dec * (nch - '0');
|
|
||||||
nch = _GETC_(file);
|
nch = _GETC_(file);
|
||||||
if (width>0) width--;
|
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')) {
|
/* handle exponent */
|
||||||
int exponent = 0, negexp = 0;
|
if (width!=0 && (nch == 'e' || nch == 'E')) {
|
||||||
float expcnt;
|
int sign = 1, e = 0;
|
||||||
|
|
||||||
nch = _GETC_(file);
|
nch = _GETC_(file);
|
||||||
if (width>0) width--;
|
if (width>0) width--;
|
||||||
/* possible sign on the exponent */
|
if (width!=0 && (nch=='+' || nch=='-')) {
|
||||||
if (width!=0 && (nch=='+' || nch=='-')) {
|
if(nch == '-')
|
||||||
negexp = (nch=='-');
|
sign = -1;
|
||||||
nch = _GETC_(file);
|
nch = _GETC_(file);
|
||||||
if (width>0) width--;
|
if (width>0) width--;
|
||||||
}
|
|
||||||
/* exponent digits */
|
|
||||||
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
|
|
||||||
exponent *= 10;
|
|
||||||
exponent += (nch - '0');
|
|
||||||
nch = _GETC_(file);
|
|
||||||
if (width>0) width--;
|
|
||||||
}
|
}
|
||||||
/* update 'cur' with this exponent. */
|
|
||||||
expcnt = negexp ? .1 : 10;
|
/* exponent digits */
|
||||||
while (exponent!=0) {
|
while (width!=0 && (nch!=_EOF_) && _ISDIGIT_(nch)) {
|
||||||
if (exponent&1)
|
if(e > INT_MAX/10 || (e = e*10 + nch - '0')<0)
|
||||||
cur*=expcnt;
|
e = INT_MAX;
|
||||||
exponent/=2;
|
nch = _GETC_(file);
|
||||||
expcnt=expcnt*expcnt;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = (exp>=0 ? d*pow(10, exp) : d/pow(10, -exp));
|
||||||
st = 1;
|
st = 1;
|
||||||
if (!suppress) {
|
if (!suppress) {
|
||||||
if (L_prefix) _SET_NUMBER_(double);
|
if (L_prefix) _SET_NUMBER_(double);
|
||||||
else if (l_prefix) _SET_NUMBER_(double);
|
else if (l_prefix) _SET_NUMBER_(double);
|
||||||
else _SET_NUMBER_(float);
|
else _SET_NUMBER_(float);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* According to msdn,
|
/* According to msdn,
|
||||||
|
@ -110,6 +110,12 @@ static void test_sscanf( void )
|
|||||||
ok(ret == 1, "expected 1, got %u\n", ret);
|
ok(ret == 1, "expected 1, got %u\n", ret);
|
||||||
ok(double_res == 32.715, "Got %lf, expected %lf\n", double_res, 32.715);
|
ok(double_res == 32.715, "Got %lf, expected %lf\n", double_res, 32.715);
|
||||||
|
|
||||||
|
strcpy(buffer, "1.1e-30");
|
||||||
|
ret = sscanf(buffer, "%lf", &double_res);
|
||||||
|
ok(ret == 1, "expected 1, got %u\n", ret);
|
||||||
|
ok(double_res >= 1.1e-30-1e-45 && double_res <= 1.1e-30+1e-45,
|
||||||
|
"Got %.18le, expected %.18le\n", double_res, 1.1e-30);
|
||||||
|
|
||||||
/* check strings */
|
/* check strings */
|
||||||
ret = sprintf(buffer," %s", pname);
|
ret = sprintf(buffer," %s", pname);
|
||||||
ok( ret == 26, "expected 26, got %u\n", ret);
|
ok( ret == 26, "expected 26, got %u\n", ret);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user