annotate lib/strtod.c @ 16235:18a38c9615f0

In commentary, do not use ` to quote.
author Paul Eggert <eggert@cs.ucla.edu>
date Thu, 05 Jan 2012 23:53:49 -0800
parents 8250f2777afc
children 498a2211d839
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
16201
8250f2777afc maint: update all copyright year number ranges
Jim Meyering <meyering@redhat.com>
parents: 14145
diff changeset
1 /* Copyright (C) 1991-1992, 1997, 1999, 2003, 2006, 2008-2012 Free Software
12559
c2cbabec01dd update nearly all FSF copyright year lists to include 2010
Jim Meyering <meyering@redhat.com>
parents: 12422
diff changeset
2 Foundation, Inc.
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
3
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 7302
diff changeset
4 This program is free software: you can redistribute it and/or modify
311
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
5 it under the terms of the GNU General Public License as published by
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 7302
diff changeset
6 the Free Software Foundation; either version 3 of the License, or
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 7302
diff changeset
7 (at your option) any later version.
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
8
311
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
9 This program is distributed in the hope that it will be useful,
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
12 GNU General Public License for more details.
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
13
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
14 You should have received a copy of the GNU General Public License
9309
bbbbbf4cd1c5 Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents: 7302
diff changeset
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
309
7900f3bbd673 remove ansidecl junk
Jim Meyering <jim@meyering.net>
parents: 308
diff changeset
16
7302
8a1a9361108c * _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents: 6930
diff changeset
17 #include <config.h>
311
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
18
9821
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
19 #include <stdlib.h>
373
Jim Meyering <jim@meyering.net>
parents: 311
diff changeset
20
311
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
21 #include <ctype.h>
9821
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
22 #include <errno.h>
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
23 #include <float.h>
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
24 #include <limits.h>
311
6980a90dddc9 merge with 1.10n5
Jim Meyering <jim@meyering.net>
parents: 310
diff changeset
25 #include <math.h>
9821
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
26 #include <stdbool.h>
13655
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
27 #include <string.h>
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
28
9822
fb687649f177 Add hex float support.
Eric Blake <ebb9@byu.net>
parents: 9821
diff changeset
29 #include "c-ctype.h"
fb687649f177 Add hex float support.
Eric Blake <ebb9@byu.net>
parents: 9821
diff changeset
30
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
31 #ifndef HAVE_LDEXP_IN_LIBC
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
32 #define HAVE_LDEXP_IN_LIBC 0
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
33 #endif
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
34 #ifndef HAVE_RAW_DECL_STRTOD
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
35 #define HAVE_RAW_DECL_STRTOD 0
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
36 #endif
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
37
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
38 /* Return true if C is a space in the current locale, avoiding
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
39 problems with signed char and isspace. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
40 static bool
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
41 locale_isspace (char c)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
42 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
43 unsigned char uc = c;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
44 return isspace (uc) != 0;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
45 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
46
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
47 #if !HAVE_LDEXP_IN_LIBC
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
48 #define ldexp dummy_ldexp
13464
abaeec5957d0 strtod: Add safety check.
Bruno Haible <bruno@clisp.org>
parents: 13456
diff changeset
49 /* A dummy definition that will never be invoked. */
abaeec5957d0 strtod: Add safety check.
Bruno Haible <bruno@clisp.org>
parents: 13456
diff changeset
50 static double ldexp (double x _GL_UNUSED, int exponent _GL_UNUSED)
abaeec5957d0 strtod: Add safety check.
Bruno Haible <bruno@clisp.org>
parents: 13456
diff changeset
51 {
abaeec5957d0 strtod: Add safety check.
Bruno Haible <bruno@clisp.org>
parents: 13456
diff changeset
52 abort ();
abaeec5957d0 strtod: Add safety check.
Bruno Haible <bruno@clisp.org>
parents: 13456
diff changeset
53 return 0.0;
abaeec5957d0 strtod: Add safety check.
Bruno Haible <bruno@clisp.org>
parents: 13456
diff changeset
54 }
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
55 #endif
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
56
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
57 /* Return X * BASE**EXPONENT. Return an extreme value and set errno
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
58 to ERANGE if underflow or overflow occurs. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
59 static double
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
60 scale_radix_exp (double x, int radix, long int exponent)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
61 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
62 /* If RADIX == 10, this code is neither precise nor fast; it is
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
63 merely a straightforward and relatively portable approximation.
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
64 If N == 2, this code is precise on a radix-2 implementation,
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
65 albeit perhaps not fast if ldexp is not in libc. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
66
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
67 long int e = exponent;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
68
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
69 if (HAVE_LDEXP_IN_LIBC && radix == 2)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
70 return ldexp (x, e < INT_MIN ? INT_MIN : INT_MAX < e ? INT_MAX : e);
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
71 else
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
72 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
73 double r = x;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
74
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
75 if (r != 0)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
76 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
77 if (e < 0)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
78 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
79 while (e++ != 0)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
80 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
81 r /= radix;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
82 if (r == 0 && x != 0)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
83 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
84 errno = ERANGE;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
85 break;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
86 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
87 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
88 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
89 else
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
90 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
91 while (e-- != 0)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
92 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
93 if (r < -DBL_MAX / radix)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
94 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
95 errno = ERANGE;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
96 return -HUGE_VAL;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
97 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
98 else if (DBL_MAX / radix < r)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
99 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
100 errno = ERANGE;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
101 return HUGE_VAL;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
102 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
103 else
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
104 r *= radix;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
105 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
106 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
107 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
108
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
109 return r;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
110 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
111 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
112
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
113 /* Parse a number at NPTR; this is a bit like strtol (NPTR, ENDPTR)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
114 except there are no leading spaces or signs or "0x", and ENDPTR is
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
115 nonnull. The number uses a base BASE (either 10 or 16) fraction, a
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
116 radix RADIX (either 10 or 2) exponent, and exponent character
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
117 EXPCHAR. To convert from a number of digits to a radix exponent,
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
118 multiply by RADIX_MULTIPLIER (either 1 or 4). */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
119 static double
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
120 parse_number (const char *nptr,
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
121 int base, int radix, int radix_multiplier, char expchar,
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
122 char **endptr)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
123 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
124 const char *s = nptr;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
125 bool got_dot = false;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
126 long int exponent = 0;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
127 double num = 0;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
128
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
129 for (;; ++s)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
130 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
131 int digit;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
132 if (c_isdigit (*s))
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
133 digit = *s - '0';
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
134 else if (base == 16 && c_isxdigit (*s))
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
135 digit = c_tolower (*s) - ('a' - 10);
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
136 else if (! got_dot && *s == '.')
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
137 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
138 /* Record that we have found the decimal point. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
139 got_dot = true;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
140 continue;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
141 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
142 else
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
143 /* Any other character terminates the number. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
144 break;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
145
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
146 /* Make sure that multiplication by base will not overflow. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
147 if (num <= DBL_MAX / base)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
148 num = num * base + digit;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
149 else
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
150 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
151 /* The value of the digit doesn't matter, since we have already
16235
18a38c9615f0 In commentary, do not use ` to quote.
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
152 gotten as many digits as can be represented in a 'double'.
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
153 This doesn't necessarily mean the result will overflow.
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
154 The exponent may reduce it to within range.
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
155
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
156 We just need to record that there was another
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
157 digit so that we can multiply by 10 later. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
158 exponent += radix_multiplier;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
159 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
160
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
161 /* Keep track of the number of digits after the decimal point.
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
162 If we just divided by base here, we might lose precision. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
163 if (got_dot)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
164 exponent -= radix_multiplier;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
165 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
166
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
167 if (c_tolower (*s) == expchar && ! locale_isspace (s[1]))
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
168 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
169 /* Add any given exponent to the implicit one. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
170 int save = errno;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
171 char *end;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
172 long int value = strtol (s + 1, &end, 10);
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
173 errno = save;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
174
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
175 if (s + 1 != end)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
176 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
177 /* Skip past the exponent, and add in the implicit exponent,
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
178 resulting in an extreme value on overflow. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
179 s = end;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
180 exponent =
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
181 (exponent < 0
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
182 ? (value < LONG_MIN - exponent ? LONG_MIN : exponent + value)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
183 : (LONG_MAX - exponent < value ? LONG_MAX : exponent + value));
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
184 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
185 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
186
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
187 *endptr = (char *) s;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
188 return scale_radix_exp (num, radix, exponent);
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
189 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
190
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
191 static double underlying_strtod (const char *, char **);
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
192
13837
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
193 /* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0.
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
194 ICC 10.0 has a bug when optimizing the expression -zero.
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
195 The expression -DBL_MIN * DBL_MIN does not work when cross-compiling
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
196 to PowerPC on MacOS X 10.5. */
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
197 #if defined __hpux || defined __sgi || defined __ICC
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
198 static double
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
199 compute_minus_zero (void)
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
200 {
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
201 return -DBL_MIN * DBL_MIN;
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
202 }
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
203 # define minus_zero compute_minus_zero ()
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
204 #else
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
205 double minus_zero = -0.0;
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
206 #endif
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
207
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
208 /* Convert NPTR to a double. If ENDPTR is not NULL, a pointer to the
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
209 character after the last one used in the number is put in *ENDPTR. */
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
210 double
1691
0eedcf045615 Protoize.
Jim Meyering <jim@meyering.net>
parents: 1042
diff changeset
211 strtod (const char *nptr, char **endptr)
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
212 {
9821
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
213 bool negative = false;
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
214
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
215 /* The number so far. */
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
216 double num;
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
217
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
218 const char *s = nptr;
13545
1531149632e8 strtod: fix const diagnostic
Paul Eggert <eggert@cs.ucla.edu>
parents: 13507
diff changeset
219 const char *end;
1531149632e8 strtod: fix const diagnostic
Paul Eggert <eggert@cs.ucla.edu>
parents: 13507
diff changeset
220 char *endbuf;
13655
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
221 int saved_errno;
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
222
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
223 /* Eat whitespace. */
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
224 while (locale_isspace (*s))
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
225 ++s;
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
226
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
227 /* Get the sign. */
9821
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
228 negative = *s == '-';
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
229 if (*s == '-' || *s == '+')
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
230 ++s;
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
231
13655
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
232 saved_errno = errno;
13545
1531149632e8 strtod: fix const diagnostic
Paul Eggert <eggert@cs.ucla.edu>
parents: 13507
diff changeset
233 num = underlying_strtod (s, &endbuf);
1531149632e8 strtod: fix const diagnostic
Paul Eggert <eggert@cs.ucla.edu>
parents: 13507
diff changeset
234 end = endbuf;
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
235
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
236 if (c_isdigit (s[*s == '.']))
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
237 {
13487
4ccc551d5cb6 strtod: fix bug in replacement function on AIX
Eric Blake <eblake@redhat.com>
parents: 13464
diff changeset
238 /* If a hex float was converted incorrectly, do it ourselves.
13507
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
239 If the string starts with "0x" but does not contain digits,
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
240 consume the "0" ourselves. If a hex float is followed by a
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
241 'p' but no exponent, then adjust the end pointer. */
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
242 if (*s == '0' && c_tolower (s[1]) == 'x')
13487
4ccc551d5cb6 strtod: fix bug in replacement function on AIX
Eric Blake <eblake@redhat.com>
parents: 13464
diff changeset
243 {
13507
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
244 if (! c_isxdigit (s[2 + (s[2] == '.')]))
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
245 end = s + 1;
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
246 else if (end <= s + 2)
13545
1531149632e8 strtod: fix const diagnostic
Paul Eggert <eggert@cs.ucla.edu>
parents: 13507
diff changeset
247 {
1531149632e8 strtod: fix const diagnostic
Paul Eggert <eggert@cs.ucla.edu>
parents: 13507
diff changeset
248 num = parse_number (s + 2, 16, 2, 4, 'p', &endbuf);
1531149632e8 strtod: fix const diagnostic
Paul Eggert <eggert@cs.ucla.edu>
parents: 13507
diff changeset
249 end = endbuf;
1531149632e8 strtod: fix const diagnostic
Paul Eggert <eggert@cs.ucla.edu>
parents: 13507
diff changeset
250 }
13487
4ccc551d5cb6 strtod: fix bug in replacement function on AIX
Eric Blake <eblake@redhat.com>
parents: 13464
diff changeset
251 else
13507
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
252 {
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
253 const char *p = s + 2;
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
254 while (p < end && c_tolower (*p) != 'p')
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
255 p++;
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
256 if (p < end && ! c_isdigit (p[1 + (p[1] == '-' || p[1] == '+')]))
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
257 end = p;
be8a41115d44 strtod: next round of AIX fixes
Eric Blake <eblake@redhat.com>
parents: 13487
diff changeset
258 }
13487
4ccc551d5cb6 strtod: fix bug in replacement function on AIX
Eric Blake <eblake@redhat.com>
parents: 13464
diff changeset
259 }
13655
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
260 else
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
261 {
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
262 /* If "1e 1" was misparsed as 10.0 instead of 1.0, re-do the
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
263 underlying strtod on a copy of the original string
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
264 truncated to avoid the bug. */
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
265 const char *e = s + 1;
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
266 while (e < end && c_tolower (*e) != 'e')
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
267 e++;
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
268 if (e < end && ! c_isdigit (e[1 + (e[1] == '-' || e[1] == '+')]))
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
269 {
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
270 char *dup = strdup (s);
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
271 errno = saved_errno;
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
272 if (!dup)
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
273 {
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
274 /* Not really our day, is it. Rounding errors are
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
275 better than outright failure. */
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
276 num = parse_number (s, 10, 10, 1, 'e', &endbuf);
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
277 }
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
278 else
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
279 {
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
280 dup[e - s] = '\0';
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
281 num = underlying_strtod (dup, &endbuf);
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
282 saved_errno = errno;
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
283 free (dup);
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
284 errno = saved_errno;
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
285 }
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
286 end = e;
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
287 }
d813f5516d9a strtod: work around IRIX 6.5 bug
Eric Blake <eblake@redhat.com>
parents: 13545
diff changeset
288 }
9822
fb687649f177 Add hex float support.
Eric Blake <ebb9@byu.net>
parents: 9821
diff changeset
289
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
290 s = end;
9822
fb687649f177 Add hex float support.
Eric Blake <ebb9@byu.net>
parents: 9821
diff changeset
291 }
fb687649f177 Add hex float support.
Eric Blake <ebb9@byu.net>
parents: 9821
diff changeset
292
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
293 /* Check for infinities and NaNs. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
294 else if (c_tolower (*s) == 'i'
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
295 && c_tolower (s[1]) == 'n'
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
296 && c_tolower (s[2]) == 'f')
9822
fb687649f177 Add hex float support.
Eric Blake <ebb9@byu.net>
parents: 9821
diff changeset
297 {
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
298 s += 3;
9822
fb687649f177 Add hex float support.
Eric Blake <ebb9@byu.net>
parents: 9821
diff changeset
299 if (c_tolower (*s) == 'i'
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9833
diff changeset
300 && c_tolower (s[1]) == 'n'
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
301 && c_tolower (s[2]) == 'i'
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
302 && c_tolower (s[3]) == 't'
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
303 && c_tolower (s[4]) == 'y')
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
304 s += 5;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
305 num = HUGE_VAL;
14145
a94d9a7b4aaa strtod: Restore errno when successfully parsing Infinity or NaN.
Bruno Haible <bruno@clisp.org>
parents: 14079
diff changeset
306 errno = saved_errno;
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
307 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
308 else if (c_tolower (*s) == 'n'
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
309 && c_tolower (s[1]) == 'a'
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
310 && c_tolower (s[2]) == 'n')
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
311 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
312 s += 3;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
313 if (*s == '(')
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9833
diff changeset
314 {
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
315 const char *p = s + 1;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
316 while (c_isalnum (*p))
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
317 p++;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
318 if (*p == ')')
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
319 s = p + 1;
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 9833
diff changeset
320 }
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
321
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
322 /* If the underlying implementation misparsed the NaN, assume
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
323 its result is incorrect, and return a NaN. Normally it's
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
324 better to use the underlying implementation's result, since a
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
325 nice implementation populates the bits of the NaN according
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
326 to interpreting n-char-sequence as a hexadecimal number. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
327 if (s != end)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
328 num = NAN;
14145
a94d9a7b4aaa strtod: Restore errno when successfully parsing Infinity or NaN.
Bruno Haible <bruno@clisp.org>
parents: 14079
diff changeset
329 errno = saved_errno;
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
330 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
331 else
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
332 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
333 /* No conversion could be performed. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
334 errno = EINVAL;
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
335 s = nptr;
9821
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
336 }
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
337
9821
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
338 if (endptr != NULL)
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
339 *endptr = (char *) s;
13837
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
340 /* Special case -0.0, since at least ICC miscompiles negation. We
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
341 can't use copysign(), as that drags in -lm on some platforms. */
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
342 if (!num && negative)
d7a891a411c1 strtod: work around icc bug
Eric Blake <eblake@redhat.com>
parents: 13655
diff changeset
343 return minus_zero;
9821
18bab9955c43 Document various strtod bugs, with some fixes.
Eric Blake <ebb9@byu.net>
parents: 9309
diff changeset
344 return negative ? -num : num;
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
345 }
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
346
13456
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
347 /* The "underlying" strtod implementation. This must be defined
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
348 after strtod because it #undefs strtod. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
349 static double
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
350 underlying_strtod (const char *nptr, char **endptr)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
351 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
352 if (HAVE_RAW_DECL_STRTOD)
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
353 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
354 /* Prefer the native strtod if available. Usually it should
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
355 work and it should give more-accurate results than our
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
356 approximation. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
357 #undef strtod
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
358 return strtod (nptr, endptr);
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
359 }
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
360 else
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
361 {
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
362 /* Approximate strtod well enough for this module. There's no
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
363 need to handle anything but finite unsigned decimal
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
364 numbers with nonnull ENDPTR. */
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
365 return parse_number (nptr, 10, 10, 1, 'e', endptr);
fd291325b6d5 strtod: make it more-accurate typically, and don't require libm
Paul R. Eggert <eggert@cs.ucla.edu>
parents: 12559
diff changeset
366 }
9
f8dce34b5ab0 Initial revision
Jim Meyering <jim@meyering.net>
parents:
diff changeset
367 }