1 /* Convert string to double in the current locale, falling back on the C locale.
2 
3    Copyright 2019-2020 Free Software Foundation, Inc.
4 
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17 
18 /* Written by Paul Eggert.  */
19 
20 #include <config.h>
21 
22 #include "cl-strtod.h"
23 
24 #include <c-strtod.h>
25 
26 #include <errno.h>
27 #include <stdlib.h>
28 
29 #if LONG
30 # define CL_STRTOD cl_strtold
31 # define DOUBLE long double
32 # define C_STRTOD c_strtold
33 # define STRTOD strtold
34 #else
35 # define CL_STRTOD cl_strtod
36 # define DOUBLE double
37 # define C_STRTOD c_strtod
38 # define STRTOD strtod
39 #endif
40 
41 /* This function acts like strtod or strtold, except that it falls
42    back on the C locale if the initial prefix is not parsable in
43    the current locale.  If the prefix is parsable in both locales,
44    it uses the longer parse, breaking ties in favor of the current locale.
45 
46    Parse the initial prefix of NPTR as a floating-point number in the
47    current locale or in the C locale (preferring the locale that
48    yields the longer parse, or the current locale if there is a tie).
49    If ENDPTR is not NULL, set *ENDPTR to the first unused byte, or to
50    NPTR if the prefix cannot be parsed.
51 
52    If successful, return a number without changing errno.
53    If the prefix cannot be parsed, return 0 and possibly set errno to EINVAL.
54    If the number overflows, return an extreme value and set errno to ERANGE.
55    If the number underflows, return a value close to 0 and set errno to ERANGE.
56    If there is some other error, return 0 and set errno.  */
57 
58 DOUBLE
CL_STRTOD(char const * nptr,char ** restrict endptr)59 CL_STRTOD (char const *nptr, char **restrict endptr)
60 {
61   char *end;
62   DOUBLE d = STRTOD (nptr, &end);
63   if (*end)
64     {
65       int strtod_errno = errno;
66       char *c_end;
67       DOUBLE c = C_STRTOD (nptr, &c_end);
68       if (end < c_end)
69         d = c, end = c_end;
70       else
71         errno = strtod_errno;
72     }
73   if (endptr)
74     *endptr = end;
75   return d;
76 }
77