1 /* Copyright (C) 1991-1992, 1997, 1999, 2003, 2006, 2008-2024 Free Software
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation, either version 3 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 #if ! (defined USE_FLOAT || defined USE_LONG_DOUBLE)
24 #include <ctype.h> /* isspace() */
26 #include <float.h> /* {FLT,DBL,LDBL}_{MIN,MAX} */
27 #include <limits.h> /* LONG_{MIN,MAX} */
28 #include <locale.h> /* localeconv() */
29 #include <math.h> /* NAN */
30 #include <stdio.h> /* sprintf() */
31 #include <string.h> /* strdup() */
33 # include <langinfo.h>
41 # define STRTOD strtof
43 # if STRTOF_HAS_UNDERFLOW_BUG
44 /* strtof would not set errno=ERANGE upon flush-to-zero underflow. */
45 # define HAVE_UNDERLYING_STRTOD 0
47 # define HAVE_UNDERLYING_STRTOD HAVE_STRTOF
49 # define HAS_GRADUAL_UNDERFLOW_PROBLEM STRTOF_HAS_GRADUAL_UNDERFLOW_PROBLEM
53 # define L_(literal) literal##f
54 # if HAVE_LDEXPF_IN_LIBC
59 #elif defined USE_LONG_DOUBLE
60 # define STRTOD strtold
62 # if defined __hpux && defined __hppa
63 /* We cannot call strtold on HP-UX/hppa, because its return type is a struct,
64 not a 'long double'. */
65 # define HAVE_UNDERLYING_STRTOD 0
66 # elif STRTOLD_HAS_UNDERFLOW_BUG
67 /* strtold would not set errno=ERANGE upon flush-to-zero underflow. */
68 # define HAVE_UNDERLYING_STRTOD 0
69 # elif defined __MINGW32__ && __MINGW64_VERSION_MAJOR < 10
70 /* strtold is broken in mingw versions before 10.0:
71 - Up to mingw 5.0.x, it leaks memory at every invocation.
72 - Up to mingw 9.0.x, it allocates an unbounded amount of stack.
73 See <https://github.com/mingw-w64/mingw-w64/commit/450309b97b2e839ea02887dfaf0f1d10fb5d40cc>
74 and <https://github.com/mingw-w64/mingw-w64/commit/73806c0709b7e6c0f6587f11a955743670e85470>. */
75 # define HAVE_UNDERLYING_STRTOD 0
77 # define HAVE_UNDERLYING_STRTOD HAVE_STRTOLD
79 # define HAS_GRADUAL_UNDERFLOW_PROBLEM STRTOLD_HAS_GRADUAL_UNDERFLOW_PROBLEM
80 # define DOUBLE long double
83 # define L_(literal) literal##L
84 # if HAVE_LDEXPL_IN_LIBC
90 # define STRTOD strtod
92 # if STRTOD_HAS_UNDERFLOW_BUG
93 /* strtod would not set errno=ERANGE upon flush-to-zero underflow. */
94 # define HAVE_UNDERLYING_STRTOD 0
96 # define HAVE_UNDERLYING_STRTOD 1
98 # define HAS_GRADUAL_UNDERFLOW_PROBLEM STRTOD_HAS_GRADUAL_UNDERFLOW_PROBLEM
99 # define DOUBLE double
102 # define L_(literal) literal
103 # if HAVE_LDEXP_IN_LIBC
110 /* Return true if C is a space in the current locale, avoiding
111 problems with signed char and isspace. */
113 locale_isspace (char c
)
115 unsigned char uc
= c
;
116 return isspace (uc
) != 0;
119 /* Determine the decimal-point character according to the current locale. */
121 decimal_point_char (void)
124 /* Determine it in a multithread-safe way. We know nl_langinfo is
125 multithread-safe on glibc systems and Mac OS X systems, but is not required
126 to be multithread-safe by POSIX. sprintf(), however, is multithread-safe.
127 localeconv() is rarely multithread-safe. */
128 #if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__))
129 point
= nl_langinfo (RADIXCHAR
);
132 sprintf (pointbuf
, "%#.0f", 1.0);
133 point
= &pointbuf
[1];
135 point
= localeconv () -> decimal_point
;
137 /* The decimal point is always a single byte: either '.' or ','. */
138 return (point
[0] != '\0' ? point
[0] : '.');
143 #define LDEXP dummy_ldexp
144 /* A dummy definition that will never be invoked. */
145 static DOUBLE
LDEXP (_GL_UNUSED DOUBLE x
, _GL_UNUSED
int exponent
)
152 /* Return X * BASE**EXPONENT. Return an extreme value and set errno
153 to ERANGE if underflow or overflow occurs. */
155 scale_radix_exp (DOUBLE x
, int radix
, long int exponent
)
157 /* If RADIX == 10, this code is neither precise nor fast; it is
158 merely a straightforward and relatively portable approximation.
159 If N == 2, this code is precise on a radix-2 implementation,
160 albeit perhaps not fast if ldexp is not in libc. */
162 long int e
= exponent
;
164 if (USE_LDEXP
&& radix
== 2)
165 return LDEXP (x
, e
< INT_MIN
? INT_MIN
: INT_MAX
< e
? INT_MAX
: e
);
178 if (r
< MIN
&& r
> -MIN
)
179 /* Gradual underflow, resulting in a denormalized
187 /* Flush-to-zero underflow. */
197 if (r
< -MAX
/ radix
)
202 else if (MAX
/ radix
< r
)
217 /* Parse a number at NPTR; this is a bit like strtol (NPTR, ENDPTR)
218 except there are no leading spaces or signs or "0x", and ENDPTR is
219 nonnull. The number uses a base BASE (either 10 or 16) fraction, a
220 radix RADIX (either 10 or 2) exponent, and exponent character
221 EXPCHAR. BASE is RADIX**RADIX_MULTIPLIER. */
223 parse_number (const char *nptr
,
224 int base
, int radix
, int radix_multiplier
, char radixchar
,
228 const char *s
= nptr
;
229 const char *digits_start
;
230 const char *digits_end
;
231 const char *radixchar_ptr
;
235 /* First, determine the start and end of the digit sequence. */
237 radixchar_ptr
= NULL
;
240 if (base
== 16 ? c_isxdigit (*s
) : c_isdigit (*s
))
242 else if (radixchar_ptr
== NULL
&& *s
== radixchar
)
244 /* Record that we have found the decimal point. */
248 /* Any other character terminates the digit sequence. */
252 /* Now radixchar_ptr == NULL or
253 digits_start <= radixchar_ptr < digits_end. */
258 (radixchar_ptr
!= NULL
259 ? - (long int) (digits_end
- radixchar_ptr
- 1)
263 { /* Remove trailing zero digits. This reduces rounding errors for
264 inputs such as 1.0000000000 or 10000000000e-10. */
265 while (digits_end
> digits_start
)
267 if (digits_end
- 1 == radixchar_ptr
|| *(digits_end
- 1) == '0')
273 (radixchar_ptr
!= NULL
274 ? (digits_end
> radixchar_ptr
275 ? - (long int) (digits_end
- radixchar_ptr
- 1)
276 : (long int) (radixchar_ptr
- digits_end
))
277 : (long int) (s
- digits_end
));
280 /* Then, convert the digit sequence to a number. */
284 for (dp
= digits_start
; dp
< digits_end
; dp
++)
285 if (dp
!= radixchar_ptr
)
289 /* Make sure that multiplication by BASE will not overflow. */
290 if (!(num
<= MAX
/ base
))
292 /* The value of the digit and all subsequent digits don't matter,
293 since we have already gotten as many digits as can be
294 represented in a 'DOUBLE'. This doesn't necessarily mean that
295 the result will overflow: The exponent may reduce it to within
299 - (radixchar_ptr
>= dp
&& radixchar_ptr
< digits_end
? 1 : 0);
303 /* Eat the next digit. */
306 else if (base
== 16 && c_isxdigit (*dp
))
307 digit
= c_tolower (*dp
) - ('a' - 10);
310 num
= num
* base
+ digit
;
314 exponent
= exponent
* radix_multiplier
;
316 /* Finally, parse the exponent. */
317 if (c_tolower (*s
) == expchar
&& ! locale_isspace (s
[1]))
319 /* Add any given exponent to the implicit one. */
320 int saved_errno
= errno
;
322 long int value
= strtol (s
+ 1, &end
, 10);
327 /* Skip past the exponent, and add in the implicit exponent,
328 resulting in an extreme value on overflow. */
332 ? (value
< LONG_MIN
- exponent
? LONG_MIN
: exponent
+ value
)
333 : (LONG_MAX
- exponent
< value
? LONG_MAX
: exponent
+ value
));
337 *endptr
= (char *) s
;
338 return scale_radix_exp (num
, radix
, exponent
);
341 /* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
342 ICC 10.0 has a bug when optimizing the expression -zero.
343 The expression -MIN * MIN does not work when cross-compiling
344 to PowerPC on Mac OS X 10.5. */
348 #if defined __hpux || defined __sgi || defined __ICC
355 /* Convert NPTR to a DOUBLE. If ENDPTR is not NULL, a pointer to the
356 character after the last one used in the number is put in *ENDPTR. */
358 STRTOD (const char *nptr
, char **endptr
)
359 #if HAVE_UNDERLYING_STRTOD
360 # if defined USE_FLOAT
362 # elif defined USE_LONG_DOUBLE
367 # if HAS_GRADUAL_UNDERFLOW_PROBLEM
368 # define SET_ERRNO_UPON_GRADUAL_UNDERFLOW(RESULT) \
371 if ((RESULT) != 0 && (RESULT) < MIN && (RESULT) > -MIN) \
376 # define SET_ERRNO_UPON_GRADUAL_UNDERFLOW(RESULT) (void)0
380 # define STRTOD(NPTR,ENDPTR) \
381 parse_number (NPTR, 10, 10, 1, radixchar, 'e', ENDPTR)
382 # define SET_ERRNO_UPON_GRADUAL_UNDERFLOW(RESULT) (void)0
384 /* From here on, STRTOD refers to the underlying implementation. It needs
385 to handle only finite unsigned decimal numbers with non-null ENDPTR. */
388 bool negative
= false;
390 /* The number so far. */
393 const char *s
= nptr
;
396 int saved_errno
= errno
;
398 radixchar
= decimal_point_char ();
400 /* Eat whitespace. */
401 while (locale_isspace (*s
))
405 negative
= *s
== '-';
406 if (*s
== '-' || *s
== '+')
409 num
= STRTOD (s
, &endbuf
);
410 SET_ERRNO_UPON_GRADUAL_UNDERFLOW (num
);
413 if (c_isdigit (s
[*s
== radixchar
]))
415 /* If a hex float was converted incorrectly, do it ourselves.
416 If the string starts with "0x" but does not contain digits,
417 consume the "0" ourselves. If a hex float is followed by a
418 'p' but no exponent, then adjust the end pointer. */
419 if (*s
== '0' && c_tolower (s
[1]) == 'x')
421 if (! c_isxdigit (s
[2 + (s
[2] == radixchar
)]))
425 /* strtod() on z/OS returns ERANGE for "0x". */
428 else if (end
<= s
+ 2)
430 num
= parse_number (s
+ 2, 16, 2, 4, radixchar
, 'p', &endbuf
);
435 const char *p
= s
+ 2;
436 while (p
< end
&& c_tolower (*p
) != 'p')
438 if (p
< end
&& ! c_isdigit (p
[1 + (p
[1] == '-' || p
[1] == '+')]))
440 char *dup
= strdup (s
);
444 /* Not really our day, is it. Rounding errors are
445 better than outright failure. */
447 parse_number (s
+ 2, 16, 2, 4, radixchar
, 'p', &endbuf
);
452 num
= STRTOD (dup
, &endbuf
);
453 SET_ERRNO_UPON_GRADUAL_UNDERFLOW (num
);
464 /* If "1e 1" was misparsed as 10.0 instead of 1.0, re-do the
465 underlying STRTOD on a copy of the original string
466 truncated to avoid the bug. */
467 const char *e
= s
+ 1;
468 while (e
< end
&& c_tolower (*e
) != 'e')
470 if (e
< end
&& ! c_isdigit (e
[1 + (e
[1] == '-' || e
[1] == '+')]))
472 char *dup
= strdup (s
);
476 /* Not really our day, is it. Rounding errors are
477 better than outright failure. */
478 num
= parse_number (s
, 10, 10, 1, radixchar
, 'e', &endbuf
);
483 num
= STRTOD (dup
, &endbuf
);
484 SET_ERRNO_UPON_GRADUAL_UNDERFLOW (num
);
496 /* Check for infinities and NaNs. */
497 else if (c_tolower (*s
) == 'i'
498 && c_tolower (s
[1]) == 'n'
499 && c_tolower (s
[2]) == 'f')
502 if (c_tolower (*s
) == 'i'
503 && c_tolower (s
[1]) == 'n'
504 && c_tolower (s
[2]) == 'i'
505 && c_tolower (s
[3]) == 't'
506 && c_tolower (s
[4]) == 'y')
511 else if (c_tolower (*s
) == 'n'
512 && c_tolower (s
[1]) == 'a'
513 && c_tolower (s
[2]) == 'n')
518 const char *p
= s
+ 1;
519 while (c_isalnum (*p
))
525 /* If the underlying implementation misparsed the NaN, assume
526 its result is incorrect, and return a NaN. Normally it's
527 better to use the underlying implementation's result, since a
528 nice implementation populates the bits of the NaN according
529 to interpreting n-char-sequence as a hexadecimal number. */
530 if (s
!= end
|| num
== num
)
536 /* No conversion could be performed. */
542 *endptr
= (char *) s
;
543 /* Special case -0.0, since at least ICC miscompiles negation. We
544 can't use copysign(), as that drags in -lm on some platforms. */
545 if (!num
&& negative
)
546 return minus_zero ();
547 return negative
? -num
: num
;