1 /* Convert string to double in the current locale, falling back on the C locale.
2
3 Copyright 2019-2023 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 non-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