diff options
author | Bruno Haible <bruno@clisp.org> | 2011-02-12 18:16:10 +0100 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2011-02-12 18:16:10 +0100 |
commit | 94c9eb9cdefca1ca06c5159be5ed52491e27535b (patch) | |
tree | b7973d3c8ba2e7e0912bf1e089448ac4f0d6a789 /lib/setlocale.c | |
parent | a8184d2038fcd3620daa6ef37f910b4e2853e4cc (diff) | |
download | gnulib-94c9eb9cdefca1ca06c5159be5ed52491e27535b.tar.gz |
setlocale: Workaround native Windows bug.
* lib/setlocale.c (rpl_setlocale): On native Windows, when setlocale
succeeds but sets LC_CTYPE to "C", report a failure.
* tests/test-setlocale2.sh: New file.
* tests/test-setlocale2.c: New file.
* modules/setlocale-tests (Files): Add the new files.
(Makefile.am): Enable test-setlocale2.sh test.
* doc/posix-functions/setlocale.texi: Mention workaround.
Diffstat (limited to 'lib/setlocale.c')
-rw-r--r-- | lib/setlocale.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/lib/setlocale.c b/lib/setlocale.c index 9fe1aa9fa7..0cef00fa6b 100644 --- a/lib/setlocale.c +++ b/lib/setlocale.c @@ -844,6 +844,14 @@ rpl_setlocale (int category, const char *locale) if (setlocale_unixlike (LC_ALL, base_name) == NULL) goto fail; +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* On native Windows, setlocale(LC_ALL,...) may succeed but set the + LC_CTYPE category to an invalid value ("C") when it does not + support the specified encoding. Report a failure instead. */ + if (strchr (base_name, '.') != NULL + && strcmp (setlocale (LC_CTYPE, NULL), "C") == 0) + goto fail; +# endif for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++) { @@ -886,7 +894,45 @@ rpl_setlocale (int category, const char *locale) } } else - return setlocale_single (category, locale); + { +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + if (category == LC_ALL && locale != NULL && strchr (locale, '.') != NULL) + { + char *saved_locale; + + /* Back up the old locale. */ + saved_locale = setlocale (LC_ALL, NULL); + if (saved_locale == NULL) + return NULL; + saved_locale = strdup (saved_locale); + if (saved_locale == NULL) + return NULL; + + if (setlocale_unixlike (LC_ALL, locale) == NULL) + { + free (saved_locale); + return NULL; + } + + /* On native Windows, setlocale(LC_ALL,...) may succeed but set the + LC_CTYPE category to an invalid value ("C") when it does not + support the specified encoding. Report a failure instead. */ + if (strcmp (setlocale (LC_CTYPE, NULL), "C") == 0) + { + if (saved_locale[0] != '\0') /* don't risk an endless recursion */ + setlocale (LC_ALL, saved_locale); + free (saved_locale); + return NULL; + } + + /* It was really successful. */ + free (saved_locale); + return setlocale (LC_ALL, NULL); + } + else +# endif + return setlocale_single (category, locale); + } } #endif |