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);