[Encode] 1.77 Released
[p5sagit/p5-mst-13.2.git] / locale.c
1 /*    locale.c
2  *
3  *    Copyright (c) 2001-2002, Larry Wall
4  *
5  *    You may distribute under the terms of either the GNU General Public
6  *    License or the Artistic License, as specified in the README file.
7  *
8  */
9
10 /*
11  * A Elbereth Gilthoniel,
12  * silivren penna míriel
13  * o menel aglar elenath!
14  * Na-chaered palan-díriel
15  * o galadhremmin ennorath,
16  * Fanuilos, le linnathon
17  * nef aear, si nef aearon!
18  */
19
20 #include "EXTERN.h"
21 #define PERL_IN_LOCALE_C
22 #include "perl.h"
23
24 #ifdef I_LOCALE
25 #  include <locale.h>
26 #endif
27
28 #ifdef I_LANGINFO
29 #   include <langinfo.h>
30 #endif
31
32 #include "reentr.h"
33
34 /*
35  * Standardize the locale name from a string returned by 'setlocale'.
36  *
37  * The standard return value of setlocale() is either
38  * (1) "xx_YY" if the first argument of setlocale() is not LC_ALL
39  * (2) "xa_YY xb_YY ..." if the first argument of setlocale() is LC_ALL
40  *     (the space-separated values represent the various sublocales,
41  *      in some unspecificed order)
42  *
43  * In some platforms it has a form like "LC_SOMETHING=Lang_Country.866\n",
44  * which is harmful for further use of the string in setlocale().
45  *
46  */
47 STATIC char *
48 S_stdize_locale(pTHX_ char *locs)
49 {
50     char *s;
51     bool okay = TRUE;
52
53     if ((s = strchr(locs, '='))) {
54         char *t;
55
56         okay = FALSE;
57         if ((t = strchr(s, '.'))) {
58             char *u;
59
60             if ((u = strchr(t, '\n'))) {
61
62                 if (u[1] == 0) {
63                     STRLEN len = u - s;
64                     Move(s + 1, locs, len, char);
65                     locs[len] = 0;
66                     okay = TRUE;
67                 }
68             }
69         }
70     }
71
72     if (!okay)
73         Perl_croak(aTHX_ "Can't fix broken locale name \"%s\"", locs);
74
75     return locs;
76 }
77
78 void
79 Perl_set_numeric_radix(pTHX)
80 {
81 #ifdef USE_LOCALE_NUMERIC
82 # ifdef HAS_LOCALECONV
83     struct lconv* lc;
84
85     lc = localeconv();
86     if (lc && lc->decimal_point) {
87         if (lc->decimal_point[0] == '.' && lc->decimal_point[1] == 0) {
88             SvREFCNT_dec(PL_numeric_radix_sv);
89             PL_numeric_radix_sv = Nullsv;
90         }
91         else {
92             if (PL_numeric_radix_sv)
93                 sv_setpv(PL_numeric_radix_sv, lc->decimal_point);
94             else
95                 PL_numeric_radix_sv = newSVpv(lc->decimal_point, 0);
96         }
97     }
98     else
99         PL_numeric_radix_sv = Nullsv;
100 # endif /* HAS_LOCALECONV */
101 #endif /* USE_LOCALE_NUMERIC */
102 }
103
104 /*
105  * Set up for a new numeric locale.
106  */
107 void
108 Perl_new_numeric(pTHX_ char *newnum)
109 {
110 #ifdef USE_LOCALE_NUMERIC
111
112     if (! newnum) {
113         if (PL_numeric_name) {
114             Safefree(PL_numeric_name);
115             PL_numeric_name = NULL;
116         }
117         PL_numeric_standard = TRUE;
118         PL_numeric_local = TRUE;
119         return;
120     }
121
122     if (! PL_numeric_name || strNE(PL_numeric_name, newnum)) {
123         Safefree(PL_numeric_name);
124         PL_numeric_name = stdize_locale(savepv(newnum));
125         PL_numeric_standard = (strEQ(newnum, "C") || strEQ(newnum, "POSIX"));
126         PL_numeric_local = TRUE;
127         set_numeric_radix();
128     }
129
130 #endif /* USE_LOCALE_NUMERIC */
131 }
132
133 void
134 Perl_set_numeric_standard(pTHX)
135 {
136 #ifdef USE_LOCALE_NUMERIC
137
138     if (! PL_numeric_standard) {
139         setlocale(LC_NUMERIC, "C");
140         PL_numeric_standard = TRUE;
141         PL_numeric_local = FALSE;
142         set_numeric_radix();
143     }
144
145 #endif /* USE_LOCALE_NUMERIC */
146 }
147
148 void
149 Perl_set_numeric_local(pTHX)
150 {
151 #ifdef USE_LOCALE_NUMERIC
152
153     if (! PL_numeric_local) {
154         setlocale(LC_NUMERIC, PL_numeric_name);
155         PL_numeric_standard = FALSE;
156         PL_numeric_local = TRUE;
157         set_numeric_radix();
158     }
159
160 #endif /* USE_LOCALE_NUMERIC */
161 }
162
163 /*
164  * Set up for a new ctype locale.
165  */
166 void
167 Perl_new_ctype(pTHX_ char *newctype)
168 {
169 #ifdef USE_LOCALE_CTYPE
170
171     int i;
172
173     for (i = 0; i < 256; i++) {
174         if (isUPPER_LC(i))
175             PL_fold_locale[i] = toLOWER_LC(i);
176         else if (isLOWER_LC(i))
177             PL_fold_locale[i] = toUPPER_LC(i);
178         else
179             PL_fold_locale[i] = i;
180     }
181
182 #endif /* USE_LOCALE_CTYPE */
183 }
184
185 /*
186  * Set up for a new collation locale.
187  */
188 void
189 Perl_new_collate(pTHX_ char *newcoll)
190 {
191 #ifdef USE_LOCALE_COLLATE
192
193     if (! newcoll) {
194         if (PL_collation_name) {
195             ++PL_collation_ix;
196             Safefree(PL_collation_name);
197             PL_collation_name = NULL;
198         }
199         PL_collation_standard = TRUE;
200         PL_collxfrm_base = 0;
201         PL_collxfrm_mult = 2;
202         return;
203     }
204
205     if (! PL_collation_name || strNE(PL_collation_name, newcoll)) {
206         ++PL_collation_ix;
207         Safefree(PL_collation_name);
208         PL_collation_name = stdize_locale(savepv(newcoll));
209         PL_collation_standard = (strEQ(newcoll, "C") || strEQ(newcoll, "POSIX"));
210
211         {
212           /*  2: at most so many chars ('a', 'b'). */
213           /* 50: surely no system expands a char more. */
214 #define XFRMBUFSIZE  (2 * 50)
215           char xbuf[XFRMBUFSIZE];
216           Size_t fa = strxfrm(xbuf, "a",  XFRMBUFSIZE);
217           Size_t fb = strxfrm(xbuf, "ab", XFRMBUFSIZE);
218           SSize_t mult = fb - fa;
219           if (mult < 1)
220               Perl_croak(aTHX_ "strxfrm() gets absurd");
221           PL_collxfrm_base = (fa > (Size_t)mult) ? (fa - mult) : 0;
222           PL_collxfrm_mult = mult;
223         }
224     }
225
226 #endif /* USE_LOCALE_COLLATE */
227 }
228
229 /*
230  * Initialize locale awareness.
231  */
232 int
233 Perl_init_i18nl10n(pTHX_ int printwarn)
234 {
235     int ok = 1;
236     /* returns
237      *    1 = set ok or not applicable,
238      *    0 = fallback to C locale,
239      *   -1 = fallback to C locale failed
240      */
241
242 #if defined(USE_LOCALE)
243
244 #ifdef USE_LOCALE_CTYPE
245     char *curctype   = NULL;
246 #endif /* USE_LOCALE_CTYPE */
247 #ifdef USE_LOCALE_COLLATE
248     char *curcoll    = NULL;
249 #endif /* USE_LOCALE_COLLATE */
250 #ifdef USE_LOCALE_NUMERIC
251     char *curnum     = NULL;
252 #endif /* USE_LOCALE_NUMERIC */
253 #ifdef __GLIBC__
254     char *language   = PerlEnv_getenv("LANGUAGE");
255 #endif
256     char *lc_all     = PerlEnv_getenv("LC_ALL");
257     char *lang       = PerlEnv_getenv("LANG");
258     bool setlocale_failure = FALSE;
259
260 #ifdef LOCALE_ENVIRON_REQUIRED
261
262     /*
263      * Ultrix setlocale(..., "") fails if there are no environment
264      * variables from which to get a locale name.
265      */
266
267     bool done = FALSE;
268
269 #ifdef LC_ALL
270     if (lang) {
271         if (setlocale(LC_ALL, ""))
272             done = TRUE;
273         else
274             setlocale_failure = TRUE;
275     }
276     if (!setlocale_failure) {
277 #ifdef USE_LOCALE_CTYPE
278         if (! (curctype =
279                setlocale(LC_CTYPE,
280                          (!done && (lang || PerlEnv_getenv("LC_CTYPE")))
281                                     ? "" : Nullch)))
282             setlocale_failure = TRUE;
283         else
284             curctype = savepv(curctype);
285 #endif /* USE_LOCALE_CTYPE */
286 #ifdef USE_LOCALE_COLLATE
287         if (! (curcoll =
288                setlocale(LC_COLLATE,
289                          (!done && (lang || PerlEnv_getenv("LC_COLLATE")))
290                                    ? "" : Nullch)))
291             setlocale_failure = TRUE;
292         else
293             curcoll = savepv(curcoll);
294 #endif /* USE_LOCALE_COLLATE */
295 #ifdef USE_LOCALE_NUMERIC
296         if (! (curnum =
297                setlocale(LC_NUMERIC,
298                          (!done && (lang || PerlEnv_getenv("LC_NUMERIC")))
299                                   ? "" : Nullch)))
300             setlocale_failure = TRUE;
301         else
302             curnum = savepv(curnum);
303 #endif /* USE_LOCALE_NUMERIC */
304     }
305
306 #endif /* LC_ALL */
307
308 #endif /* !LOCALE_ENVIRON_REQUIRED */
309
310 #ifdef LC_ALL
311     if (! setlocale(LC_ALL, ""))
312         setlocale_failure = TRUE;
313 #endif /* LC_ALL */
314
315     if (!setlocale_failure) {
316 #ifdef USE_LOCALE_CTYPE
317         if (! (curctype = setlocale(LC_CTYPE, "")))
318             setlocale_failure = TRUE;
319         else
320             curctype = savepv(curctype);
321 #endif /* USE_LOCALE_CTYPE */
322 #ifdef USE_LOCALE_COLLATE
323         if (! (curcoll = setlocale(LC_COLLATE, "")))
324             setlocale_failure = TRUE;
325         else
326             curcoll = savepv(curcoll);
327 #endif /* USE_LOCALE_COLLATE */
328 #ifdef USE_LOCALE_NUMERIC
329         if (! (curnum = setlocale(LC_NUMERIC, "")))
330             setlocale_failure = TRUE;
331         else
332             curnum = savepv(curnum);
333 #endif /* USE_LOCALE_NUMERIC */
334     }
335
336     if (setlocale_failure) {
337         char *p;
338         bool locwarn = (printwarn > 1 ||
339                         (printwarn &&
340                          (!(p = PerlEnv_getenv("PERL_BADLANG")) || atoi(p))));
341
342         if (locwarn) {
343 #ifdef LC_ALL
344
345             PerlIO_printf(Perl_error_log,
346                "perl: warning: Setting locale failed.\n");
347
348 #else /* !LC_ALL */
349
350             PerlIO_printf(Perl_error_log,
351                "perl: warning: Setting locale failed for the categories:\n\t");
352 #ifdef USE_LOCALE_CTYPE
353             if (! curctype)
354                 PerlIO_printf(Perl_error_log, "LC_CTYPE ");
355 #endif /* USE_LOCALE_CTYPE */
356 #ifdef USE_LOCALE_COLLATE
357             if (! curcoll)
358                 PerlIO_printf(Perl_error_log, "LC_COLLATE ");
359 #endif /* USE_LOCALE_COLLATE */
360 #ifdef USE_LOCALE_NUMERIC
361             if (! curnum)
362                 PerlIO_printf(Perl_error_log, "LC_NUMERIC ");
363 #endif /* USE_LOCALE_NUMERIC */
364             PerlIO_printf(Perl_error_log, "\n");
365
366 #endif /* LC_ALL */
367
368             PerlIO_printf(Perl_error_log,
369                 "perl: warning: Please check that your locale settings:\n");
370
371 #ifdef __GLIBC__
372             PerlIO_printf(Perl_error_log,
373                           "\tLANGUAGE = %c%s%c,\n",
374                           language ? '"' : '(',
375                           language ? language : "unset",
376                           language ? '"' : ')');
377 #endif
378
379             PerlIO_printf(Perl_error_log,
380                           "\tLC_ALL = %c%s%c,\n",
381                           lc_all ? '"' : '(',
382                           lc_all ? lc_all : "unset",
383                           lc_all ? '"' : ')');
384
385 #if defined(USE_ENVIRON_ARRAY)
386             {
387               char **e;
388               for (e = environ; *e; e++) {
389                   if (strnEQ(*e, "LC_", 3)
390                         && strnNE(*e, "LC_ALL=", 7)
391                         && (p = strchr(*e, '=')))
392                       PerlIO_printf(Perl_error_log, "\t%.*s = \"%s\",\n",
393                                     (int)(p - *e), *e, p + 1);
394               }
395             }
396 #else
397             PerlIO_printf(Perl_error_log,
398                           "\t(possibly more locale environment variables)\n");
399 #endif
400
401             PerlIO_printf(Perl_error_log,
402                           "\tLANG = %c%s%c\n",
403                           lang ? '"' : '(',
404                           lang ? lang : "unset",
405                           lang ? '"' : ')');
406
407             PerlIO_printf(Perl_error_log,
408                           "    are supported and installed on your system.\n");
409         }
410
411 #ifdef LC_ALL
412
413         if (setlocale(LC_ALL, "C")) {
414             if (locwarn)
415                 PerlIO_printf(Perl_error_log,
416       "perl: warning: Falling back to the standard locale (\"C\").\n");
417             ok = 0;
418         }
419         else {
420             if (locwarn)
421                 PerlIO_printf(Perl_error_log,
422       "perl: warning: Failed to fall back to the standard locale (\"C\").\n");
423             ok = -1;
424         }
425
426 #else /* ! LC_ALL */
427
428         if (0
429 #ifdef USE_LOCALE_CTYPE
430             || !(curctype || setlocale(LC_CTYPE, "C"))
431 #endif /* USE_LOCALE_CTYPE */
432 #ifdef USE_LOCALE_COLLATE
433             || !(curcoll || setlocale(LC_COLLATE, "C"))
434 #endif /* USE_LOCALE_COLLATE */
435 #ifdef USE_LOCALE_NUMERIC
436             || !(curnum || setlocale(LC_NUMERIC, "C"))
437 #endif /* USE_LOCALE_NUMERIC */
438             )
439         {
440             if (locwarn)
441                 PerlIO_printf(Perl_error_log,
442       "perl: warning: Cannot fall back to the standard locale (\"C\").\n");
443             ok = -1;
444         }
445
446 #endif /* ! LC_ALL */
447
448 #ifdef USE_LOCALE_CTYPE
449         curctype = savepv(setlocale(LC_CTYPE, Nullch));
450 #endif /* USE_LOCALE_CTYPE */
451 #ifdef USE_LOCALE_COLLATE
452         curcoll = savepv(setlocale(LC_COLLATE, Nullch));
453 #endif /* USE_LOCALE_COLLATE */
454 #ifdef USE_LOCALE_NUMERIC
455         curnum = savepv(setlocale(LC_NUMERIC, Nullch));
456 #endif /* USE_LOCALE_NUMERIC */
457     }
458     else {
459
460 #ifdef USE_LOCALE_CTYPE
461     new_ctype(curctype);
462 #endif /* USE_LOCALE_CTYPE */
463
464 #ifdef USE_LOCALE_COLLATE
465     new_collate(curcoll);
466 #endif /* USE_LOCALE_COLLATE */
467
468 #ifdef USE_LOCALE_NUMERIC
469     new_numeric(curnum);
470 #endif /* USE_LOCALE_NUMERIC */
471
472     }
473
474 #endif /* USE_LOCALE */
475
476 #ifdef USE_PERLIO
477     {
478       /* Set PL_wantutf8 to TRUE if using PerlIO _and_
479          any of the following are true:
480          - nl_langinfo(CODESET) contains /^utf-?8/i
481          - $ENV{LANGUAGE} contains /^utf-?8/i (only if using glibc)
482          - $ENV{LC_CALL} contains /^utf-?8/i
483          - $ENV{LC_CTYPE} contains /^utf-?8/i
484          - $ENV{LANG} contains /^utf-?8/i
485          If PL_wantutf8 is true, perl.c:S_parse_body()
486          will turn on the PerlIO :utf8 discipline on STDIN, STDOUT,
487          STDERR, _and_ the default open discipline.
488       */
489          bool wantutf8 = FALSE;
490          char *codeset = NULL;
491 #if defined(HAS_NL_LANGINFO) && defined(CODESET)
492          codeset = nl_langinfo(CODESET);
493 #endif
494          if (codeset &&
495              (ibcmp(codeset,  "UTF-8", 5) == 0 ||
496               ibcmp(codeset,  "UTF8",  4) == 0))
497               wantutf8 = TRUE;
498 #if defined(USE_LOCALE)
499 #ifdef __GLIBC__
500          if (!wantutf8 && language &&
501              (ibcmp(language, "UTF-8", 5) == 0 ||
502               ibcmp(language, "UTF8",  4) == 0))
503               wantutf8 = TRUE;
504 #endif
505          if (!wantutf8 && lc_all &&
506              (ibcmp(lc_all,   "UTF-8", 5) == 0 ||
507               ibcmp(lc_all,   "UTF8",  4) == 0))
508               wantutf8 = TRUE;
509 #ifdef USE_LOCALE_CTYPE
510          if (!wantutf8 && curctype &&
511              (ibcmp(curctype,     "UTF-8", 5) == 0 ||
512               ibcmp(curctype,     "UTF8",  4) == 0))
513               wantutf8 = TRUE;
514 #endif
515          if (!wantutf8 && lang &&
516              (ibcmp(lang,     "UTF-8", 5) == 0 ||
517               ibcmp(lang,     "UTF8",  4) == 0))
518               wantutf8 = TRUE;
519 #endif /* USE_LOCALE */
520          if (wantutf8)
521               PL_wantutf8 = TRUE;
522     }
523 #endif
524
525 #ifdef USE_LOCALE_CTYPE
526     if (curctype != NULL)
527         Safefree(curctype);
528 #endif /* USE_LOCALE_CTYPE */
529 #ifdef USE_LOCALE_COLLATE
530     if (curcoll != NULL)
531         Safefree(curcoll);
532 #endif /* USE_LOCALE_COLLATE */
533 #ifdef USE_LOCALE_NUMERIC
534     if (curnum != NULL)
535         Safefree(curnum);
536 #endif /* USE_LOCALE_NUMERIC */
537     return ok;
538 }
539
540 /* Backwards compatibility. */
541 int
542 Perl_init_i18nl14n(pTHX_ int printwarn)
543 {
544     return init_i18nl10n(printwarn);
545 }
546
547 #ifdef USE_LOCALE_COLLATE
548
549 /*
550  * mem_collxfrm() is a bit like strxfrm() but with two important
551  * differences. First, it handles embedded NULs. Second, it allocates
552  * a bit more memory than needed for the transformed data itself.
553  * The real transformed data begins at offset sizeof(collationix).
554  * Please see sv_collxfrm() to see how this is used.
555  */
556 char *
557 Perl_mem_collxfrm(pTHX_ const char *s, STRLEN len, STRLEN *xlen)
558 {
559     char *xbuf;
560     STRLEN xAlloc, xin, xout; /* xalloc is a reserved word in VC */
561
562     /* the first sizeof(collationix) bytes are used by sv_collxfrm(). */
563     /* the +1 is for the terminating NUL. */
564
565     xAlloc = sizeof(PL_collation_ix) + PL_collxfrm_base + (PL_collxfrm_mult * len) + 1;
566     New(171, xbuf, xAlloc, char);
567     if (! xbuf)
568         goto bad;
569
570     *(U32*)xbuf = PL_collation_ix;
571     xout = sizeof(PL_collation_ix);
572     for (xin = 0; xin < len; ) {
573         SSize_t xused;
574
575         for (;;) {
576             xused = strxfrm(xbuf + xout, s + xin, xAlloc - xout);
577             if (xused == -1)
578                 goto bad;
579             if ((STRLEN)xused < xAlloc - xout)
580                 break;
581             xAlloc = (2 * xAlloc) + 1;
582             Renew(xbuf, xAlloc, char);
583             if (! xbuf)
584                 goto bad;
585         }
586
587         xin += strlen(s + xin) + 1;
588         xout += xused;
589
590         /* Embedded NULs are understood but silently skipped
591          * because they make no sense in locale collation. */
592     }
593
594     xbuf[xout] = '\0';
595     *xlen = xout - sizeof(PL_collation_ix);
596     return xbuf;
597
598   bad:
599     Safefree(xbuf);
600     *xlen = 0;
601     return NULL;
602 }
603
604 #endif /* USE_LOCALE_COLLATE */
605