Mercurial > gnulib
comparison lib/strtod.c @ 40166:cdb3438ceb13
strtold: New module.
* lib/stdlib.in.h (strtold): New declaration.
* lib/strtold.c: New file.
* lib/strtod.c: Consider USE_LONG_DOUBLE.
(STRTOD, LDEXP, HAVE_UNDERLYING_STRTOD, DOUBLE, MIN, MAX, L_,
USE_LDEXP): New macros.
(LDEXP, scale_radix_exp, parse_number, STRTOD): Adapt for
USE_LONG_DOUBLE.
(underlying_strtod): Remove function. Replace with some macros.
Re-add the code for a missing underlying function that was removed on
2013-02-19.
* m4/strtold.m4: New file.
* m4/stdlib_h.m4 (gl_STDLIB_H): Test whether strtold is declared.
(gl_STDLIB_H_DEFAULTS): Initialize GNULIB_STRTOLD, HAVE_STRTOLD,
REPLACE_STRTOLD.
* modules/stdlib (Makefile.am): Substitute GNULIB_STRTOLD, HAVE_STRTOLD,
REPLACE_STRTOLD.
* modules/strtold: New file.
* doc/posix-functions/strtold.texi: Document the new module.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Wed, 30 Jan 2019 03:52:31 +0100 |
parents | b06060465f09 |
children | ecb43221748b |
comparison
equal
deleted
inserted
replaced
40165:959d7cd4aec1 | 40166:cdb3438ceb13 |
---|---|
12 GNU General Public License for more details. | 12 GNU General Public License for more details. |
13 | 13 |
14 You should have received a copy of the GNU General Public License | 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/>. */ | 15 along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
16 | 16 |
17 #include <config.h> | 17 #if ! defined USE_LONG_DOUBLE |
18 | 18 # include <config.h> |
19 #endif | |
20 | |
21 /* Specification. */ | |
19 #include <stdlib.h> | 22 #include <stdlib.h> |
20 | 23 |
21 #include <ctype.h> | 24 #include <ctype.h> |
22 #include <errno.h> | 25 #include <errno.h> |
23 #include <float.h> | 26 #include <float.h> |
26 #include <stdbool.h> | 29 #include <stdbool.h> |
27 #include <string.h> | 30 #include <string.h> |
28 | 31 |
29 #include "c-ctype.h" | 32 #include "c-ctype.h" |
30 | 33 |
31 #ifndef HAVE_LDEXP_IN_LIBC | 34 #undef MIN |
32 #define HAVE_LDEXP_IN_LIBC 0 | 35 #undef MAX |
36 #ifdef USE_LONG_DOUBLE | |
37 # define STRTOD strtold | |
38 # define LDEXP ldexpl | |
39 # if defined __hpux && defined __hppa | |
40 /* We cannot call strtold on HP-UX/hppa, because its return type is a struct, | |
41 not a 'long double'. */ | |
42 # define HAVE_UNDERLYING_STRTOD 0 | |
43 # else | |
44 # define HAVE_UNDERLYING_STRTOD HAVE_STRTOLD | |
45 # endif | |
46 # define DOUBLE long double | |
47 # define MIN LDBL_MIN | |
48 # define MAX LDBL_MAX | |
49 # define L_(literal) literal##L | |
50 #else | |
51 # define STRTOD strtod | |
52 # define LDEXP ldexp | |
53 # define HAVE_UNDERLYING_STRTOD 1 | |
54 # define DOUBLE double | |
55 # define MIN DBL_MIN | |
56 # define MAX DBL_MAX | |
57 # define L_(literal) literal | |
58 #endif | |
59 | |
60 #if (defined USE_LONG_DOUBLE ? HAVE_LDEXPM_IN_LIBC : HAVE_LDEXP_IN_LIBC) | |
61 # define USE_LDEXP 1 | |
62 #else | |
63 # define USE_LDEXP 0 | |
33 #endif | 64 #endif |
34 | 65 |
35 /* Return true if C is a space in the current locale, avoiding | 66 /* Return true if C is a space in the current locale, avoiding |
36 problems with signed char and isspace. */ | 67 problems with signed char and isspace. */ |
37 static bool | 68 static bool |
39 { | 70 { |
40 unsigned char uc = c; | 71 unsigned char uc = c; |
41 return isspace (uc) != 0; | 72 return isspace (uc) != 0; |
42 } | 73 } |
43 | 74 |
44 #if !HAVE_LDEXP_IN_LIBC | 75 #if !USE_LDEXP |
45 #define ldexp dummy_ldexp | 76 #undef LDEXP |
77 #define LDEXP dummy_ldexp | |
46 /* A dummy definition that will never be invoked. */ | 78 /* A dummy definition that will never be invoked. */ |
47 static double ldexp (double x _GL_UNUSED, int exponent _GL_UNUSED) | 79 static DOUBLE LDEXP (DOUBLE x _GL_UNUSED, int exponent _GL_UNUSED) |
48 { | 80 { |
49 abort (); | 81 abort (); |
50 return 0.0; | 82 return L_(0.0); |
51 } | 83 } |
52 #endif | 84 #endif |
53 | 85 |
54 /* Return X * BASE**EXPONENT. Return an extreme value and set errno | 86 /* Return X * BASE**EXPONENT. Return an extreme value and set errno |
55 to ERANGE if underflow or overflow occurs. */ | 87 to ERANGE if underflow or overflow occurs. */ |
56 static double | 88 static DOUBLE |
57 scale_radix_exp (double x, int radix, long int exponent) | 89 scale_radix_exp (DOUBLE x, int radix, long int exponent) |
58 { | 90 { |
59 /* If RADIX == 10, this code is neither precise nor fast; it is | 91 /* If RADIX == 10, this code is neither precise nor fast; it is |
60 merely a straightforward and relatively portable approximation. | 92 merely a straightforward and relatively portable approximation. |
61 If N == 2, this code is precise on a radix-2 implementation, | 93 If N == 2, this code is precise on a radix-2 implementation, |
62 albeit perhaps not fast if ldexp is not in libc. */ | 94 albeit perhaps not fast if ldexp is not in libc. */ |
63 | 95 |
64 long int e = exponent; | 96 long int e = exponent; |
65 | 97 |
66 if (HAVE_LDEXP_IN_LIBC && radix == 2) | 98 if (USE_LDEXP && radix == 2) |
67 return ldexp (x, e < INT_MIN ? INT_MIN : INT_MAX < e ? INT_MAX : e); | 99 return LDEXP (x, e < INT_MIN ? INT_MIN : INT_MAX < e ? INT_MAX : e); |
68 else | 100 else |
69 { | 101 { |
70 double r = x; | 102 DOUBLE r = x; |
71 | 103 |
72 if (r != 0) | 104 if (r != 0) |
73 { | 105 { |
74 if (e < 0) | 106 if (e < 0) |
75 { | 107 { |
85 } | 117 } |
86 else | 118 else |
87 { | 119 { |
88 while (e-- != 0) | 120 while (e-- != 0) |
89 { | 121 { |
90 if (r < -DBL_MAX / radix) | 122 if (r < -MAX / radix) |
91 { | 123 { |
92 errno = ERANGE; | 124 errno = ERANGE; |
93 return -HUGE_VAL; | 125 return -HUGE_VAL; |
94 } | 126 } |
95 else if (DBL_MAX / radix < r) | 127 else if (MAX / radix < r) |
96 { | 128 { |
97 errno = ERANGE; | 129 errno = ERANGE; |
98 return HUGE_VAL; | 130 return HUGE_VAL; |
99 } | 131 } |
100 else | 132 else |
111 except there are no leading spaces or signs or "0x", and ENDPTR is | 143 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 | 144 nonnull. The number uses a base BASE (either 10 or 16) fraction, a |
113 radix RADIX (either 10 or 2) exponent, and exponent character | 145 radix RADIX (either 10 or 2) exponent, and exponent character |
114 EXPCHAR. To convert from a number of digits to a radix exponent, | 146 EXPCHAR. To convert from a number of digits to a radix exponent, |
115 multiply by RADIX_MULTIPLIER (either 1 or 4). */ | 147 multiply by RADIX_MULTIPLIER (either 1 or 4). */ |
116 static double | 148 static DOUBLE |
117 parse_number (const char *nptr, | 149 parse_number (const char *nptr, |
118 int base, int radix, int radix_multiplier, char expchar, | 150 int base, int radix, int radix_multiplier, char expchar, |
119 char **endptr) | 151 char **endptr) |
120 { | 152 { |
121 const char *s = nptr; | 153 const char *s = nptr; |
122 bool got_dot = false; | 154 bool got_dot = false; |
123 long int exponent = 0; | 155 long int exponent = 0; |
124 double num = 0; | 156 DOUBLE num = 0; |
125 | 157 |
126 for (;; ++s) | 158 for (;; ++s) |
127 { | 159 { |
128 int digit; | 160 int digit; |
129 if (c_isdigit (*s)) | 161 if (c_isdigit (*s)) |
139 else | 171 else |
140 /* Any other character terminates the number. */ | 172 /* Any other character terminates the number. */ |
141 break; | 173 break; |
142 | 174 |
143 /* Make sure that multiplication by base will not overflow. */ | 175 /* Make sure that multiplication by base will not overflow. */ |
144 if (num <= DBL_MAX / base) | 176 if (num <= MAX / base) |
145 num = num * base + digit; | 177 num = num * base + digit; |
146 else | 178 else |
147 { | 179 { |
148 /* The value of the digit doesn't matter, since we have already | 180 /* The value of the digit doesn't matter, since we have already |
149 gotten as many digits as can be represented in a 'double'. | 181 gotten as many digits as can be represented in a 'DOUBLE'. |
150 This doesn't necessarily mean the result will overflow. | 182 This doesn't necessarily mean the result will overflow. |
151 The exponent may reduce it to within range. | 183 The exponent may reduce it to within range. |
152 | 184 |
153 We just need to record that there was another | 185 We just need to record that there was another |
154 digit so that we can multiply by 10 later. */ | 186 digit so that we can multiply by 10 later. */ |
183 | 215 |
184 *endptr = (char *) s; | 216 *endptr = (char *) s; |
185 return scale_radix_exp (num, radix, exponent); | 217 return scale_radix_exp (num, radix, exponent); |
186 } | 218 } |
187 | 219 |
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. | 220 /* 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. | 221 ICC 10.0 has a bug when optimizing the expression -zero. |
192 The expression -DBL_MIN * DBL_MIN does not work when cross-compiling | 222 The expression -MIN * MIN does not work when cross-compiling |
193 to PowerPC on Mac OS X 10.5. */ | 223 to PowerPC on Mac OS X 10.5. */ |
194 #if defined __hpux || defined __sgi || defined __ICC | 224 #if defined __hpux || defined __sgi || defined __ICC |
195 static double | 225 static DOUBLE |
196 compute_minus_zero (void) | 226 compute_minus_zero (void) |
197 { | 227 { |
198 return -DBL_MIN * DBL_MIN; | 228 return -MIN * MIN; |
199 } | 229 } |
200 # define minus_zero compute_minus_zero () | 230 # define minus_zero compute_minus_zero () |
201 #else | 231 #else |
202 double minus_zero = -0.0; | 232 DOUBLE minus_zero = -0.0; |
203 #endif | 233 #endif |
204 | 234 |
205 /* Convert NPTR to a double. If ENDPTR is not NULL, a pointer to the | 235 /* 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. */ | 236 character after the last one used in the number is put in *ENDPTR. */ |
207 double | 237 DOUBLE |
208 strtod (const char *nptr, char **endptr) | 238 STRTOD (const char *nptr, char **endptr) |
239 #if HAVE_UNDERLYING_STRTOD | |
240 # ifdef USE_LONG_DOUBLE | |
241 # undef strtold | |
242 # else | |
243 # undef strtod | |
244 # endif | |
245 #else | |
246 # undef STRTOD | |
247 # define STRTOD(NPTR,ENDPTR) parse_number (NPTR, 10, 10, 1, 'e', ENDPTR) | |
248 #endif | |
249 /* From here on, STRTOD refers to the underlying implementation. It needs | |
250 to handle only finite unsigned decimal numbers with non-null ENDPTR. */ | |
209 { | 251 { |
210 bool negative = false; | 252 bool negative = false; |
211 | 253 |
212 /* The number so far. */ | 254 /* The number so far. */ |
213 double num; | 255 DOUBLE num; |
214 | 256 |
215 const char *s = nptr; | 257 const char *s = nptr; |
216 const char *end; | 258 const char *end; |
217 char *endbuf; | 259 char *endbuf; |
218 int saved_errno = errno; | 260 int saved_errno = errno; |
224 /* Get the sign. */ | 266 /* Get the sign. */ |
225 negative = *s == '-'; | 267 negative = *s == '-'; |
226 if (*s == '-' || *s == '+') | 268 if (*s == '-' || *s == '+') |
227 ++s; | 269 ++s; |
228 | 270 |
229 num = underlying_strtod (s, &endbuf); | 271 num = STRTOD (s, &endbuf); |
230 end = endbuf; | 272 end = endbuf; |
231 | 273 |
232 if (c_isdigit (s[*s == '.'])) | 274 if (c_isdigit (s[*s == '.'])) |
233 { | 275 { |
234 /* If a hex float was converted incorrectly, do it ourselves. | 276 /* If a hex float was converted incorrectly, do it ourselves. |
259 } | 301 } |
260 } | 302 } |
261 else | 303 else |
262 { | 304 { |
263 /* If "1e 1" was misparsed as 10.0 instead of 1.0, re-do the | 305 /* 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 | 306 underlying STRTOD on a copy of the original string |
265 truncated to avoid the bug. */ | 307 truncated to avoid the bug. */ |
266 const char *e = s + 1; | 308 const char *e = s + 1; |
267 while (e < end && c_tolower (*e) != 'e') | 309 while (e < end && c_tolower (*e) != 'e') |
268 e++; | 310 e++; |
269 if (e < end && ! c_isdigit (e[1 + (e[1] == '-' || e[1] == '+')])) | 311 if (e < end && ! c_isdigit (e[1 + (e[1] == '-' || e[1] == '+')])) |
277 num = parse_number (s, 10, 10, 1, 'e', &endbuf); | 319 num = parse_number (s, 10, 10, 1, 'e', &endbuf); |
278 } | 320 } |
279 else | 321 else |
280 { | 322 { |
281 dup[e - s] = '\0'; | 323 dup[e - s] = '\0'; |
282 num = underlying_strtod (dup, &endbuf); | 324 num = STRTOD (dup, &endbuf); |
283 saved_errno = errno; | 325 saved_errno = errno; |
284 free (dup); | 326 free (dup); |
285 errno = saved_errno; | 327 errno = saved_errno; |
286 } | 328 } |
287 end = e; | 329 end = e; |
342 can't use copysign(), as that drags in -lm on some platforms. */ | 384 can't use copysign(), as that drags in -lm on some platforms. */ |
343 if (!num && negative) | 385 if (!num && negative) |
344 return minus_zero; | 386 return minus_zero; |
345 return negative ? -num : num; | 387 return negative ? -num : num; |
346 } | 388 } |
347 | |
348 /* The underlying strtod implementation. This must be defined | |
349 after strtod because it #undefs strtod. */ | |
350 static double | |
351 underlying_strtod (const char *nptr, char **endptr) | |
352 { | |
353 #undef strtod | |
354 return strtod (nptr, endptr); | |
355 } |