On a recent mingw (both 32-bit and 64-bit), I'm seeing this test failure: FAIL: test-localename =====================
../../tests/test-localename.c:158: assertion 'strcmp (name, "de_DE.UTF-8") == 0' failed Once this is worked around, there is another one here: /* Check that gl_locale_name_thread always returns NULL. */ ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL); It is due to the localename.c change from 2014-07-15 [1]. While the general approach (to call GetThreadLocale only as a fallback, because GetThreadLocale does not consider changes made by 'setlocale') is reasonable, the exact placement of the new code is odd: Fixing the test failures in the tests (attached: fix-tests.diff) makes the code even stranger. [1] https://lists.gnu.org/archive/html/bug-gnulib/2014-07/msg00003.html The better fix is this one: 2018-05-02 Bruno Haible <br...@clisp.org> localename: Fix test failures on mingw. * lib/localename.c (gl_locale_name_thread): Remove code specific to native Windows. (gl_locale_name_posix): Move code specific to native Windows here. * tests/test-localename.c (test_locale_name, test_locale_name_posix): Accept result without charset suffix, as it appears on mingw. diff --git a/lib/localename.c b/lib/localename.c index 74c8ee0..f7a7fa5 100644 --- a/lib/localename.c +++ b/lib/localename.c @@ -2786,7 +2786,27 @@ gl_locale_name_thread (int category, const char *categoryname) const char *name = gl_locale_name_thread_unsafe (category, categoryname); if (name != NULL) return struniq (name); -#elif defined WINDOWS_NATIVE +#endif + /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when + SetThreadLocale has not been called - which is a very frequent case - + the value of GetThreadLocale() ignores past calls to 'setlocale'. */ + return NULL; +} + +/* XPG3 defines the result of 'setlocale (category, NULL)' as: + "Directs 'setlocale()' to query 'category' and return the current + setting of 'local'." + However it does not specify the exact format. Neither do SUSV2 and + ISO C 99. So we can use this feature only on selected systems (e.g. + those using GNU C Library). */ +#if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__) +# define HAVE_LOCALE_NULL +#endif + +const char * +gl_locale_name_posix (int category, const char *categoryname) +{ +#if defined WINDOWS_NATIVE if (LC_MIN <= category && category <= LC_MAX) { char *locname = setlocale (category, NULL); @@ -2796,8 +2816,8 @@ gl_locale_name_thread (int category, const char *categoryname) separated list of locales. We need only one, so we take the one corresponding to LC_CTYPE, as the most important for character translations. */ - if (strchr (locname, ';')) - locname = setlocale (LC_CTYPE, NULL); + if (category == LC_ALL && strchr (locname, ';')) + locname = setlocale (LC_CTYPE, NULL); /* Convert locale name to LCID. We don't want to use LocaleNameToLCID because (a) it is only available since Vista, @@ -2808,22 +2828,6 @@ gl_locale_name_thread (int category, const char *categoryname) return gl_locale_name_from_win32_LCID (lcid); } #endif - return NULL; -} - -/* XPG3 defines the result of 'setlocale (category, NULL)' as: - "Directs 'setlocale()' to query 'category' and return the current - setting of 'local'." - However it does not specify the exact format. Neither do SUSV2 and - ISO C 99. So we can use this feature only on selected systems (e.g. - those using GNU C Library). */ -#if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__) -# define HAVE_LOCALE_NULL -#endif - -const char * -gl_locale_name_posix (int category, const char *categoryname) -{ /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'. On some systems this can be done by the 'setlocale' function itself. */ #if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL diff --git a/tests/test-localename.c b/tests/test-localename.c index c0952a1..7e866c7 100644 --- a/tests/test-localename.c +++ b/tests/test-localename.c @@ -155,7 +155,16 @@ test_locale_name (void) if (setlocale (LC_ALL, "") != NULL) { name = gl_locale_name (LC_CTYPE, "LC_CTYPE"); +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ + /* On native Windows, here, + gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") + returns NULL and + gl_locale_name_posix (LC_CTYPE, "LC_CTYPE") + returns either "de_DE" or "de_DE.UTF-8". */ + ASSERT (strcmp (name, "de_DE") == 0 || strcmp (name, "de_DE.UTF-8") == 0); +#else ASSERT (strcmp (name, "de_DE.UTF-8") == 0); +#endif name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES"); ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); } @@ -575,7 +584,11 @@ test_locale_name_posix (void) if (setlocale (LC_ALL, "") != NULL) { name = gl_locale_name_posix (LC_CTYPE, "LC_CTYPE"); +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ + ASSERT (strcmp (name, "de_DE") == 0 || strcmp (name, "de_DE.UTF-8") == 0); +#else ASSERT (strcmp (name, "de_DE.UTF-8") == 0); +#endif name = gl_locale_name_posix (LC_MESSAGES, "LC_MESSAGES"); ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); }
diff --git a/tests/test-localename.c b/tests/test-localename.c index c0952a1..74b7a93 100644 --- a/tests/test-localename.c +++ b/tests/test-localename.c @@ -155,7 +155,16 @@ test_locale_name (void) if (setlocale (LC_ALL, "") != NULL) { name = gl_locale_name (LC_CTYPE, "LC_CTYPE"); +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ + /* On native Windows, here, + gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") + may return either "de_DE" or NULL, whereas + gl_locale_name_posix (LC_CTYPE, "LC_CTYPE") + returns "de_DE.UTF-8". */ + ASSERT (strcmp (name, "de_DE") == 0 || strcmp (name, "de_DE.UTF-8") == 0); +#else ASSERT (strcmp (name, "de_DE.UTF-8") == 0); +#endif name = gl_locale_name (LC_MESSAGES, "LC_MESSAGES"); ASSERT (strcmp (name, "fr_FR.UTF-8") == 0); } @@ -473,8 +482,11 @@ test_locale_name_thread (void) } } #else - /* Check that gl_locale_name_thread always returns NULL. */ + /* Check that gl_locale_name_thread always returns NULL, + except on native Windows. */ +# if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) ASSERT (gl_locale_name_thread (LC_CTYPE, "LC_CTYPE") == NULL); +# endif ASSERT (gl_locale_name_thread (LC_MESSAGES, "LC_MESSAGES") == NULL); #endif }