summaryrefslogtreecommitdiff
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. */