about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--stdlib/strtod.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/stdlib/strtod.c b/stdlib/strtod.c
index 49ef2898be..72d2fe453f 100644
--- a/stdlib/strtod.c
+++ b/stdlib/strtod.c
@@ -698,10 +698,7 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
      decimal point, exponent character or any non-FP number character.  */
   startp = cp;
   dig_no = 0;
-  while (dig_no < (base == 16 ? HEXNDIG : NDIG) ||
-	 /* If parsing grouping info, keep going past useful digits
-	    so we can check all the grouping separators.  */
-	 grouping)
+  while (1)
     {
       if ((c >= L_('0') && c <= L_('9'))
 	  || (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f')))
@@ -760,11 +757,6 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
 	}
     }
 
-  if (dig_no >= (base == 16 ? HEXNDIG : NDIG))
-    /* Too many digits to be representable.  Assigning this to EXPONENT
-       allows us to read the full number but return HUGE_VAL after parsing.  */
-    exponent = MAX_10_EXP;
-
   /* We have the number digits in the integer part.  Whether these are all or
      any is really a fractional digit will be decided later.  */
   int_no = dig_no;
@@ -820,11 +812,11 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
 	  /* Get the exponent limit. */
 	  if (base == 16)
 	    exp_limit = (exp_negative ?
-			 -MIN_EXP + MANT_DIG - 4 * int_no :
+			 -MIN_EXP + MANT_DIG + 4 * int_no :
 			 MAX_EXP - 4 * int_no + lead_zero);
 	  else
 	    exp_limit = (exp_negative ?
-			 -MIN_10_EXP + MANT_DIG - int_no :
+			 -MIN_10_EXP + MANT_DIG + int_no :
 			 MAX_10_EXP - int_no + lead_zero);
 
 	  do
@@ -882,6 +874,22 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
       assert (dig_no >= int_no);
     }
 
+  if (dig_no == int_no && dig_no > 0 && exponent < 0)
+    do
+      {
+	while (expp[-1] < L_('0') || expp[-1] > L_('9'))
+	  --expp;
+
+	if (expp[-1] != L_('0'))
+	  break;
+
+	--expp;
+	--dig_no;
+	--int_no;
+	++exponent;
+      }
+    while (dig_no > 0 && exponent < 0);
+
  number_parsed:
 
   /* The whole string is parsed.  Store the address of the next character.  */