gdtoa-strtod.c.patch   [plain text]


--- gdtoa-strtod.c.orig	2010-01-29 16:43:20.000000000 -0800
+++ gdtoa-strtod.c	2010-01-29 18:05:44.000000000 -0800
@@ -29,6 +29,8 @@ THIS SOFTWARE.
 /* Please send bug reports to David M. Gay (dmg at acm dot org,
  * with " at " changed at "@" and " dot " changed to ".").	*/
 
+#include "xlocale_private.h"
+
 #include "gdtoaimp.h"
 #ifndef NO_FENV_H
 #include <fenv.h>
@@ -58,11 +60,11 @@ static CONST double tinytens[] = { 1e-16
 #endif
 
  double
-strtod
+strtod_l
 #ifdef KR_headers
-	(s00, se) CONST char *s00; char **se;
+	(s00, se, loc) CONST char *s00; char **se; locale_t loc;
 #else
-	(CONST char *s00, char **se)
+	(CONST char *s00, char **se, locale_t loc)
 #endif
 {
 #ifdef Avoid_Underflow
@@ -71,6 +73,7 @@ strtod
 	int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, dsign,
 		 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
 	CONST char *s, *s0, *s1;
+	char *strunc = NULL;
 	double aadj;
 	Long L;
 	U adj, aadj1, rv, rv0;
@@ -80,15 +83,16 @@ strtod
 	int inexact, oldinexact;
 #endif
 #ifdef USE_LOCALE /*{{*/
+	NORMALIZE_LOCALE(loc);
 #ifdef NO_LOCALE_CACHE
-	char *decimalpoint = localeconv()->decimal_point;
+	char *decimalpoint = localeconv_l(loc)->decimal_point;
 	int dplen = strlen(decimalpoint);
 #else
 	char *decimalpoint;
 	static char *decimalpoint_cache;
 	static int dplen;
 	if (!(s0 = decimalpoint_cache)) {
-		s0 = localeconv()->decimal_point;
+		s0 = localeconv_l(loc)->decimal_point;
 		if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
 			strcpy(decimalpoint_cache, s0);
 			s0 = decimalpoint_cache;
@@ -154,7 +158,7 @@ strtod
 #else
 #define fpi1 fpi
 #endif
-			switch((i = gethex(&s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
+			switch((i = gethex(&s, &fpi1, &exp, &bb, sign, loc)) & STRTOG_Retmask) {
 			  case STRTOG_NoNumber:
 				s = s00;
 				sign = 0;
@@ -310,6 +314,9 @@ strtod
 			}
 		goto ret;
 		}
+#define FPIEMIN (1-1023-53+1)	// fpi.emin
+#define FPINBITS 52		// fpi.nbits
+	TRUNCATE_DIGITS(s0, strunc, nd, nd0, nf, FPINBITS, FPIEMIN, dplen);
 	e1 = e -= nf;
 
 	/* Now we have nd0 digits, starting at s0, followed by a
@@ -346,7 +353,7 @@ strtod
 #ifdef Honor_FLT_ROUNDS
 				/* round correctly FLT_ROUNDS = 2 or 3 */
 				if (sign) {
-					rv = -rv;
+					dval(&rv) = -dval(&rv);
 					sign = 0;
 					}
 #endif
@@ -362,7 +369,7 @@ strtod
 #ifdef Honor_FLT_ROUNDS
 				/* round correctly FLT_ROUNDS = 2 or 3 */
 				if (sign) {
-					rv = -rv;
+					dval(&rv) = -dval(&rv);
 					sign = 0;
 					}
 #endif
@@ -390,7 +397,7 @@ strtod
 #ifdef Honor_FLT_ROUNDS
 			/* round correctly FLT_ROUNDS = 2 or 3 */
 			if (sign) {
-				rv = -rv;
+				dval(&rv) = -dval(&rv);
 				sign = 0;
 				}
 #endif
@@ -672,17 +679,17 @@ strtod
 					else
 #endif /*Sudden_Underflow*/
 #endif /*Avoid_Underflow*/
-					dval(&rv) += adj*ulp(&rv);
+					dval(&rv) += dval(&adj)*ulp(&rv);
 					}
 				break;
 				}
 			dval(&adj) = ratio(delta, bs);
-			if (adj < 1.)
+			if (dval(&adj) < 1.)
 				dval(&adj) = 1.;
-			if (adj <= 0x7ffffffe) {
+			if (dval(&adj) <= 0x7ffffffe) {
 				/* dval(&adj) = Rounding ? ceil(&adj) : floor(&adj); */
-				y = adj;
-				if (y != adj) {
+				y = dval(&adj);
+				if (y != dval(&adj)) {
 					if (!((Rounding>>1) ^ dsign))
 						y++;
 					dval(&adj) = y;
@@ -709,10 +716,10 @@ strtod
 			if (dsign) {
 				if (word0(&rv) == Big0 && word1(&rv) == Big1)
 					goto ovfl;
-				dval(&rv) += adj;
+				dval(&rv) += dval(&adj);
 				}
 			else
-				dval(&rv) -= adj;
+				dval(&rv) -= dval(&adj);
 			goto cont;
 			}
 #endif /*Honor_FLT_ROUNDS*/
@@ -991,7 +998,7 @@ strtod
 		dval(&rv) *= dval(&rv0);
 #ifndef NO_ERRNO
 		/* try to avoid the bug of testing an 8087 register value */
-#ifdef IEEE_Arith
+#if defined(IEEE_Arith) && __DARWIN_UNIX03
 		if (!(word0(&rv) & Exp_mask))
 #else
 		if (word0(&rv) == 0 && word1(&rv) == 0)
@@ -1016,6 +1023,22 @@ strtod
  ret:
 	if (se)
 		*se = (char *)s;
+	if (strunc)
+#ifdef FREE
+		FREE(strunc);
+#else
+		free(strunc);
+#endif
 	return sign ? -dval(&rv) : dval(&rv);
 	}
 
+ double
+strtod
+#ifdef KR_headers
+	(s00, se) CONST char *s00; char **se;
+#else
+	(CONST char *s00, char **se)
+#endif
+{
+	return strtod_l(s00, se, __current_locale());
+}