Mercurial > gnulib
comparison lib/setlocale.c @ 39841:e8445477dfdd
setlocale: Improve support for locales not supported by libc.
Reported by Dapeng Gao <peter@dpgao.cc> at
<https://savannah.gnu.org/bugs/?54479>.
* gettext-runtime/intl/setlocale.c: Include <stdio.h>.
(libintl_setlocale): Use a more error-tolerant strategy when the locale
to be set is not supported by libc: Emit warnings instead of failing.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sun, 16 Sep 2018 03:15:54 +0200 |
parents | 30b98859ed4a |
children | c49e0b132887 |
comparison
equal
deleted
inserted
replaced
39840:461ea8ba270c | 39841:e8445477dfdd |
---|---|
27 gettext/gettext-runtime/intl/setlocale.c ! */ | 27 gettext/gettext-runtime/intl/setlocale.c ! */ |
28 | 28 |
29 /* Specification. */ | 29 /* Specification. */ |
30 #include <locale.h> | 30 #include <locale.h> |
31 | 31 |
32 #include <stdio.h> | |
32 #include <stdlib.h> | 33 #include <stdlib.h> |
33 #include <string.h> | 34 #include <string.h> |
34 | 35 |
35 #include "localename.h" | 36 #include "localename.h" |
36 | 37 |
820 if (category == LC_ALL) | 821 if (category == LC_ALL) |
821 { | 822 { |
822 /* Set LC_CTYPE first. Then the other categories. */ | 823 /* Set LC_CTYPE first. Then the other categories. */ |
823 static int const categories[] = | 824 static int const categories[] = |
824 { | 825 { |
826 LC_CTYPE, | |
825 LC_NUMERIC, | 827 LC_NUMERIC, |
826 LC_TIME, | 828 LC_TIME, |
827 LC_COLLATE, | 829 LC_COLLATE, |
828 LC_MONETARY, | 830 LC_MONETARY, |
829 LC_MESSAGES | 831 LC_MESSAGES |
846 base_name = | 848 base_name = |
847 gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE)); | 849 gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE)); |
848 if (base_name == NULL) | 850 if (base_name == NULL) |
849 base_name = gl_locale_name_default (); | 851 base_name = gl_locale_name_default (); |
850 | 852 |
851 if (setlocale_unixlike (LC_ALL, base_name) == NULL) | 853 if (setlocale_unixlike (LC_ALL, base_name) != NULL) |
852 goto fail; | 854 { |
855 /* LC_CTYPE category already set. */ | |
856 i = 1; | |
857 } | |
858 else | |
859 { | |
860 /* On Mac OS X, "UTF-8" is a valid locale name for LC_CTYPE but | |
861 not for LC_ALL. Therefore this call may fail. So, try | |
862 another base_name. */ | |
863 base_name = "C"; | |
864 if (setlocale_unixlike (LC_ALL, base_name) == NULL) | |
865 goto fail; | |
866 i = 0; | |
867 } | |
853 # if defined _WIN32 && ! defined __CYGWIN__ | 868 # if defined _WIN32 && ! defined __CYGWIN__ |
854 /* On native Windows, setlocale(LC_ALL,...) may succeed but set the | 869 /* On native Windows, setlocale(LC_ALL,...) may succeed but set the |
855 LC_CTYPE category to an invalid value ("C") when it does not | 870 LC_CTYPE category to an invalid value ("C") when it does not |
856 support the specified encoding. Report a failure instead. */ | 871 support the specified encoding. Report a failure instead. */ |
857 if (strchr (base_name, '.') != NULL | 872 if (strchr (base_name, '.') != NULL |
858 && strcmp (setlocale (LC_CTYPE, NULL), "C") == 0) | 873 && strcmp (setlocale (LC_CTYPE, NULL), "C") == 0) |
859 goto fail; | 874 goto fail; |
860 # endif | 875 # endif |
861 | 876 |
862 for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++) | 877 for (; i < sizeof (categories) / sizeof (categories[0]); i++) |
863 { | 878 { |
864 int cat = categories[i]; | 879 int cat = categories[i]; |
865 const char *name; | 880 const char *name; |
866 | 881 |
867 name = gl_locale_name_environ (cat, category_to_name (cat)); | 882 name = gl_locale_name_environ (cat, category_to_name (cat)); |
874 # if LC_MESSAGES == 1729 | 889 # if LC_MESSAGES == 1729 |
875 || cat == LC_MESSAGES | 890 || cat == LC_MESSAGES |
876 # endif | 891 # endif |
877 ) | 892 ) |
878 if (setlocale_single (cat, name) == NULL) | 893 if (setlocale_single (cat, name) == NULL) |
894 # if defined __APPLE__ && defined __MACH__ | |
895 /* On Mac OS X 10.13, some locales can be set through | |
896 System Preferences > Language & Region, that are not | |
897 supported by libc. The system's setlocale() falls | |
898 back to "C" for these locale categories. Let's do the | |
899 same, but print a warning, to limit user expectations. */ | |
900 fprintf (stderr, | |
901 "Warning: Failed to set locale category %s to %s.\n", | |
902 category_to_name (cat), name); | |
903 # else | |
879 goto fail; | 904 goto fail; |
905 # endif | |
880 } | 906 } |
881 | 907 |
882 /* All steps were successful. */ | 908 /* All steps were successful. */ |
883 free (saved_locale); | 909 free (saved_locale); |
884 return setlocale (LC_ALL, NULL); | 910 return setlocale (LC_ALL, NULL); |