fix raw_string_to_scalar_type locale handling

Fixes #3334
This commit is contained in:
Kurtis Rader 2016-08-29 20:11:40 -07:00
parent b895a50bb2
commit 6b1801063b
4 changed files with 25 additions and 5 deletions

View File

@ -264,11 +264,20 @@ uintmax_t raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) {
template <>
long double raw_string_to_scalar_type(const wchar_t *s, wchar_t **end) {
// Forcing the locale to C is questionable but it's what the old C_STRTOD() that I inlined here
// as part of changing how locale management is done by fish.
char *old_locale = setlocale(LC_NUMERIC, "C");
double val = wcstod(s, end);
setlocale(LC_NUMERIC, old_locale);
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;
}

View File

@ -0,0 +1 @@
2,34: value not completely converted

View File

@ -34,4 +34,11 @@ printf "%5" 10 ^ /dev/null
# \376 is 0xFE
printf '\376' | xxd -p
true
# Verify that floating point conversions and output work correctly with
# different combinations of locales and floating point strings. See issue
# #3334. This starts by assuming an locale using english conventions.
printf '%e\n' "1.23" # should succeed, output should be 1.230000e+00
printf '%e\n' "2,34" # should fail
set -x LC_NUMERIC fr_FR.UTF-8
printf '%e\n' "3,45" # should succeed, output should be 3,450000e+00
printf '%e\n' "4.56" # should succeed, output should be 4,560000e+00

View File

@ -14,3 +14,6 @@ I P Q R
Test escapes
a
fe
1.230000e+00
3,450000e+00
4,560000e+00