summaryrefslogtreecommitdiff
path: root/lib/setlocale.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2011-02-12 18:16:10 +0100
committerBruno Haible <bruno@clisp.org>2011-02-12 18:16:10 +0100
commit94c9eb9cdefca1ca06c5159be5ed52491e27535b (patch)
treeb7973d3c8ba2e7e0912bf1e089448ac4f0d6a789 /lib/setlocale.c
parenta8184d2038fcd3620daa6ef37f910b4e2853e4cc (diff)
downloadgnulib-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.c48
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