summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/gdtoa/dtoa.c39
-rw-r--r--lib/libc/gdtoa/g_Qfmt.c15
-rw-r--r--lib/libc/gdtoa/g__fmt.c70
-rw-r--r--lib/libc/gdtoa/g_ddfmt.c23
-rw-r--r--lib/libc/gdtoa/g_dfmt.c22
-rw-r--r--lib/libc/gdtoa/g_ffmt.c15
-rw-r--r--lib/libc/gdtoa/g_xLfmt.c15
-rw-r--r--lib/libc/gdtoa/g_xfmt.c15
-rw-r--r--lib/libc/gdtoa/gdtoa.c12
-rw-r--r--lib/libc/gdtoa/gdtoa.h19
-rw-r--r--lib/libc/gdtoa/gdtoa_fltrnds.h18
-rw-r--r--lib/libc/gdtoa/gdtoaimp.h11
-rw-r--r--lib/libc/gdtoa/gethex.c134
-rw-r--r--lib/libc/gdtoa/strtoIg.c16
-rw-r--r--lib/libc/gdtoa/strtod.c94
-rw-r--r--lib/libc/gdtoa/strtodg.c71
-rw-r--r--lib/libc/gdtoa/strtof.c9
-rw-r--r--lib/libc/gdtoa/strtopQ.c9
-rw-r--r--lib/libc/gdtoa/strtopd.c7
-rw-r--r--lib/libc/gdtoa/strtopdd.c11
-rw-r--r--lib/libc/gdtoa/strtopf.c9
-rw-r--r--lib/libc/gdtoa/strtopx.c9
-rw-r--r--lib/libc/gdtoa/strtopxL.c9
23 files changed, 500 insertions, 152 deletions
diff --git a/lib/libc/gdtoa/dtoa.c b/lib/libc/gdtoa/dtoa.c
index e808cc1f4f3..48fdf5efc2d 100644
--- a/lib/libc/gdtoa/dtoa.c
+++ b/lib/libc/gdtoa/dtoa.c
@@ -66,7 +66,6 @@ THIS SOFTWARE.
*/
#ifdef Honor_FLT_ROUNDS
-#define Rounding rounding
#undef Check_FLT_ROUNDS
#define Check_FLT_ROUNDS
#else
@@ -127,12 +126,22 @@ dtoa
Bigint *b, *b1, *delta, *mlo, *mhi, *S;
double d2, ds, eps;
char *s, *s0;
-#ifdef Honor_FLT_ROUNDS
- int rounding;
-#endif
#ifdef SET_INEXACT
int inexact, oldinexact;
#endif
+#ifdef Honor_FLT_ROUNDS /*{*/
+ int Rounding;
+#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
+ Rounding = Flt_Rounds;
+#else /*}{*/
+ Rounding = 1;
+ switch(fegetround()) {
+ case FE_TOWARDZERO: Rounding = 0; break;
+ case FE_UPWARD: Rounding = 2; break;
+ case FE_DOWNWARD: Rounding = 3;
+ }
+#endif /*}}*/
+#endif /*}*/
#ifndef MULTIPLE_THREADS
if (dtoa_result) {
@@ -178,12 +187,12 @@ dtoa
inexact = 1;
#endif
#ifdef Honor_FLT_ROUNDS
- if ((rounding = Flt_Rounds) >= 2) {
+ if (Rounding >= 2) {
if (*sign)
- rounding = rounding == 2 ? 0 : 2;
+ Rounding = Rounding == 2 ? 0 : 2;
else
- if (rounding != 2)
- rounding = 0;
+ if (Rounding != 2)
+ Rounding = 0;
}
#endif
@@ -316,7 +325,7 @@ dtoa
s = s0 = rv_alloc(i);
#ifdef Honor_FLT_ROUNDS
- if (mode > 1 && rounding != 1)
+ if (mode > 1 && Rounding != 1)
leftright = 0;
#endif
@@ -453,7 +462,7 @@ dtoa
if (i == ilim) {
#ifdef Honor_FLT_ROUNDS
if (mode > 1)
- switch(rounding) {
+ switch(Rounding) {
case 0: goto ret1;
case 2: goto bump_up;
}
@@ -521,7 +530,7 @@ dtoa
spec_case = 0;
if ((mode < 2 || leftright)
#ifdef Honor_FLT_ROUNDS
- && rounding == 1
+ && Rounding == 1
#endif
) {
if (!word1(d) && !(word0(d) & Bndry_mask)
@@ -614,7 +623,7 @@ dtoa
#ifndef ROUND_BIASED
if (j1 == 0 && mode != 1 && !(word1(d) & 1)
#ifdef Honor_FLT_ROUNDS
- && rounding >= 1
+ && Rounding >= 1
#endif
) {
if (dig == '9')
@@ -642,7 +651,7 @@ dtoa
}
#ifdef Honor_FLT_ROUNDS
if (mode > 1)
- switch(rounding) {
+ switch(Rounding) {
case 0: goto accept_dig;
case 2: goto keep_dig;
}
@@ -660,7 +669,7 @@ dtoa
}
if (j1 > 0) {
#ifdef Honor_FLT_ROUNDS
- if (!rounding)
+ if (!Rounding)
goto accept_dig;
#endif
if (dig == '9') { /* possible if i == 1 */
@@ -703,7 +712,7 @@ dtoa
/* Round off last digit */
#ifdef Honor_FLT_ROUNDS
- switch(rounding) {
+ switch(Rounding) {
case 0: goto trimzeros;
case 2: goto roundoff;
}
diff --git a/lib/libc/gdtoa/g_Qfmt.c b/lib/libc/gdtoa/g_Qfmt.c
index 2b9b3679963..15d1bdde459 100644
--- a/lib/libc/gdtoa/g_Qfmt.c
+++ b/lib/libc/gdtoa/g_Qfmt.c
@@ -51,15 +51,20 @@ THIS SOFTWARE.
char*
#ifdef KR_headers
-g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
+g_Qfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize;
#else
-g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize)
+g_Qfmt(char *buf, void *V, int ndig, size_t bufsize)
#endif
{
- static FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 };
+ static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 };
char *b, *s, *se;
ULong bits[4], *L, sign;
int decpt, ex, i, mode;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
if (ndig < 0)
ndig = 0;
@@ -109,6 +114,6 @@ g_Qfmt(char *buf, void *V, int ndig, unsigned bufsize)
return 0;
mode = 0;
}
- s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
- return g__fmt(buf, s, se, decpt, sign);
+ s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+ return g__fmt(buf, s, se, decpt, sign, bufsize);
}
diff --git a/lib/libc/gdtoa/g__fmt.c b/lib/libc/gdtoa/g__fmt.c
index 021ecfb5728..fbccb7d9897 100644
--- a/lib/libc/gdtoa/g__fmt.c
+++ b/lib/libc/gdtoa/g__fmt.c
@@ -37,24 +37,51 @@ THIS SOFTWARE.
char *
#ifdef KR_headers
-g__fmt(b, s, se, decpt, sign) char *b; char *s; char *se; int decpt; ULong sign;
+g__fmt(b, s, se, decpt, sign, blen) char *b; char *s; char *se; int decpt; ULong sign; size_t blen;
#else
-g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
+g__fmt(char *b, char *s, char *se, int decpt, ULong sign, size_t blen)
#endif
{
int i, j, k;
- char *s0 = s;
+ char *be, *s0;
+ size_t len;
#ifdef USE_LOCALE
- char decimalpoint = *localeconv()->decimal_point;
+#ifdef NO_LOCALE_CACHE
+ char *decimalpoint = localeconv()->decimal_point;
+ size_t dlen = strlen(decimalpoint);
#else
-#define decimalpoint '.'
+ char *decimalpoint;
+ static char *decimalpoint_cache;
+ static size_t dlen;
+ if (!(s0 = decimalpoint_cache)) {
+ s0 = localeconv()->decimal_point;
+ dlen = strlen(s0);
+ if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ strcpy(decimalpoint_cache, s0);
+ s0 = decimalpoint_cache;
+ }
+ }
+ decimalpoint = s0;
+#endif
+#else
+#define dlen 0
#endif
+ s0 = s;
+ len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */
+ if (blen < len)
+ goto ret0;
+ be = b + blen - 1;
if (sign)
*b++ = '-';
if (decpt <= -4 || decpt > se - s + 5) {
*b++ = *s++;
if (*s) {
- *b++ = decimalpoint;
+#ifdef USE_LOCALE
+ while((*b = *decimalpoint++))
+ ++b;
+#else
+ *b++ = '.';
+#endif
while((*b = *s++) !=0)
b++;
}
@@ -69,6 +96,8 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){}
for(;;) {
i = decpt / k;
+ if (b >= be)
+ goto ret0;
*b++ = i + '0';
if (--j <= 0)
break;
@@ -78,22 +107,41 @@ g__fmt(char *b, char *s, char *se, int decpt, ULong sign)
*b = 0;
}
else if (decpt <= 0) {
- *b++ = decimalpoint;
+#ifdef USE_LOCALE
+ while((*b = *decimalpoint++))
+ ++b;
+#else
+ *b++ = '.';
+#endif
+ if (be < b - decpt + (se - s))
+ goto ret0;
for(; decpt < 0; decpt++)
*b++ = '0';
- while((*b = *s++) !=0)
+ while((*b = *s++) != 0)
b++;
}
else {
- while((*b = *s++) !=0) {
+ while((*b = *s++) != 0) {
b++;
- if (--decpt == 0 && *s)
- *b++ = decimalpoint;
+ if (--decpt == 0 && *s) {
+#ifdef USE_LOCALE
+ while(*b = *decimalpoint++)
+ ++b;
+#else
+ *b++ = '.';
+#endif
+ }
+ }
+ if (b + decpt > be) {
+ ret0:
+ b = 0;
+ goto ret;
}
for(; decpt > 0; decpt--)
*b++ = '0';
*b = 0;
}
+ ret:
freedtoa(s0);
return b;
}
diff --git a/lib/libc/gdtoa/g_ddfmt.c b/lib/libc/gdtoa/g_ddfmt.c
index 7fc30578a90..b65d39d793c 100644
--- a/lib/libc/gdtoa/g_ddfmt.c
+++ b/lib/libc/gdtoa/g_ddfmt.c
@@ -33,9 +33,9 @@ THIS SOFTWARE.
char *
#ifdef KR_headers
-g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; unsigned bufsize;
+g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; size_t bufsize;
#else
-g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
+g_ddfmt(char *buf, double *dd, int ndig, size_t bufsize)
#endif
{
FPI fpi;
@@ -44,6 +44,21 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
int bx, by, decpt, ex, ey, i, j, mode;
Bigint *x, *y, *z;
double ddx[2];
+#ifdef Honor_FLT_ROUNDS /*{{*/
+ int Rounding;
+#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
+ Rounding = Flt_Rounds;
+#else /*}{*/
+ Rounding = 1;
+ switch(fegetround()) {
+ case FE_TOWARDZERO: Rounding = 0; break;
+ case FE_UPWARD: Rounding = 2; break;
+ case FE_DOWNWARD: Rounding = 3;
+ }
+#endif /*}}*/
+#else /*}{*/
+#define Rounding FPI_Round_near
+#endif /*}}*/
if (bufsize < 10 || bufsize < ndig + 8)
return 0;
@@ -144,11 +159,11 @@ g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
}
fpi.emin = 1-1023-53+1;
fpi.emax = 2046-1023-106+1;
- fpi.rounding = FPI_Round_near;
+ fpi.rounding = Rounding;
fpi.sudden_underflow = 0;
i = STRTOG_Normal;
s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
- b = g__fmt(buf, s, se, decpt, z->sign);
+ b = g__fmt(buf, s, se, decpt, z->sign, bufsize);
Bfree(z);
return b;
}
diff --git a/lib/libc/gdtoa/g_dfmt.c b/lib/libc/gdtoa/g_dfmt.c
index db2636f6da9..23d8b2470f4 100644
--- a/lib/libc/gdtoa/g_dfmt.c
+++ b/lib/libc/gdtoa/g_dfmt.c
@@ -33,15 +33,20 @@ THIS SOFTWARE.
char*
#ifdef KR_headers
-g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; unsigned bufsize;
+g_dfmt(buf, d, ndig, bufsize) char *buf; double *d; int ndig; size_t bufsize;
#else
-g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
+g_dfmt(char *buf, double *d, int ndig, size_t bufsize)
#endif
{
- static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
+ static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
char *b, *s, *se;
ULong bits[2], *L, sign;
int decpt, ex, i, mode;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
if (ndig < 0)
ndig = 0;
@@ -52,6 +57,8 @@ g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
sign = L[_0] & 0x80000000L;
if ((L[_0] & 0x7ff00000) == 0x7ff00000) {
/* Infinity or NaN */
+ if (bufsize < 10)
+ return 0;
if (L[_0] & 0xfffff || L[_1]) {
return strcp(buf, "NaN");
}
@@ -78,12 +85,9 @@ g_dfmt(char *buf, double *d, int ndig, unsigned bufsize)
ex = 1;
ex -= 0x3ff + 52;
mode = 2;
- if (ndig <= 0) {
- if (bufsize < 25)
- return 0;
+ if (ndig <= 0)
mode = 0;
- }
i = STRTOG_Normal;
- s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
- return g__fmt(buf, s, se, decpt, sign);
+ s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+ return g__fmt(buf, s, se, decpt, sign, bufsize);
}
diff --git a/lib/libc/gdtoa/g_ffmt.c b/lib/libc/gdtoa/g_ffmt.c
index 612adfae382..1c27c602b22 100644
--- a/lib/libc/gdtoa/g_ffmt.c
+++ b/lib/libc/gdtoa/g_ffmt.c
@@ -33,15 +33,20 @@ THIS SOFTWARE.
char*
#ifdef KR_headers
-g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; unsigned bufsize;
+g_ffmt(buf, f, ndig, bufsize) char *buf; float *f; int ndig; size_t bufsize;
#else
-g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
+g_ffmt(char *buf, float *f, int ndig, size_t bufsize)
#endif
{
- static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, 0 };
+ static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, 0 };
char *b, *s, *se;
ULong bits[1], *L, sign;
int decpt, ex, i, mode;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
if (ndig < 0)
ndig = 0;
@@ -83,6 +88,6 @@ g_ffmt(char *buf, float *f, int ndig, unsigned bufsize)
mode = 0;
}
i = STRTOG_Normal;
- s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
- return g__fmt(buf, s, se, decpt, sign);
+ s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+ return g__fmt(buf, s, se, decpt, sign, bufsize);
}
diff --git a/lib/libc/gdtoa/g_xLfmt.c b/lib/libc/gdtoa/g_xLfmt.c
index 1bbc6e215ed..6fa1de2dad6 100644
--- a/lib/libc/gdtoa/g_xLfmt.c
+++ b/lib/libc/gdtoa/g_xLfmt.c
@@ -49,15 +49,20 @@ THIS SOFTWARE.
char*
#ifdef KR_headers
-g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
+g_xLfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize;
#else
-g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize)
+g_xLfmt(char *buf, void *V, int ndig, size_t bufsize)
#endif
{
- static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
+ static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
char *b, *s, *se;
ULong bits[2], *L, sign;
int decpt, ex, i, mode;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
if (ndig < 0)
ndig = 0;
@@ -103,6 +108,6 @@ g_xLfmt(char *buf, void *V, int ndig, unsigned bufsize)
return 0;
mode = 0;
}
- s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
- return g__fmt(buf, s, se, decpt, sign);
+ s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+ return g__fmt(buf, s, se, decpt, sign, bufsize);
}
diff --git a/lib/libc/gdtoa/g_xfmt.c b/lib/libc/gdtoa/g_xfmt.c
index 47a862d6bc7..495c7b471e7 100644
--- a/lib/libc/gdtoa/g_xfmt.c
+++ b/lib/libc/gdtoa/g_xfmt.c
@@ -53,16 +53,21 @@ THIS SOFTWARE.
char*
#ifdef KR_headers
-g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; unsigned bufsize;
+g_xfmt(buf, V, ndig, bufsize) char *buf; char *V; int ndig; size_t bufsize;
#else
-g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
+g_xfmt(char *buf, void *V, int ndig, size_t bufsize)
#endif
{
- static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
+ static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
char *b, *s, *se;
ULong bits[2], sign;
UShort *L;
int decpt, ex, i, mode;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
if (ndig < 0)
ndig = 0;
@@ -109,6 +114,6 @@ g_xfmt(char *buf, void *V, int ndig, unsigned bufsize)
return 0;
mode = 0;
}
- s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
- return g__fmt(buf, s, se, decpt, sign);
+ s = gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se);
+ return g__fmt(buf, s, se, decpt, sign, bufsize);
}
diff --git a/lib/libc/gdtoa/gdtoa.c b/lib/libc/gdtoa/gdtoa.c
index 8ff8cc587ea..3b642508fe9 100644
--- a/lib/libc/gdtoa/gdtoa.c
+++ b/lib/libc/gdtoa/gdtoa.c
@@ -417,11 +417,9 @@ gdtoa
if (dval(d) > ds + dval(eps))
goto bump_up;
else if (dval(d) < ds - dval(eps)) {
- while(*--s == '0'){}
- s++;
if (dval(d))
inex = STRTOG_Inexlo;
- goto ret1;
+ goto clear_trailing0;
}
break;
}
@@ -479,8 +477,12 @@ gdtoa
}
++*s++;
}
- else
+ else {
inex = STRTOG_Inexlo;
+ clear_trailing0:
+ while(*--s == '0'){}
+ ++s;
+ }
break;
}
}
@@ -738,7 +740,7 @@ gdtoa
if (b->wds > 1 || b->x[0])
inex = STRTOG_Inexlo;
while(*--s == '0'){}
- s++;
+ ++s;
}
ret:
Bfree(S);
diff --git a/lib/libc/gdtoa/gdtoa.h b/lib/libc/gdtoa/gdtoa.h
index ee6a9e53faf..e59ebf65d08 100644
--- a/lib/libc/gdtoa/gdtoa.h
+++ b/lib/libc/gdtoa/gdtoa.h
@@ -33,6 +33,7 @@ THIS SOFTWARE.
#define GDTOA_H_INCLUDED
#include "arith.h"
+#include <stddef.h> /* for size_t */
#ifndef Long
#define Long long
@@ -74,9 +75,9 @@ typedef unsigned short UShort;
/* The following may be or-ed into one of the above values. */
- STRTOG_Neg = 0x08,
- STRTOG_Inexlo = 0x10,
- STRTOG_Inexhi = 0x20,
+ STRTOG_Neg = 0x08, /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */
+ STRTOG_Inexlo = 0x10, /* returned result rounded toward zero */
+ STRTOG_Inexhi = 0x20, /* returned result rounded away from zero */
STRTOG_Inexact = 0x30,
STRTOG_Underflow= 0x40,
STRTOG_Overflow = 0x80
@@ -111,12 +112,12 @@ extern float strtof ANSI((CONST char *, char **));
extern double strtod ANSI((CONST char *, char **));
extern int strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
-extern char* g_ddfmt ANSI((char*, double*, int, unsigned));
-extern char* g_dfmt ANSI((char*, double*, int, unsigned));
-extern char* g_ffmt ANSI((char*, float*, int, unsigned));
-extern char* g_Qfmt ANSI((char*, void*, int, unsigned));
-extern char* g_xfmt ANSI((char*, void*, int, unsigned));
-extern char* g_xLfmt ANSI((char*, void*, int, unsigned));
+extern char* g_ddfmt ANSI((char*, double*, int, size_t));
+extern char* g_dfmt ANSI((char*, double*, int, size_t));
+extern char* g_ffmt ANSI((char*, float*, int, size_t));
+extern char* g_Qfmt ANSI((char*, void*, int, size_t));
+extern char* g_xfmt ANSI((char*, void*, int, size_t));
+extern char* g_xLfmt ANSI((char*, void*, int, size_t));
extern int strtoId ANSI((CONST char*, char**, double*, double*));
extern int strtoIdd ANSI((CONST char*, char**, double*, double*));
diff --git a/lib/libc/gdtoa/gdtoa_fltrnds.h b/lib/libc/gdtoa/gdtoa_fltrnds.h
new file mode 100644
index 00000000000..33e5f9e5342
--- /dev/null
+++ b/lib/libc/gdtoa/gdtoa_fltrnds.h
@@ -0,0 +1,18 @@
+ FPI *fpi, fpi1;
+ int Rounding;
+#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
+ Rounding = Flt_Rounds;
+#else /*}{*/
+ Rounding = 1;
+ switch(fegetround()) {
+ case FE_TOWARDZERO: Rounding = 0; break;
+ case FE_UPWARD: Rounding = 2; break;
+ case FE_DOWNWARD: Rounding = 3;
+ }
+#endif /*}}*/
+ fpi = &fpi0;
+ if (Rounding != 1) {
+ fpi1 = fpi0;
+ fpi = &fpi1;
+ fpi1.rounding = Rounding;
+ }
diff --git a/lib/libc/gdtoa/gdtoaimp.h b/lib/libc/gdtoa/gdtoaimp.h
index e850dae5a55..4ece8801d37 100644
--- a/lib/libc/gdtoa/gdtoaimp.h
+++ b/lib/libc/gdtoa/gdtoaimp.h
@@ -151,7 +151,7 @@ THIS SOFTWARE.
* dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
* #define IMPRECISE_INEXACT if you do not care about the setting of
* the STRTOG_Inexact bits in the special case of doing IEEE double
- * precision conversions (which could also be done by the strtog in
+ * precision conversions (which could also be done by the strtod in
* dtoa.c).
* #define NO_HEX_FP to disable recognition of C9x's hexadecimal
* floating-point constants.
@@ -175,6 +175,9 @@ THIS SOFTWARE.
#include "gdtoa.h"
#include "gd_qnan.h"
+#ifdef Honor_FLT_ROUNDS
+#include <fenv.h>
+#endif
#ifdef DEBUG
#include "stdio.h"
@@ -580,13 +583,13 @@ extern void memcpy_D2A ANSI((void*, const void*, size_t));
extern int cmp ANSI((Bigint*, Bigint*));
extern void copybits ANSI((ULong*, int, Bigint*));
extern Bigint *d2b ANSI((double, int*, int*));
- extern int decrement ANSI((Bigint*));
+ extern void decrement ANSI((Bigint*));
extern Bigint *diff ANSI((Bigint*, Bigint*));
extern char *dtoa ANSI((double d, int mode, int ndigits,
int *decpt, int *sign, char **rve));
extern char *gdtoa ANSI((FPI *fpi, int be, ULong *bits, int *kindp,
- int mode, int ndigits, int *decpt, char **rve));
- extern char *g__fmt ANSI((char*, char*, char*, int, ULong));
+ int mode, int ndigits, int *decpt, char **rve));
+ extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t));
extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int));
extern void hexdig_init_D2A(Void);
extern int hexnan ANSI((CONST char**, FPI*, ULong*));
diff --git a/lib/libc/gdtoa/gethex.c b/lib/libc/gdtoa/gethex.c
index f130fd53112..13908e5be79 100644
--- a/lib/libc/gdtoa/gethex.c
+++ b/lib/libc/gdtoa/gethex.c
@@ -45,17 +45,30 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
{
Bigint *b;
CONST unsigned char *decpt, *s0, *s, *s1;
- int esign, havedig, irv, k, n, nbits, up, zret;
+ int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret;
ULong L, lostbits, *x;
Long e, e1;
#ifdef USE_LOCALE
- unsigned char decimalpoint = *localeconv()->decimal_point;
+ int i;
+#ifdef NO_LOCALE_CACHE
+ const unsigned char *decimalpoint = (unsigned char*)localeconv()->decimal_point;
#else
-#define decimalpoint '.'
+ const unsigned char *decimalpoint;
+ static unsigned char *decimalpoint_cache;
+ if (!(s0 = decimalpoint_cache)) {
+ s0 = (unsigned char*)localeconv()->decimal_point;
+ if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ strcpy(decimalpoint_cache, s0);
+ s0 = decimalpoint_cache;
+ }
+ }
+ decimalpoint = s0;
+#endif
#endif
if (!hexdig['0'])
hexdig_init_D2A();
+ *bp = 0;
havedig = 0;
s0 = *(CONST unsigned char **)sp + 2;
while(s0[havedig] == '0')
@@ -65,11 +78,21 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
decpt = 0;
zret = 0;
e = 0;
- if (!hexdig[*s]) {
+ if (hexdig[*s])
+ havedig++;
+ else {
zret = 1;
- if (*s != decimalpoint)
+#ifdef USE_LOCALE
+ for(i = 0; decimalpoint[i]; ++i) {
+ if (s[i] != decimalpoint[i])
+ goto pcheck;
+ }
+ decpt = s += i;
+#else
+ if (*s != '.')
goto pcheck;
decpt = ++s;
+#endif
if (!hexdig[*s])
goto pcheck;
while(*s == '0')
@@ -81,19 +104,28 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
}
while(hexdig[*s])
s++;
- if (*s == decimalpoint && !decpt) {
+#ifdef USE_LOCALE
+ if (*s == *decimalpoint && !decpt) {
+ for(i = 1; decimalpoint[i]; ++i) {
+ if (s[i] != decimalpoint[i])
+ goto pcheck;
+ }
+ decpt = s += i;
+#else
+ if (*s == '.' && !decpt) {
decpt = ++s;
+#endif
while(hexdig[*s])
s++;
- }
+ }/*}*/
if (decpt)
e = -(((Long)(s-decpt)) << 2);
pcheck:
s1 = s;
+ big = esign = 0;
switch(*s) {
case 'p':
case 'P':
- esign = 0;
switch(*++s) {
case '-':
esign = 1;
@@ -106,17 +138,65 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
break;
}
e1 = n - 0x10;
- while((n = hexdig[*++s]) !=0 && n <= 0x19)
+ while((n = hexdig[*++s]) !=0 && n <= 0x19) {
+ if (e1 & 0xf8000000)
+ big = 1;
e1 = 10*e1 + n - 0x10;
+ }
if (esign)
e1 = -e1;
e += e1;
}
*sp = (char*)s;
- if (zret) {
- if (!havedig)
- *sp = s0 - 1;
+ if (!havedig)
+ *sp = (char*)s0 - 1;
+ if (zret)
return STRTOG_Zero;
+ if (big) {
+ if (esign) {
+ switch(fpi->rounding) {
+ case FPI_Round_up:
+ if (sign)
+ break;
+ goto ret_tiny;
+ case FPI_Round_down:
+ if (!sign)
+ break;
+ goto ret_tiny;
+ }
+ goto retz;
+ ret_tiny:
+ b = Balloc(0);
+ b->wds = 1;
+ b->x[0] = 1;
+ goto dret;
+ }
+ switch(fpi->rounding) {
+ case FPI_Round_near:
+ goto ovfl1;
+ case FPI_Round_up:
+ if (!sign)
+ goto ovfl1;
+ goto ret_big;
+ case FPI_Round_down:
+ if (sign)
+ goto ovfl1;
+ goto ret_big;
+ }
+ ret_big:
+ nbits = fpi->nbits;
+ n0 = n = nbits >> kshift;
+ if (nbits & kmask)
+ ++n;
+ for(j = n, k = 0; j >>= 1; ++k);
+ *bp = b = Balloc(k);
+ b->wds = n;
+ for(j = 0; j < n0; ++j)
+ b->x[j] = ALL_ON;
+ if (n > n0)
+ b->x[j] = ULbits >> (ULbits - (nbits & kmask));
+ *exp = fpi->emin;
+ return STRTOG_Normal | STRTOG_Inexlo;
}
n = s1 - s0 - 1;
for(k = 0; n > 7; n >>= 1)
@@ -125,9 +205,19 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
x = b->x;
n = 0;
L = 0;
+#ifdef USE_LOCALE
+ for(i = 0; decimalpoint[i+1]; ++i);
+#endif
while(s1 > s0) {
- if (*--s1 == decimalpoint)
+#ifdef USE_LOCALE
+ if (*--s1 == decimalpoint[i]) {
+ s1 -= i;
continue;
+ }
+#else
+ if (*--s1 == '.')
+ continue;
+#endif
if (n == 32) {
*x++ = L;
L = 0;
@@ -149,7 +239,7 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
k = n - 1;
if (x[k>>kshift] & 1 << (k & kmask)) {
lostbits = 2;
- if (k > 1 && any_on(b,k-1))
+ if (k > 0 && any_on(b,k))
lostbits = 3;
}
}
@@ -165,7 +255,10 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
if (e > fpi->emax) {
ovfl:
Bfree(b);
- *bp = 0;
+ ovfl1:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
}
irv = STRTOG_Normal;
@@ -185,15 +278,22 @@ gethex( CONST char **sp, FPI *fpi, Long *exp, Bigint **bp, int sign)
case FPI_Round_down:
if (sign) {
one_bit:
- *exp = fpi->emin;
x[0] = b->wds = 1;
+ dret:
*bp = b;
+ *exp = fpi->emin;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
return STRTOG_Denormal | STRTOG_Inexhi
| STRTOG_Underflow;
}
}
Bfree(b);
- *bp = 0;
+ retz:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow;
}
k = n - 1;
diff --git a/lib/libc/gdtoa/strtoIg.c b/lib/libc/gdtoa/strtoIg.c
index ec46a3ebb75..90c88db3283 100644
--- a/lib/libc/gdtoa/strtoIg.c
+++ b/lib/libc/gdtoa/strtoIg.c
@@ -61,12 +61,16 @@ strtoIg(CONST char *s00, char **se, FPI *fpi, Long *exp, Bigint **B, int *rvp)
if (rv & STRTOG_Inexlo) {
swap = 0;
b1 = increment(b1);
- if (fpi->sudden_underflow
- && (rv & STRTOG_Retmask) == STRTOG_Zero) {
- b1->x[0] = 0;
- b1->x[nw1] = 1L << nb11;
- rv1 += STRTOG_Normal - STRTOG_Zero;
- rv1 &= ~STRTOG_Underflow;
+ if ((rv & STRTOG_Retmask) == STRTOG_Zero) {
+ if (fpi->sudden_underflow) {
+ b1->x[0] = 0;
+ b1->x[nw1] = 1L << nb11;
+ rv1 += STRTOG_Normal - STRTOG_Zero;
+ rv1 &= ~STRTOG_Underflow;
+ goto swapcheck;
+ }
+ rv1 &= STRTOG_Inexlo | STRTOG_Underflow | STRTOG_Zero;
+ rv1 |= STRTOG_Inexhi | STRTOG_Denormal;
goto swapcheck;
}
if (b1->wds > nw
diff --git a/lib/libc/gdtoa/strtod.c b/lib/libc/gdtoa/strtod.c
index 66a3baa2bc3..62a6ffbf04f 100644
--- a/lib/libc/gdtoa/strtod.c
+++ b/lib/libc/gdtoa/strtod.c
@@ -42,16 +42,15 @@ THIS SOFTWARE.
#ifndef NO_IEEE_Scale
#define Avoid_Underflow
#undef tinytens
-/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
+/* The factor of 2^106 in tinytens[4] helps us avoid setting the underflow */
/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
- 9007199254740992.e-256
+ 9007199254740992.*9007199254740992.e-256
};
#endif
#endif
#ifdef Honor_FLT_ROUNDS
-#define Rounding rounding
#undef Check_FLT_ROUNDS
#define Check_FLT_ROUNDS
#else
@@ -79,9 +78,35 @@ strtod
#ifdef SET_INEXACT
int inexact, oldinexact;
#endif
-#ifdef Honor_FLT_ROUNDS
- int rounding;
-#endif
+#ifdef USE_LOCALE
+#ifdef NO_LOCALE_CACHE
+ char *decimalpoint = localeconv()->decimal_point;
+#else
+ char *decimalpoint;
+ static char *decimalpoint_cache;
+ if (!(s0 = decimalpoint_cache)) {
+ s0 = localeconv()->decimal_point;
+ if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ strcpy(decimalpoint_cache, s0);
+ s0 = decimalpoint_cache;
+ }
+ }
+ decimalpoint = (char*)s0;
+#endif
+#endif
+#ifdef Honor_FLT_ROUNDS /*{*/
+ int Rounding;
+#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */
+ Rounding = Flt_Rounds;
+#else /*}{*/
+ Rounding = 1;
+ switch(fegetround()) {
+ case FE_TOWARDZERO: Rounding = 0; break;
+ case FE_UPWARD: Rounding = 2; break;
+ case FE_DOWNWARD: Rounding = 3;
+ }
+#endif /*}}*/
+#endif /*}*/
sign = nz0 = nz = decpt = 0;
dval(rv) = 0.;
@@ -107,7 +132,7 @@ strtod
}
break2:
if (*s == '0') {
-#ifndef NO_HEX_FP
+#ifndef NO_HEX_FP /*{{*/
{
static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI };
Long exp;
@@ -116,16 +141,20 @@ strtod
case 'x':
case 'X':
{
-#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD)
+#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD) /*{{*/
FPI fpi1 = fpi;
+#ifdef Honor_FLT_ROUNDS /*{{*/
+ fpi1.rounding = Rounding;
+#else /*}{*/
switch(fegetround()) {
case FE_TOWARDZERO: fpi1.rounding = 0; break;
case FE_UPWARD: fpi1.rounding = 2; break;
case FE_DOWNWARD: fpi1.rounding = 3;
}
-#else
+#endif /*}}*/
+#else /*}{*/
#define fpi1 fpi
-#endif
+#endif /*}}*/
switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
@@ -157,13 +186,17 @@ strtod
z = 10*z + c - '0';
nd0 = nd;
#ifdef USE_LOCALE
- if (c == *localeconv()->decimal_point)
+ if (c == *decimalpoint) {
+ for(i = 1; decimalpoint[i]; ++i)
+ if (s[i] != decimalpoint[i])
+ goto dig_done;
+ s += i;
+ c = *s;
#else
- if (c == '.')
+ if (c == '.') {
+ c = *++s;
#endif
- {
decpt = 1;
- c = *++s;
if (!nd) {
for(; c == '0'; c = *++s)
nz++;
@@ -192,7 +225,7 @@ strtod
nz = 0;
}
}
- }
+ }/*}*/
dig_done:
e = 0;
if (c == 'e' || c == 'E') {
@@ -379,12 +412,12 @@ strtod
scale = 0;
#endif
#ifdef Honor_FLT_ROUNDS
- if ((rounding = Flt_Rounds) >= 2) {
+ if (Rounding >= 2) {
if (sign)
- rounding = rounding == 2 ? 0 : 2;
+ Rounding = Rounding == 2 ? 0 : 2;
else
- if (rounding != 2)
- rounding = 0;
+ if (Rounding != 2)
+ Rounding = 0;
}
#endif
#endif /*IEEE_Arith*/
@@ -403,7 +436,7 @@ strtod
/* Can't trust HUGE_VAL */
#ifdef IEEE_Arith
#ifdef Honor_FLT_ROUNDS
- switch(rounding) {
+ switch(Rounding) {
case 0: /* toward 0 */
case 3: /* toward -infinity */
word0(rv) = Big0;
@@ -534,7 +567,7 @@ strtod
bd2 -= bbe;
bs2 = bb2;
#ifdef Honor_FLT_ROUNDS
- if (rounding != 1)
+ if (Rounding != 1)
bs2++;
#endif
#ifdef Avoid_Underflow
@@ -592,7 +625,7 @@ strtod
delta->sign = 0;
i = cmp(delta, bs);
#ifdef Honor_FLT_ROUNDS
- if (rounding != 1) {
+ if (Rounding != 1) {
if (i < 0) {
/* Error is less than an ulp */
if (!delta->x[0] && delta->wds <= 1) {
@@ -602,7 +635,7 @@ strtod
#endif
break;
}
- if (rounding) {
+ if (Rounding) {
if (dsign) {
adj = 1.;
goto apply_adj;
@@ -648,10 +681,10 @@ strtod
if (adj < 1.)
adj = 1.;
if (adj <= 0x7ffffffe) {
- /* adj = rounding ? ceil(adj) : floor(adj); */
+ /* adj = Rounding ? ceil(adj) : floor(adj); */
y = adj;
if (y != adj) {
- if (!((rounding>>1) ^ dsign))
+ if (!((Rounding>>1) ^ dsign))
y++;
adj = y;
}
@@ -674,8 +707,11 @@ strtod
#endif /*Sudden_Underflow*/
#endif /*Avoid_Underflow*/
adj *= ulp(dval(rv));
- if (dsign)
+ if (dsign) {
+ if (word0(rv) == Big0 && word1(rv) == Big1)
+ goto ovfl;
dval(rv) += adj;
+ }
else
dval(rv) -= adj;
goto cont;
@@ -768,7 +804,7 @@ strtod
}
#endif /*Avoid_Underflow*/
L = (word0(rv) & Exp_mask) - Exp_msk1;
-#endif /*Sudden_Underflow}*/
+#endif /*Sudden_Underflow}}*/
word0(rv) = L | Bndry_mask1;
word1(rv) = 0xffffffff;
#ifdef IBM
@@ -956,7 +992,11 @@ strtod
dval(rv) *= dval(rv0);
#ifndef NO_ERRNO
/* try to avoid the bug of testing an 8087 register value */
+#ifdef IEEE_Arith
+ if (!(word0(rv) & Exp_mask))
+#else
if (word0(rv) == 0 && word1(rv) == 0)
+#endif
errno = ERANGE;
#endif
}
diff --git a/lib/libc/gdtoa/strtodg.c b/lib/libc/gdtoa/strtodg.c
index 0c008737813..41ead32decb 100644
--- a/lib/libc/gdtoa/strtodg.c
+++ b/lib/libc/gdtoa/strtodg.c
@@ -89,7 +89,7 @@ increment(Bigint *b)
return b;
}
- int
+ void
#ifdef KR_headers
decrement(b) Bigint *b;
#else
@@ -119,7 +119,6 @@ decrement(Bigint *b)
*x++ = y & 0xffff;
} while(borrow && x < xe);
#endif
- return STRTOG_Inexlo;
}
static int
@@ -206,9 +205,9 @@ rvOK
goto ret;
}
switch(rd) {
- case 1:
+ case 1: /* round down (toward -Infinity) */
goto trunc;
- case 2:
+ case 2: /* round up (toward +Infinity) */
break;
default: /* round near */
k = bdif - 1;
@@ -330,8 +329,24 @@ strtodg
CONST char *s, *s0, *s1;
double adj, adj0, rv, tol;
Long L;
- ULong y, z;
+ ULong *b, *be, y, z;
Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
+#ifdef USE_LOCALE
+#ifdef NO_LOCALE_CACHE
+ char *decimalpoint = localeconv()->decimal_point;
+#else
+ char *decimalpoint;
+ static char *decimalpoint_cache;
+ if (!(s0 = decimalpoint_cache)) {
+ s0 = localeconv()->decimal_point;
+ if ((decimalpoint_cache = (char*)malloc(strlen(s0) + 1))) {
+ strcpy(decimalpoint_cache, s0);
+ s0 = decimalpoint_cache;
+ }
+ }
+ decimalpoint = (char*)s0;
+#endif
+#endif
irv = STRTOG_Zero;
denorm = sign = nz0 = nz = 0;
@@ -390,13 +405,17 @@ strtodg
z = 10*z + c - '0';
nd0 = nd;
#ifdef USE_LOCALE
- if (c == *localeconv()->decimal_point)
+ if (c == *decimalpoint) {
+ for(i = 1; decimalpoint[i]; ++i)
+ if (s[i] != decimalpoint[i])
+ goto dig_done;
+ s += i;
+ c = *s;
#else
- if (c == '.')
+ if (c == '.') {
+ c = *++s;
#endif
- {
decpt = 1;
- c = *++s;
if (!nd) {
for(; c == '0'; c = *++s)
nz++;
@@ -425,7 +444,7 @@ strtodg
nz = 0;
}
}
- }
+ }/*}*/
dig_done:
e = 0;
if (c == 'e' || c == 'E') {
@@ -976,6 +995,29 @@ strtodg
Bfree(bd0);
Bfree(delta);
if (rve > fpi->emax) {
+ switch(fpi->rounding & 3) {
+ case FPI_Round_near:
+ goto huge;
+ case FPI_Round_up:
+ if (!sign)
+ goto huge;
+ break;
+ case FPI_Round_down:
+ if (sign)
+ goto huge;
+ }
+ /* Round to largest representable magnitude */
+ Bfree(rvb);
+ rvb = 0;
+ irv = STRTOG_Normal | STRTOG_Inexlo;
+ *exp = fpi->emax;
+ b = bits;
+ be = b + ((fpi->nbits + 31) >> 5);
+ while(b < be)
+ *b++ = -1;
+ if ((j = fpi->nbits & 0x1f))
+ *--be >>= (32 - j);
+ goto ret;
huge:
rvb->wds = 0;
irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
@@ -990,12 +1032,19 @@ strtodg
if (sudden_underflow) {
rvb->wds = 0;
irv = STRTOG_Underflow | STRTOG_Inexlo;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
}
else {
irv = (irv & ~STRTOG_Retmask) |
(rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
- if (irv & STRTOG_Inexact)
+ if (irv & STRTOG_Inexact) {
irv |= STRTOG_Underflow;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ }
}
}
if (se)
diff --git a/lib/libc/gdtoa/strtof.c b/lib/libc/gdtoa/strtof.c
index 21bc6c15bfe..f8111b716c2 100644
--- a/lib/libc/gdtoa/strtof.c
+++ b/lib/libc/gdtoa/strtof.c
@@ -38,13 +38,18 @@ strtof(s, sp) CONST char *s; char **sp;
strtof(CONST char *s, char **sp)
#endif
{
- static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
+ static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
ULong bits[1];
Long exp;
int k;
union { ULong L[1]; float f; } u;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
- k = strtodg(s, sp, &fpi, &exp, bits);
+ k = strtodg(s, sp, fpi, &exp, bits);
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
case STRTOG_Zero:
diff --git a/lib/libc/gdtoa/strtopQ.c b/lib/libc/gdtoa/strtopQ.c
index dd5dab826c9..77f31903374 100644
--- a/lib/libc/gdtoa/strtopQ.c
+++ b/lib/libc/gdtoa/strtopQ.c
@@ -56,13 +56,18 @@ strtopQ(s, sp, V) CONST char *s; char **sp; void *V;
strtopQ(CONST char *s, char **sp, void *V)
#endif
{
- static FPI fpi = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI };
+ static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, SI };
ULong bits[4];
Long exp;
int k;
ULong *L = (ULong*)V;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
- k = strtodg(s, sp, &fpi, &exp, bits);
+ k = strtodg(s, sp, fpi, &exp, bits);
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
case STRTOG_Zero:
diff --git a/lib/libc/gdtoa/strtopd.c b/lib/libc/gdtoa/strtopd.c
index 42c57fcc1fc..0fb35daeaa5 100644
--- a/lib/libc/gdtoa/strtopd.c
+++ b/lib/libc/gdtoa/strtopd.c
@@ -42,8 +42,13 @@ strtopd(CONST char *s, char **sp, double *d)
ULong bits[2];
Long exp;
int k;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
- k = strtodg(s, sp, &fpi0, &exp, bits);
+ k = strtodg(s, sp, fpi, &exp, bits);
ULtod((ULong*)d, bits, exp, k);
return k;
}
diff --git a/lib/libc/gdtoa/strtopdd.c b/lib/libc/gdtoa/strtopdd.c
index 9b788eecc9a..c6659761abb 100644
--- a/lib/libc/gdtoa/strtopdd.c
+++ b/lib/libc/gdtoa/strtopdd.c
@@ -39,9 +39,9 @@ strtopdd(CONST char *s, char **sp, double *dd)
#endif
{
#ifdef Sudden_Underflow
- static FPI fpi = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
+ static FPI fpi0 = { 106, 1-1023, 2046-1023-106+1, 1, 1 };
#else
- static FPI fpi = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
+ static FPI fpi0 = { 106, 1-1023-53+1, 2046-1023-106+1, 1, 0 };
#endif
ULong bits[4];
Long exp;
@@ -51,8 +51,13 @@ strtopdd(CONST char *s, char **sp, double *dd)
ULong L[4];
} U;
U *u;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
- rv = strtodg(s, sp, &fpi, &exp, bits);
+ rv = strtodg(s, sp, fpi, &exp, bits);
u = (U*)dd;
switch(rv & STRTOG_Retmask) {
case STRTOG_NoNumber:
diff --git a/lib/libc/gdtoa/strtopf.c b/lib/libc/gdtoa/strtopf.c
index cc7c970cba4..74694a07ef5 100644
--- a/lib/libc/gdtoa/strtopf.c
+++ b/lib/libc/gdtoa/strtopf.c
@@ -38,12 +38,17 @@ strtopf(s, sp, f) CONST char *s; char **sp; float *f;
strtopf(CONST char *s, char **sp, float *f)
#endif
{
- static FPI fpi = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
+ static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI };
ULong bits[1], *L;
Long exp;
int k;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
- k = strtodg(s, sp, &fpi, &exp, bits);
+ k = strtodg(s, sp, fpi, &exp, bits);
L = (ULong*)f;
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
diff --git a/lib/libc/gdtoa/strtopx.c b/lib/libc/gdtoa/strtopx.c
index 4dcb06ae73c..07d04587b00 100644
--- a/lib/libc/gdtoa/strtopx.c
+++ b/lib/libc/gdtoa/strtopx.c
@@ -58,13 +58,18 @@ strtopx(s, sp, V) CONST char *s; char **sp; void *V;
strtopx(CONST char *s, char **sp, void *V)
#endif
{
- static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
+ static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
ULong bits[2];
Long exp;
int k;
UShort *L = (UShort*)V;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
- k = strtodg(s, sp, &fpi, &exp, bits);
+ k = strtodg(s, sp, fpi, &exp, bits);
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
case STRTOG_Zero:
diff --git a/lib/libc/gdtoa/strtopxL.c b/lib/libc/gdtoa/strtopxL.c
index 68c83d2bdae..b0f5cdd0d81 100644
--- a/lib/libc/gdtoa/strtopxL.c
+++ b/lib/libc/gdtoa/strtopxL.c
@@ -54,13 +54,18 @@ strtopxL(s, sp, V) CONST char *s; char **sp; void *V;
strtopxL(CONST char *s, char **sp, void *V)
#endif
{
- static FPI fpi = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
+ static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI };
ULong bits[2];
Long exp;
int k;
ULong *L = (ULong*)V;
+#ifdef Honor_FLT_ROUNDS
+#include "gdtoa_fltrnds.h"
+#else
+#define fpi &fpi0
+#endif
- k = strtodg(s, sp, &fpi, &exp, bits);
+ k = strtodg(s, sp, fpi, &exp, bits);
switch(k & STRTOG_Retmask) {
case STRTOG_NoNumber:
case STRTOG_Zero: