strtod: next round of AIX fixes
[gnulib.git] / lib / strtod.c
1 /* Copyright (C) 1991-1992, 1997, 1999, 2003, 2006, 2008-2010 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 <http://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
28 #include "c-ctype.h"
29
30 #ifndef HAVE_LDEXP_IN_LIBC
31 #define HAVE_LDEXP_IN_LIBC 0
32 #endif
33 #ifndef HAVE_RAW_DECL_STRTOD
34 #define HAVE_RAW_DECL_STRTOD 0
35 #endif
36
37 /* Return true if C is a space in the current locale, avoiding
38    problems with signed char and isspace.  */
39 static bool
40 locale_isspace (char c)
41 {
42   unsigned char uc = c;
43   return isspace (uc) != 0;
44 }
45
46 #if !HAVE_LDEXP_IN_LIBC
47  #define ldexp dummy_ldexp
48  /* A dummy definition that will never be invoked.  */
49  static double ldexp (double x _GL_UNUSED, int exponent _GL_UNUSED)
50  {
51    abort ();
52    return 0.0;
53  }
54 #endif
55
56 /* Return X * BASE**EXPONENT.  Return an extreme value and set errno
57    to ERANGE if underflow or overflow occurs.  */
58 static double
59 scale_radix_exp (double x, int radix, long int exponent)
60 {
61   /* If RADIX == 10, this code is neither precise nor fast; it is
62      merely a straightforward and relatively portable approximation.
63      If N == 2, this code is precise on a radix-2 implementation,
64      albeit perhaps not fast if ldexp is not in libc.  */
65
66   long int e = exponent;
67
68   if (HAVE_LDEXP_IN_LIBC && radix == 2)
69     return ldexp (x, e < INT_MIN ? INT_MIN : INT_MAX < e ? INT_MAX : e);
70   else
71     {
72       double r = x;
73
74       if (r != 0)
75         {
76           if (e < 0)
77             {
78               while (e++ != 0)
79                 {
80                   r /= radix;
81                   if (r == 0 && x != 0)
82                     {
83                       errno = ERANGE;
84                       break;
85                     }
86                 }
87             }
88           else
89             {
90               while (e-- != 0)
91                 {
92                   if (r < -DBL_MAX / radix)
93                     {
94                       errno = ERANGE;
95                       return -HUGE_VAL;
96                     }
97                   else if (DBL_MAX / radix < r)
98                     {
99                       errno = ERANGE;
100                       return HUGE_VAL;
101                     }
102                   else
103                     r *= radix;
104                 }
105             }
106         }
107
108       return r;
109     }
110 }
111
112 /* Parse a number at NPTR; this is a bit like strtol (NPTR, ENDPTR)
113    except there are no leading spaces or signs or "0x", and ENDPTR is
114    nonnull.  The number uses a base BASE (either 10 or 16) fraction, a
115    radix RADIX (either 10 or 2) exponent, and exponent character
116    EXPCHAR.  To convert from a number of digits to a radix exponent,
117    multiply by RADIX_MULTIPLIER (either 1 or 4).  */
118 static double
119 parse_number (const char *nptr,
120               int base, int radix, int radix_multiplier, char expchar,
121               char **endptr)
122 {
123   const char *s = nptr;
124   bool got_dot = false;
125   long int exponent = 0;
126   double num = 0;
127
128   for (;; ++s)
129     {
130       int digit;
131       if (c_isdigit (*s))
132         digit = *s - '0';
133       else if (base == 16 && c_isxdigit (*s))
134         digit = c_tolower (*s) - ('a' - 10);
135       else if (! got_dot && *s == '.')
136         {
137           /* Record that we have found the decimal point.  */
138           got_dot = true;
139           continue;
140         }
141       else
142         /* Any other character terminates the number.  */
143         break;
144
145       /* Make sure that multiplication by base will not overflow.  */
146       if (num <= DBL_MAX / base)
147         num = num * base + digit;
148       else
149         {
150           /* The value of the digit doesn't matter, since we have already
151              gotten as many digits as can be represented in a `double'.
152              This doesn't necessarily mean the result will overflow.
153              The exponent may reduce it to within range.
154
155              We just need to record that there was another
156              digit so that we can multiply by 10 later.  */
157           exponent += radix_multiplier;
158         }
159
160       /* Keep track of the number of digits after the decimal point.
161          If we just divided by base here, we might lose precision.  */
162       if (got_dot)
163         exponent -= radix_multiplier;
164     }
165
166   if (c_tolower (*s) == expchar && ! locale_isspace (s[1]))
167     {
168       /* Add any given exponent to the implicit one.  */
169       int save = errno;
170       char *end;
171       long int value = strtol (s + 1, &end, 10);
172       errno = save;
173
174       if (s + 1 != end)
175         {
176           /* Skip past the exponent, and add in the implicit exponent,
177              resulting in an extreme value on overflow.  */
178           s = end;
179           exponent =
180             (exponent < 0
181              ? (value < LONG_MIN - exponent ? LONG_MIN : exponent + value)
182              : (LONG_MAX - exponent < value ? LONG_MAX : exponent + value));
183         }
184     }
185
186   *endptr = (char *) s;
187   return scale_radix_exp (num, radix, exponent);
188 }
189
190 static double underlying_strtod (const char *, char **);
191
192 /* Convert NPTR to a double.  If ENDPTR is not NULL, a pointer to the
193    character after the last one used in the number is put in *ENDPTR.  */
194 double
195 strtod (const char *nptr, char **endptr)
196 {
197   bool negative = false;
198
199   /* The number so far.  */
200   double num;
201
202   const char *s = nptr;
203   char *end;
204
205   /* Eat whitespace.  */
206   while (locale_isspace (*s))
207     ++s;
208
209   /* Get the sign.  */
210   negative = *s == '-';
211   if (*s == '-' || *s == '+')
212     ++s;
213
214   num = underlying_strtod (s, &end);
215
216   if (c_isdigit (s[*s == '.']))
217     {
218       /* If a hex float was converted incorrectly, do it ourselves.
219          If the string starts with "0x" but does not contain digits,
220          consume the "0" ourselves.  If a hex float is followed by a
221          'p' but no exponent, then adjust the end pointer.  */
222       if (*s == '0' && c_tolower (s[1]) == 'x')
223         {
224           if (! c_isxdigit (s[2 + (s[2] == '.')]))
225             end = s + 1;
226           else if (end <= s + 2)
227             num = parse_number (s + 2, 16, 2, 4, 'p', &end);
228           else
229             {
230               const char *p = s + 2;
231               while (p < end && c_tolower (*p) != 'p')
232                 p++;
233               if (p < end && ! c_isdigit (p[1 + (p[1] == '-' || p[1] == '+')]))
234                 end = p;
235             }
236         }
237
238       s = end;
239     }
240
241   /* Check for infinities and NaNs.  */
242   else if (c_tolower (*s) == 'i'
243            && c_tolower (s[1]) == 'n'
244            && c_tolower (s[2]) == 'f')
245     {
246       s += 3;
247       if (c_tolower (*s) == 'i'
248           && c_tolower (s[1]) == 'n'
249           && c_tolower (s[2]) == 'i'
250           && c_tolower (s[3]) == 't'
251           && c_tolower (s[4]) == 'y')
252         s += 5;
253       num = HUGE_VAL;
254     }
255   else if (c_tolower (*s) == 'n'
256            && c_tolower (s[1]) == 'a'
257            && c_tolower (s[2]) == 'n')
258     {
259       s += 3;
260       if (*s == '(')
261         {
262           const char *p = s + 1;
263           while (c_isalnum (*p))
264             p++;
265           if (*p == ')')
266             s = p + 1;
267         }
268
269       /* If the underlying implementation misparsed the NaN, assume
270          its result is incorrect, and return a NaN.  Normally it's
271          better to use the underlying implementation's result, since a
272          nice implementation populates the bits of the NaN according
273          to interpreting n-char-sequence as a hexadecimal number.  */
274       if (s != end)
275         num = NAN;
276     }
277   else
278     {
279       /* No conversion could be performed.  */
280       errno = EINVAL;
281       s = nptr;
282     }
283
284   if (endptr != NULL)
285     *endptr = (char *) s;
286   return negative ? -num : num;
287 }
288
289 /* The "underlying" strtod implementation.  This must be defined
290    after strtod because it #undefs strtod.  */
291 static double
292 underlying_strtod (const char *nptr, char **endptr)
293 {
294   if (HAVE_RAW_DECL_STRTOD)
295     {
296       /* Prefer the native strtod if available.  Usually it should
297          work and it should give more-accurate results than our
298          approximation.  */
299       #undef strtod
300       return strtod (nptr, endptr);
301     }
302   else
303     {
304       /* Approximate strtod well enough for this module.  There's no
305          need to handle anything but finite unsigned decimal
306          numbers with nonnull ENDPTR.  */
307       return parse_number (nptr, 10, 10, 1, 'e', endptr);
308     }
309 }