+ /* If a hex float was converted incorrectly, do it ourselves.
+ If the string starts with "0x" but does not contain digits,
+ consume the "0" ourselves. If a hex float is followed by a
+ 'p' but no exponent, then adjust the end pointer. */
+ if (*s == '0' && c_tolower (s[1]) == 'x')
+ {
+ if (! c_isxdigit (s[2 + (s[2] == '.')]))
+ end = s + 1;
+ else if (end <= s + 2)
+ {
+ num = parse_number (s + 2, 16, 2, 4, 'p', &endbuf);
+ end = endbuf;
+ }
+ else
+ {
+ const char *p = s + 2;
+ while (p < end && c_tolower (*p) != 'p')
+ p++;
+ if (p < end && ! c_isdigit (p[1 + (p[1] == '-' || p[1] == '+')]))
+ end = p;
+ }
+ }
+ else
+ {
+ /* If "1e 1" was misparsed as 10.0 instead of 1.0, re-do the
+ underlying strtod on a copy of the original string
+ truncated to avoid the bug. */
+ const char *e = s + 1;
+ while (e < end && c_tolower (*e) != 'e')
+ e++;
+ if (e < end && ! c_isdigit (e[1 + (e[1] == '-' || e[1] == '+')]))
+ {
+ char *dup = strdup (s);
+ errno = saved_errno;
+ if (!dup)
+ {
+ /* Not really our day, is it. Rounding errors are
+ better than outright failure. */
+ num = parse_number (s, 10, 10, 1, 'e', &endbuf);
+ }
+ else
+ {
+ dup[e - s] = '\0';
+ num = underlying_strtod (dup, &endbuf);
+ saved_errno = errno;
+ free (dup);
+ errno = saved_errno;
+ }
+ end = e;
+ }
+ }
+
+ s = end;