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 }