1 /* Copyright (C) 1991-1992, 1997, 1999, 2003, 2006, 2008-2018 Free Software
2 Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
8
9 This program 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 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include <stdlib.h>
20
21 #include <ctype.h>
22 #include <errno.h>
23 #include <float.h>
24 #include <limits.h>
25 #include <math.h>
26 #include <stdbool.h>
27 #include <string.h>
28
29 #include "c-ctype.h"
30
31 #ifndef HAVE_LDEXP_IN_LIBC
32 #define HAVE_LDEXP_IN_LIBC 0
33 #endif
34
35 /* Return true if C is a space in the current locale, avoiding
36 problems with signed char and isspace. */
37 static bool
locale_isspace(char c)38 locale_isspace (char c)
39 {
40 unsigned char uc = c;
41 return isspace (uc) != 0;
42 }
43
44 #if !HAVE_LDEXP_IN_LIBC
45 #define ldexp dummy_ldexp
46 /* A dummy definition that will never be invoked. */
ldexp(double x _GL_UNUSED,int exponent _GL_UNUSED)47 static double ldexp (double x _GL_UNUSED, int exponent _GL_UNUSED)
48 {
49 abort ();
50 return 0.0;
51 }
52 #endif
53
54 /* Return X * BASE**EXPONENT. Return an extreme value and set errno
55 to ERANGE if underflow or overflow occurs. */
56 static double
scale_radix_exp(double x,int radix,long int exponent)57 scale_radix_exp (double x, int radix, long int exponent)
58 {
59 /* If RADIX == 10, this code is neither precise nor fast; it is
60 merely a straightforward and relatively portable approximation.
61 If N == 2, this code is precise on a radix-2 implementation,
62 albeit perhaps not fast if ldexp is not in libc. */
63
64 long int e = exponent;
65
66 if (HAVE_LDEXP_IN_LIBC && radix == 2)
67 return ldexp (x, e < INT_MIN ? INT_MIN : INT_MAX < e ? INT_MAX : e);
68 else
69 {
70 double r = x;
71
72 if (r != 0)
73 {
74 if (e < 0)
75 {
76 while (e++ != 0)
77 {
78 r /= radix;
79 if (r == 0 && x != 0)
80 {
81 errno = ERANGE;
82 break;
83 }
84 }
85 }
86 else
87 {
88 while (e-- != 0)
89 {
90 if (r < -DBL_MAX / radix)
91 {
92 errno = ERANGE;
93 return -HUGE_VAL;
94 }
95 else if (DBL_MAX / radix < r)
96 {
97 errno = ERANGE;
98 return HUGE_VAL;
99 }
100 else
101 r *= radix;
102 }
103 }
104 }
105
106 return r;
107 }
108 }
109
110 /* Parse a number at NPTR; this is a bit like strtol (NPTR, ENDPTR)
111 except there are no leading spaces or signs or "0x", and ENDPTR is
112 nonnull. The number uses a base BASE (either 10 or 16) fraction, a
113 radix RADIX (either 10 or 2) exponent, and exponent character
114 EXPCHAR. To convert from a number of digits to a radix exponent,
115 multiply by RADIX_MULTIPLIER (either 1 or 4). */
116 static double
parse_number(const char * nptr,int base,int radix,int radix_multiplier,char expchar,char ** endptr)117 parse_number (const char *nptr,
118 int base, int radix, int radix_multiplier, char expchar,
119 char **endptr)
120 {
121 const char *s = nptr;
122 bool got_dot = false;
123 long int exponent = 0;
124 double num = 0;
125
126 for (;; ++s)
127 {
128 int digit;
129 if (c_isdigit (*s))
130 digit = *s - '0';
131 else if (base == 16 && c_isxdigit (*s))
132 digit = c_tolower (*s) - ('a' - 10);
133 else if (! got_dot && *s == '.')
134 {
135 /* Record that we have found the decimal point. */
136 got_dot = true;
137 continue;
138 }
139 else
140 /* Any other character terminates the number. */
141 break;
142
143 /* Make sure that multiplication by base will not overflow. */
144 if (num <= DBL_MAX / base)
145 num = num * base + digit;
146 else
147 {
148 /* The value of the digit doesn't matter, since we have already
149 gotten as many digits as can be represented in a 'double'.
150 This doesn't necessarily mean the result will overflow.
151 The exponent may reduce it to within range.
152
153 We just need to record that there was another
154 digit so that we can multiply by 10 later. */
155 exponent += radix_multiplier;
156 }
157
158 /* Keep track of the number of digits after the decimal point.
159 If we just divided by base here, we might lose precision. */
160 if (got_dot)
161 exponent -= radix_multiplier;
162 }
163
164 if (c_tolower (*s) == expchar && ! locale_isspace (s[1]))
165 {
166 /* Add any given exponent to the implicit one. */
167 int save = errno;
168 char *end;
169 long int value = strtol (s + 1, &end, 10);
170 errno = save;
171
172 if (s + 1 != end)
173 {
174 /* Skip past the exponent, and add in the implicit exponent,
175 resulting in an extreme value on overflow. */
176 s = end;
177 exponent =
178 (exponent < 0
179 ? (value < LONG_MIN - exponent ? LONG_MIN : exponent + value)
180 : (LONG_MAX - exponent < value ? LONG_MAX : exponent + value));
181 }
182 }
183
184 *endptr = (char *) s;
185 return scale_radix_exp (num, radix, exponent);
186 }
187
188 static double underlying_strtod (const char *, char **);
189
190 /* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
191 ICC 10.0 has a bug when optimizing the expression -zero.
192 The expression -DBL_MIN * DBL_MIN does not work when cross-compiling
193 to PowerPC on Mac OS X 10.5. */
194 #if defined __hpux || defined __sgi || defined __ICC
195 static double
compute_minus_zero(void)196 compute_minus_zero (void)
197 {
198 return -DBL_MIN * DBL_MIN;
199 }
200 # define minus_zero compute_minus_zero ()
201 #else
202 double minus_zero = -0.0;
203 #endif
204
205 /* Convert NPTR to a double. If ENDPTR is not NULL, a pointer to the
206 character after the last one used in the number is put in *ENDPTR. */
207 double
strtod(const char * nptr,char ** endptr)208 strtod (const char *nptr, char **endptr)
209 {
210 bool negative = false;
211
212 /* The number so far. */
213 double num;
214
215 const char *s = nptr;
216 const char *end;
217 char *endbuf;
218 int saved_errno = errno;
219
220 /* Eat whitespace. */
221 while (locale_isspace (*s))
222 ++s;
223
224 /* Get the sign. */
225 negative = *s == '-';
226 if (*s == '-' || *s == '+')
227 ++s;
228
229 num = underlying_strtod (s, &endbuf);
230 end = endbuf;
231
232 if (c_isdigit (s[*s == '.']))
233 {
234 /* If a hex float was converted incorrectly, do it ourselves.
235 If the string starts with "0x" but does not contain digits,
236 consume the "0" ourselves. If a hex float is followed by a
237 'p' but no exponent, then adjust the end pointer. */
238 if (*s == '0' && c_tolower (s[1]) == 'x')
239 {
240 if (! c_isxdigit (s[2 + (s[2] == '.')]))
241 {
242 end = s + 1;
243
244 /* strtod() on z/OS returns ERANGE for "0x". */
245 errno = saved_errno;
246 }
247 else if (end <= s + 2)
248 {
249 num = parse_number (s + 2, 16, 2, 4, 'p', &endbuf);
250 end = endbuf;
251 }
252 else
253 {
254 const char *p = s + 2;
255 while (p < end && c_tolower (*p) != 'p')
256 p++;
257 if (p < end && ! c_isdigit (p[1 + (p[1] == '-' || p[1] == '+')]))
258 end = p;
259 }
260 }
261 else
262 {
263 /* If "1e 1" was misparsed as 10.0 instead of 1.0, re-do the
264 underlying strtod on a copy of the original string
265 truncated to avoid the bug. */
266 const char *e = s + 1;
267 while (e < end && c_tolower (*e) != 'e')
268 e++;
269 if (e < end && ! c_isdigit (e[1 + (e[1] == '-' || e[1] == '+')]))
270 {
271 char *dup = strdup (s);
272 errno = saved_errno;
273 if (!dup)
274 {
275 /* Not really our day, is it. Rounding errors are
276 better than outright failure. */
277 num = parse_number (s, 10, 10, 1, 'e', &endbuf);
278 }
279 else
280 {
281 dup[e - s] = '\0';
282 num = underlying_strtod (dup, &endbuf);
283 saved_errno = errno;
284 free (dup);
285 errno = saved_errno;
286 }
287 end = e;
288 }
289 }
290
291 s = end;
292 }
293
294 /* Check for infinities and NaNs. */
295 else if (c_tolower (*s) == 'i'
296 && c_tolower (s[1]) == 'n'
297 && c_tolower (s[2]) == 'f')
298 {
299 s += 3;
300 if (c_tolower (*s) == 'i'
301 && c_tolower (s[1]) == 'n'
302 && c_tolower (s[2]) == 'i'
303 && c_tolower (s[3]) == 't'
304 && c_tolower (s[4]) == 'y')
305 s += 5;
306 num = HUGE_VAL;
307 errno = saved_errno;
308 }
309 else if (c_tolower (*s) == 'n'
310 && c_tolower (s[1]) == 'a'
311 && c_tolower (s[2]) == 'n')
312 {
313 s += 3;
314 if (*s == '(')
315 {
316 const char *p = s + 1;
317 while (c_isalnum (*p))
318 p++;
319 if (*p == ')')
320 s = p + 1;
321 }
322
323 /* If the underlying implementation misparsed the NaN, assume
324 its result is incorrect, and return a NaN. Normally it's
325 better to use the underlying implementation's result, since a
326 nice implementation populates the bits of the NaN according
327 to interpreting n-char-sequence as a hexadecimal number. */
328 if (s != end || num == num)
329 num = NAN;
330 errno = saved_errno;
331 }
332 else
333 {
334 /* No conversion could be performed. */
335 errno = EINVAL;
336 s = nptr;
337 }
338
339 if (endptr != NULL)
340 *endptr = (char *) s;
341 /* Special case -0.0, since at least ICC miscompiles negation. We
342 can't use copysign(), as that drags in -lm on some platforms. */
343 if (!num && negative)
344 return minus_zero;
345 return negative ? -num : num;
346 }
347
348 /* The underlying strtod implementation. This must be defined
349 after strtod because it #undefs strtod. */
350 static double
underlying_strtod(const char * nptr,char ** endptr)351 underlying_strtod (const char *nptr, char **endptr)
352 {
353 #undef strtod
354 return strtod (nptr, endptr);
355 }
356