diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/internal/floatscan.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/src/internal/floatscan.c b/src/internal/floatscan.c index 7d9a4524..3875719b 100644 --- a/src/internal/floatscan.c +++ b/src/internal/floatscan.c @@ -3,6 +3,7 @@ #include <math.h> #include <float.h> #include <limits.h> +#include <errno.h> #include "shgetc.h" #include "floatscan.h" @@ -111,6 +112,7 @@ static long double decfloat(FILE *f, int bits, int emin, int sign, int pok) shunget(f); } if (!gotdig) { + errno = EINVAL; shlim(f, 0); return 0; } @@ -119,10 +121,14 @@ static long double decfloat(FILE *f, int bits, int emin, int sign, int pok) return sign * 0.0; if (lrp==dc && (!k || (k==1 && !j)) && (bits>30 || x[0]>>bits==0)) return sign * (long double)x[0]; - if (lrp > -emin/2) + if (lrp > -emin/2) { + errno = ERANGE; return sign * LDBL_MAX * LDBL_MAX; - if (lrp < emin-2*LDBL_MANT_DIG) + } + if (lrp < emin-2*LDBL_MANT_DIG) { + errno = ERANGE; return sign * LDBL_MIN * LDBL_MIN; + } if (k<KMAX && j) { for (; j<9; j++) x[k]*=10; @@ -257,6 +263,8 @@ static long double decfloat(FILE *f, int bits, int emin, int sign, int pok) y = scalbnl(y, e2); + if (!y) errno = ERANGE; + return y; } @@ -332,8 +340,14 @@ static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) e2 += 4*rp - 32; if (!x) return sign * 0.0; - if (e2 > -emin) return sign * LDBL_MAX * LDBL_MAX; - if (e2 < emin-2*LDBL_MANT_DIG) return sign * LDBL_MIN * LDBL_MIN; + if (e2 > -emin) { + errno = ERANGE; + return sign * LDBL_MAX * LDBL_MAX; + } + if (e2 < emin-2*LDBL_MANT_DIG) { + errno = ERANGE; + return sign * LDBL_MIN * LDBL_MIN; + } while (x < 0x80000000) { if (y>=0.5) { @@ -359,6 +373,8 @@ static long double hexfloat(FILE *f, int bits, int emin, int sign, int pok) y = bias + sign*(long double)x + sign*y; y -= bias; + if (!y) errno = ERANGE; + return scalbnl(y, e2); } @@ -409,6 +425,7 @@ long double __floatscan(FILE *f, int c, int prec, int pok) if (i) { shunget(f); + errno = EINVAL; shlim(f, 0); return 0; } |