This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
d_setlocale.U: Add more info to user messages
[metaconfig.git] / U / perl / d_setlocale.U
1 ?RCS: Copyright (c) 1991-1997, 2004-2006, Raphael Manfredi
2 ?RCS: Copyright (c) 2019, Karl Williamson
3 ?RCS:
4 ?RCS: You may redistribute only under the terms of the Artistic Licence,
5 ?RCS: as specified in the README file that comes with the distribution.
6 ?RCS: You may reuse parts of this distribution only within the terms of
7 ?RCS: that same Artistic Licence; a copy of which may be found at the root
8 ?RCS: of the source tree for dist 4.0.
9 ?RCS:
10 ?MAKE:d_setlocale d_setlocale_accepts_any_locale_name d_has_C_UTF8: \
11         cat Compile run rm_try i_locale i_wctype d_towupper Setvar Myread
12 ?MAKE:  -pick add $@ %<
13 ?S:d_has_C_UTF8:
14 ?S:     This variable is set to either "true" or "false" depending on
15 ?S:     whether the compilation system supports the C.UTF-8 locale.
16 ?S:.
17 ?S:d_setlocale:
18 ?S:     This variable conditionally defines HAS_SETLOCALE if setlocale() is
19 ?S:     available to handle locale-specific ctype implementations.
20 ?S:.
21 ?S:d_setlocale_accepts_any_locale_name:
22 ?S:     This variable conditionally defines SETLOCALE_ACCEPTS_ANY_LOCALE_NAME
23 ?S:     if setlocale() accepts any locale name.
24 ?S:.
25 ?C:HAS_SETLOCALE:
26 ?C:     This symbol, if defined, indicates that the setlocale routine is
27 ?C:     available to handle locale-specific ctype implementations.
28 ?C:.
29 ?C:SETLOCALE_ACCEPTS_ANY_LOCALE_NAME:
30 ?C:     This symbol, if defined, indicates that the setlocale routine is
31 ?C:     available and it accepts any input locale name as valid.
32 ?C:.
33 ?H:#$d_setlocale HAS_SETLOCALE  /**/
34 ?H:#$d_setlocale_accepts_any_locale_name SETLOCALE_ACCEPTS_ANY_LOCALE_NAME      /**/
35 ?H:.
36 ?F:!try
37 ?T:LC_CTYPE c_utf8_locale
38 : check for setlocale function and behavior
39 case "$d_setlocale" in
40 '')
41 $cat >&4 <<EOM
42
43 Checking to see if you have setlocale() and its behavior
44 EOM
45 $cat >try.c <<EOCP
46 #include <stdlib.h>
47 #include <string.h>
48 #$i_locale I_LOCALE
49 #ifdef I_LOCALE
50 #  include <locale.h>
51 #endif
52 #$i_wctype I_WCTYPE
53 #ifdef I_WCTYPE
54 #  include <wctype.h>
55 #endif
56
57 int main() {
58     const char * invalid_name = "\a";   /* This is really invalid! */
59     int accepts_any_locale_name = 0;
60     int has_C_UTF8 = 0;
61     unsigned char bad_setlocale = 255;
62
63     /* If LC_CTYPE isn't defined the compilation will fail, and locales will be
64      * disabled.  It's hard to imagine an instance where meaningful locale
65      * handling could be done without LC_CTYPE */
66     const char *  name = setlocale(LC_CTYPE, "C");
67
68     if (name == NULL || strcmp(name, "C") != 0) {
69         exit(bad_setlocale);
70     }
71
72     name = setlocale(LC_CTYPE, invalid_name);
73     if (name != NULL) {
74
75         /* Let it pass if it accepts the name but gives back one of the C
76          * locales */
77         if (strcmp(name, "C") != 0 && strcmp(name, "C.UTF-8") != 0) {
78             accepts_any_locale_name = 1;
79         }
80     }
81
82     name = setlocale(LC_CTYPE, "C.UTF-8");
83     if (name != NULL) {
84         unsigned char y_with_diaeresis = ('A' == 193) ? 0xDF : 0xFF;
85
86 #$d_towupper HAS_TOWUPPER
87 #ifdef HAS_TOWUPPER
88
89         /* We assume that if the machine doesn't have the C99 towupper, it
90          * doesn't have C.UTF-8, even if we successfully changed locales to
91          * include it.  This seems safer even on platforms that didn't accept
92          * the really invalid name */
93
94         if (towupper(y_with_diaeresis) == 0x178) {
95             has_C_UTF8 = 1;
96         }
97
98 #endif
99
100     }
101
102 #if 0
103
104     /* Currently unused code to determine if LC_ALL with disparate values uses
105      * category = value pairs or positional, and to determine the separator
106      * between the categories.  We could add code so that if the separator were
107      * > '9', we subtract 10; similarly for 'Z' and 'z', and then just about
108      * every possible ASCII separator would fit in the 5 bits available in the
109      * exit code.  This would not be true in EBCDIC.  And then if LC_ALL is
110      * positional, we probably would want to know the order of the categories.
111      * Using a file between the C program and the shell script would really be
112      * require to do that */
113 #ifdef LC_ALL
114
115     unsigned char min_separator = ' ' - 1;
116     unsigned char separator = min_separator;
117     int uses_name_value_pair_names = 0;
118
119     name = setlocale(LC_ALL, "C");
120     if (name == NULL || strcmp(name, "C") != 0) {
121         exit(bad_setlocale);
122     }
123
124     if (has_C_UTF8) {
125         char * pos;
126
127         name = setlocale(LC_CTYPE, "C.UTF-8");
128         if (name == NULL) {
129             exit(bad_setlocale);
130         }
131         name = setlocale(LC_ALL, NULL);
132         if (name == NULL) {
133             exit(bad_setlocale);
134         }
135
136         pos = strstr(name, "LC_CTYPE" "=C.UTF-8");
137         if (pos != NULL) {
138             uses_name_value_pair_names = 1;
139             if (pos == name) {
140                 separator = name[sizeof("LC_CTYPE=C.UTF-8") - 1];
141             }
142             else {
143                 separator = *(pos - 1);
144             }
145         }
146         else {
147             pos = strstr(name, "C.UTF-8");
148             if (pos == NULL) {
149                 /* bad */
150             }
151             else if (pos == name) {
152                 separator = name[sizeof("C.UTF-8") - 1];
153             }
154             else {
155                 separator = *(pos - 1);
156             }
157         }
158     }
159
160 #endif
161 #endif
162
163     exit( 0 /* (separator - min_separator) << 3
164         | uses_name_value_pair_names      << 2
165           */
166         | has_C_UTF8                      << 1
167         | accepts_any_locale_name);
168
169 }
170 EOCP
171 val=
172 set d_setlocale
173 eval $setvar
174 case $d_setlocale in
175     $undef) d_setlocale_accepts_any_locale_name="$undef"
176             d_has_C_UTF8="false"
177             ;;
178     *) set try
179        if eval $compile; then
180            echo "Your system has setlocale()..." >&4
181            $run ./try
182            case $? in
183                0) echo "and it seems sane; you don't have a C.UTF8 locale" >&4
184                   d_setlocale="$define"
185                   d_setlocale_accepts_any_locale_name="$undef"
186                   d_has_C_UTF8="false"
187                   ;;
188                1) echo "and it seems sane, but accepts any locale name as valid" >&4
189                   d_setlocale="$define"
190                   d_setlocale_accepts_any_locale_name="$define"
191                   d_has_C_UTF8="false"
192                   ;;
193                2) echo "and it seems sane; you have a C.UTF8 locale" >&4
194                   d_setlocale="$define"
195                   d_setlocale_accepts_any_locale_name="$undef"
196                   d_has_C_UTF8="true"
197                   ;;
198                3) echo "and it seems sane, but accepts any locale name as valid" >&4
199                   d_setlocale="$define"
200                   d_setlocale_accepts_any_locale_name="$define"
201                   d_has_C_UTF8="true"
202                   ;;
203                *) echo "but it doesn't seem to work, so we won't use it." >&4
204                   d_setlocale="$undef"
205                   d_setlocale_accepts_any_locale_name="$undef"
206                   d_has_C_UTF8="false"
207                   ;;
208            esac
209        else
210            echo "your system does not have setlocale()" >&4
211            d_setlocale="$undef"
212            d_setlocale_accepts_any_locale_name="$undef"
213            d_has_C_UTF8="false"
214        fi
215 esac
216 $rm_try
217 ;;
218 *) val="$d_setlocale"
219     set d_setlocale
220     eval $setvar
221     case "$d_setlocale" in
222         $undef) echo "There may be other ways to set the locale on your system, so we need to ask:" >&4
223         ;;
224     esac
225     rp="Does your system have the C.UTF8 locale?"
226     dflt=n
227     . ./myread
228     case "$ans" in
229         [Yy]*) d_has_C_UTF8="true"
230                c_utf8_locale=" or C.UTF8"
231                ;;
232         *)     d_has_C_UTF8="false"
233                c_utf8_locale=""
234                ;;
235     esac
236     case "$d_setlocale" in
237         $define)
238             rp="When you set your locale to something besides C$c_utf8_locale, does it do so, or just pretend to?" >&4
239             dflt=n
240             . ./myread
241             case "$ans" in
242                 true|[Yy]*)
243                    d_setlocale_accepts_any_locale_name="$undef"
244                    ;;
245                 *) d_setlocale_accepts_any_locale_name="$define"
246                    ;;
247             esac
248             ;;
249         *) d_setlocale_accepts_any_locale_name="$undef"
250            ;;
251     esac
252 esac
253