X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Finternal%2Ffloatscan.c;h=eef70df9d6bc03ac463ae8eaa6419c9b8577e78f;hb=f4e4632abfa8297db1485e132bb15b9ef6c32a1b;hp=377a008bd86600602c6d1fd877c47f2fa6b26626;hpb=2ac580fdfe1daf9924f221dc98878ae480306bfa;p=musl diff --git a/src/internal/floatscan.c b/src/internal/floatscan.c index 377a008b..eef70df9 100644 --- a/src/internal/floatscan.c +++ b/src/internal/floatscan.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "shgetc.h" #include "floatscan.h" @@ -14,16 +15,26 @@ #define LD_B1B_MAX 9007199, 254740991 #define KMAX 128 -#else /* LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 */ +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 #define LD_B1B_DIG 3 #define LD_B1B_MAX 18, 446744073, 709551615 #define KMAX 2048 +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 + +#define LD_B1B_DIG 4 +#define LD_B1B_MAX 10384593, 717069655, 257060992, 658440191 +#define KMAX 2048 + +#else +#error Unsupported long double representation #endif #define MASK (KMAX-1) +#define CONCAT2(x,y) x ## y +#define CONCAT(x,y) CONCAT2(x,y) static long long scanexp(FILE *f, int pok) { @@ -44,7 +55,7 @@ static long long scanexp(FILE *f, int pok) } for (x=0; c-'0'<10U && x LDBL_MANT_DIG+e2-emin) { bits = LDBL_MANT_DIG+e2-emin; if (bits<0) bits=0; + denormal = 1; } /* Calculate bias term to force rounding, move out lower bits */ @@ -275,11 +294,18 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po y += frac; y -= bias; - y = scalbnl(y, e2); - - if (!y) errno = ERANGE; + if ((e2+LDBL_MANT_DIG & INT_MAX) > emax-5) { + if (fabs(y) >= CONCAT(0x1p, LDBL_MANT_DIG)) { + if (denormal && bits==LDBL_MANT_DIG+e2-emin) + denormal = 0; + y *= 0.5; + e2++; + } + if (e2+LDBL_MANT_DIG>emax || (denormal && frac)) + errno = ERANGE; + } - return y; + return scalbnl(y, e2); } static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) @@ -335,7 +361,7 @@ static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) } else { shlim(f, 0); } - return 0; + return sign * 0.0; } if (!gotrad) rp = dc; while (dc<8) x *= 16, dc++; @@ -394,12 +420,13 @@ static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) return scalbnl(y, e2); } -long double __floatscan(FILE *f, int c, int prec, int pok) +long double __floatscan(FILE *f, int prec, int pok) { int sign = 1; - int i; + size_t i; int bits; int emin; + int c; switch (prec) { case 0: @@ -418,7 +445,7 @@ long double __floatscan(FILE *f, int c, int prec, int pok) return 0; } - if (c<0) c = shgetc(f); + while (isspace((c=shgetc(f)))); if (c=='+' || c=='-') { sign -= 2*(c=='-'); @@ -428,14 +455,33 @@ long double __floatscan(FILE *f, int c, int prec, int pok) for (i=0; i<8 && (c|32)=="infinity"[i]; i++) if (i<7) c = shgetc(f); if (i==3 || i==8 || (i>3 && pok)) { - if (i==3) shunget(f); - if (pok) for (; i>3; i--) shunget(f); - else shlim(f, 0); + if (i!=8) { + shunget(f); + if (pok) for (; i>3; i--) shunget(f); + } return sign * INFINITY; } if (!i) for (i=0; i<3 && (c|32)=="nan"[i]; i++) - if (i<3) c = shgetc(f); + if (i<2) c = shgetc(f); if (i==3) { + if (shgetc(f) != '(') { + shunget(f); + return NAN; + } + for (i=1; ; i++) { + c = shgetc(f); + if (c-'0'<10U || c-'A'<26U || c-'a'<26U || c=='_') + continue; + if (c==')') return NAN; + shunget(f); + if (!pok) { + errno = EINVAL; + shlim(f, 0); + return 0; + } + while (i--) shunget(f); + return NAN; + } return NAN; }