diff --git a/src/builtin_printf.cpp b/src/builtin_printf.cpp index d05cce172..65e008235 100644 --- a/src/builtin_printf.cpp +++ b/src/builtin_printf.cpp @@ -271,19 +271,11 @@ template <> long double raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) { double val = wcstod(s, end); if (**end == L'\0') return val; - // The conversion using the user's locale failed. That may be due to the string not being a // valid floating point value. It could also be due to the locale using different separator // characters than the normal english convention. So try again by forcing the use of a locale // that employs the english convention for writing floating point numbers. - // - // TODO: switch to the wcstod_l() function to avoid changing the global locale. - char *saved_locale = strdup(setlocale(LC_NUMERIC, NULL)); - setlocale(LC_NUMERIC, "C"); - val = wcstod(s, end); - setlocale(LC_NUMERIC, saved_locale); - free(saved_locale); - return val; + return wcstod_l(s, end, fish_c_locale()); } template diff --git a/src/wutil.cpp b/src/wutil.cpp index 31e4cc8ff..6988fd932 100644 --- a/src/wutil.cpp +++ b/src/wutil.cpp @@ -517,6 +517,11 @@ int fish_wcswidth(const wchar_t *str) { return fish_wcswidth(str, wcslen(str)); /// See fallback.h for the normal definitions. int fish_wcswidth(const wcstring &str) { return fish_wcswidth(str.c_str(), str.size()); } +locale_t fish_c_locale() { + static locale_t loc = newlocale(LC_ALL_MASK, "C", NULL); + return loc; +} + /// Like fish_wcstol(), but fails on a value outside the range of an int. /// /// This is needed because BSD and GNU implementations differ in several ways that make it really diff --git a/src/wutil.h b/src/wutil.h index 0713d34ca..72ac10cbb 100644 --- a/src/wutil.h +++ b/src/wutil.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "common.h" @@ -117,6 +118,9 @@ int fish_iswgraph(wint_t wc); int fish_wcswidth(const wchar_t *str); int fish_wcswidth(const wcstring &str); +// returns an immortal locale_t corresponding to the C locale. +locale_t fish_c_locale(); + int fish_wcstoi(const wchar_t *str, const wchar_t **endptr = NULL, int base = 10); long fish_wcstol(const wchar_t *str, const wchar_t **endptr = NULL, int base = 10); long long fish_wcstoll(const wchar_t *str, const wchar_t **endptr = NULL, int base = 10);