2 * Locale-independent strtod().
4 * This file may be redistributed under the terms of the
5 * GNU Lesser General Public License.
7 * Copyright (C) 2021 Karel Zak <kzak@redhat.com>
21 #if defined(HAVE_NEWLOCALE) && (defined(HAVE_STRTOD_L) || defined(HAVE_USELOCALE))
25 #if defined(USE_CLOCALE)
26 static volatile locale_t c_locale
;
28 static locale_t
get_c_locale(void)
31 c_locale
= newlocale(LC_ALL_MASK
, "C", (locale_t
) 0);
37 double c_strtod(char const *str
, char **end
)
42 #if defined(USE_CLOCALE)
43 locale_t cl
= get_c_locale();
45 #if defined(HAVE_STRTOD_L)
47 * A) try strtod_l() for "C" locale
50 return strtod_l(str
, end
, cl
);
51 #elif defined(HAVE_USELOCALE)
53 * B) classic strtod(), but switch to "C" locale by uselocal()
56 locale_t org_cl
= uselocale(locale
);
60 res
= strtod(str
, end
);
67 #endif /* HAVE_USELOCALE */
68 #endif /* USE_CLOCALE */
70 * C) classic strtod(), but switch to "C" locale by setlocale()
72 char *org_locale
= setlocale(LC_NUMERIC
, NULL
);
75 org_locale
= strdup(org_locale
);
79 setlocale(LC_NUMERIC
, "C");
81 res
= strtod(str
, end
);
85 setlocale(LC_NUMERIC
, org_locale
);
93 int main(int argc
, char *argv
[])
99 fprintf(stderr
, "usage: %s decimal.number\n",
100 program_invocation_short_name
);
104 res
= c_strtod(argv
[1], &end
);
105 printf("Result: %g, errno: %d, endptr: '%s'\n", res
, errno
, end
);
107 return errno
? EXIT_FAILURE
: EXIT_SUCCESS
;