X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/66610fdd5da795f6de595e815ccc4d1c9f3f4505..ccb58ea9c92c04da4d563dd590a79a336d9a6214:/locale.c diff --git a/locale.c b/locale.c index 526a568..c10228d 100644 --- a/locale.c +++ b/locale.c @@ -1,7 +1,7 @@ /* locale.c * - * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, 2005, by Larry Wall and others + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + * 2002, 2003, 2005, 2006, 2007, 2008 by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -9,13 +9,15 @@ */ /* - * A Elbereth Gilthoniel, - * silivren penna míriel - * o menel aglar elenath! - * Na-chaered palan-díriel - * o galadhremmin ennorath, - * Fanuilos, le linnathon - * nef aear, si nef aearon! + * A Elbereth Gilthoniel, + * silivren penna míriel + * o menel aglar elenath! + * Na-chaered palan-díriel + * o galadhremmin ennorath, + * Fanuilos, le linnathon + * nef aear, si nef aearon! + * + * [p.238 of _The Lord of the Rings_, II/i: "Many Meetings"] */ /* utility functions for handling locale-specific stuff like what @@ -26,10 +28,6 @@ #define PERL_IN_LOCALE_C #include "perl.h" -#ifdef I_LOCALE -# include -#endif - #ifdef I_LANGINFO # include #endif @@ -44,7 +42,7 @@ * (1) "xx_YY" if the first argument of setlocale() is not LC_ALL * (2) "xa_YY xb_YY ..." if the first argument of setlocale() is LC_ALL * (the space-separated values represent the various sublocales, - * in some unspecificed order) + * in some unspecified order) * * In some platforms it has a form like "LC_SOMETHING=Lang_Country.866\n", * which is harmful for further use of the string in setlocale(). @@ -53,24 +51,21 @@ STATIC char * S_stdize_locale(pTHX_ char *locs) { - char *s; + const char * const s = strchr(locs, '='); bool okay = TRUE; - if ((s = strchr(locs, '='))) { - char *t; + PERL_ARGS_ASSERT_STDIZE_LOCALE; + if (s) { + const char * const t = strchr(s, '.'); okay = FALSE; - if ((t = strchr(s, '.'))) { - char *u; - - if ((u = strchr(t, '\n'))) { - - if (u[1] == 0) { - STRLEN len = u - s; - Move(s + 1, locs, len, char); - locs[len] = 0; - okay = TRUE; - } + if (t) { + const char * const u = strchr(t, '\n'); + if (u && (u[1] == 0)) { + const STRLEN len = u - s; + Move(s + 1, locs, len, char); + locs[len] = 0; + okay = TRUE; } } } @@ -86,14 +81,14 @@ void Perl_set_numeric_radix(pTHX) { #ifdef USE_LOCALE_NUMERIC + dVAR; # ifdef HAS_LOCALECONV - struct lconv* lc; + const struct lconv* const lc = localeconv(); - lc = localeconv(); if (lc && lc->decimal_point) { if (lc->decimal_point[0] == '.' && lc->decimal_point[1] == 0) { SvREFCNT_dec(PL_numeric_radix_sv); - PL_numeric_radix_sv = Nullsv; + PL_numeric_radix_sv = NULL; } else { if (PL_numeric_radix_sv) @@ -103,7 +98,7 @@ Perl_set_numeric_radix(pTHX) } } else - PL_numeric_radix_sv = Nullsv; + PL_numeric_radix_sv = NULL; # endif /* HAS_LOCALECONV */ #endif /* USE_LOCALE_NUMERIC */ } @@ -112,15 +107,14 @@ Perl_set_numeric_radix(pTHX) * Set up for a new numeric locale. */ void -Perl_new_numeric(pTHX_ char *newnum) +Perl_new_numeric(pTHX_ const char *newnum) { #ifdef USE_LOCALE_NUMERIC + dVAR; if (! newnum) { - if (PL_numeric_name) { - Safefree(PL_numeric_name); - PL_numeric_name = NULL; - } + Safefree(PL_numeric_name); + PL_numeric_name = NULL; PL_numeric_standard = TRUE; PL_numeric_local = TRUE; return; @@ -142,6 +136,7 @@ void Perl_set_numeric_standard(pTHX) { #ifdef USE_LOCALE_NUMERIC + dVAR; if (! PL_numeric_standard) { setlocale(LC_NUMERIC, "C"); @@ -157,6 +152,7 @@ void Perl_set_numeric_local(pTHX) { #ifdef USE_LOCALE_NUMERIC + dVAR; if (! PL_numeric_local) { setlocale(LC_NUMERIC, PL_numeric_name); @@ -172,12 +168,14 @@ Perl_set_numeric_local(pTHX) * Set up for a new ctype locale. */ void -Perl_new_ctype(pTHX_ char *newctype) +Perl_new_ctype(pTHX_ const char *newctype) { #ifdef USE_LOCALE_CTYPE dVAR; int i; + PERL_ARGS_ASSERT_NEW_CTYPE; + for (i = 0; i < 256; i++) { if (isUPPER_LC(i)) PL_fold_locale[i] = toLOWER_LC(i); @@ -188,16 +186,19 @@ Perl_new_ctype(pTHX_ char *newctype) } #endif /* USE_LOCALE_CTYPE */ - (void)newctype; + PERL_ARGS_ASSERT_NEW_CTYPE; + PERL_UNUSED_ARG(newctype); + PERL_UNUSED_CONTEXT; } /* * Set up for a new collation locale. */ void -Perl_new_collate(pTHX_ char *newcoll) +Perl_new_collate(pTHX_ const char *newcoll) { #ifdef USE_LOCALE_COLLATE + dVAR; if (! newcoll) { if (PL_collation_name) { @@ -223,11 +224,12 @@ Perl_new_collate(pTHX_ char *newcoll) /* 50: surely no system expands a char more. */ #define XFRMBUFSIZE (2 * 50) char xbuf[XFRMBUFSIZE]; - Size_t fa = strxfrm(xbuf, "a", XFRMBUFSIZE); - Size_t fb = strxfrm(xbuf, "ab", XFRMBUFSIZE); - SSize_t mult = fb - fa; - if (mult < 1) - Perl_croak(aTHX_ "strxfrm() gets absurd"); + const Size_t fa = strxfrm(xbuf, "a", XFRMBUFSIZE); + const Size_t fb = strxfrm(xbuf, "ab", XFRMBUFSIZE); + const SSize_t mult = fb - fa; + if (mult < 1 && !(fa == 0 && fb == 0)) + Perl_croak(aTHX_ "panic: strxfrm() gets absurd - a => %"UVuf", ab => %"UVuf, + (UV) fa, (UV) fb); PL_collxfrm_base = (fa > (Size_t)mult) ? (fa - mult) : 0; PL_collxfrm_mult = mult; } @@ -250,6 +252,7 @@ Perl_init_i18nl10n(pTHX_ int printwarn) */ #if defined(USE_LOCALE) + dVAR; #ifdef USE_LOCALE_CTYPE char *curctype = NULL; @@ -261,10 +264,10 @@ Perl_init_i18nl10n(pTHX_ int printwarn) char *curnum = NULL; #endif /* USE_LOCALE_NUMERIC */ #ifdef __GLIBC__ - char *language = PerlEnv_getenv("LANGUAGE"); + char * const language = PerlEnv_getenv("LANGUAGE"); #endif - char *lc_all = PerlEnv_getenv("LC_ALL"); - char *lang = PerlEnv_getenv("LANG"); + char * const lc_all = PerlEnv_getenv("LC_ALL"); + char * const lang = PerlEnv_getenv("LANG"); bool setlocale_failure = FALSE; #ifdef LOCALE_ENVIRON_REQUIRED @@ -285,28 +288,31 @@ Perl_init_i18nl10n(pTHX_ int printwarn) } if (!setlocale_failure) { #ifdef USE_LOCALE_CTYPE + Safefree(curctype); if (! (curctype = setlocale(LC_CTYPE, (!done && (lang || PerlEnv_getenv("LC_CTYPE"))) - ? "" : Nullch))) + ? "" : NULL))) setlocale_failure = TRUE; else curctype = savepv(curctype); #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE + Safefree(curcoll); if (! (curcoll = setlocale(LC_COLLATE, (!done && (lang || PerlEnv_getenv("LC_COLLATE"))) - ? "" : Nullch))) + ? "" : NULL))) setlocale_failure = TRUE; else curcoll = savepv(curcoll); #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC + Safefree(curnum); if (! (curnum = setlocale(LC_NUMERIC, (!done && (lang || PerlEnv_getenv("LC_NUMERIC"))) - ? "" : Nullch))) + ? "" : NULL))) setlocale_failure = TRUE; else curnum = savepv(curnum); @@ -324,18 +330,21 @@ Perl_init_i18nl10n(pTHX_ int printwarn) if (!setlocale_failure) { #ifdef USE_LOCALE_CTYPE + Safefree(curctype); if (! (curctype = setlocale(LC_CTYPE, ""))) setlocale_failure = TRUE; else curctype = savepv(curctype); #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE + Safefree(curcoll); if (! (curcoll = setlocale(LC_COLLATE, ""))) setlocale_failure = TRUE; else curcoll = savepv(curcoll); #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC + Safefree(curnum); if (! (curnum = setlocale(LC_NUMERIC, ""))) setlocale_failure = TRUE; else @@ -345,7 +354,7 @@ Perl_init_i18nl10n(pTHX_ int printwarn) if (setlocale_failure) { char *p; - bool locwarn = (printwarn > 1 || + const bool locwarn = (printwarn > 1 || (printwarn && (!(p = PerlEnv_getenv("PERL_BADLANG")) || atoi(p)))); @@ -456,13 +465,16 @@ Perl_init_i18nl10n(pTHX_ int printwarn) #endif /* ! LC_ALL */ #ifdef USE_LOCALE_CTYPE - curctype = savepv(setlocale(LC_CTYPE, Nullch)); + Safefree(curctype); + curctype = savepv(setlocale(LC_CTYPE, NULL)); #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE - curcoll = savepv(setlocale(LC_COLLATE, Nullch)); + Safefree(curcoll); + curcoll = savepv(setlocale(LC_COLLATE, NULL)); #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC - curnum = savepv(setlocale(LC_NUMERIC, Nullch)); + Safefree(curnum); + curnum = savepv(setlocale(LC_NUMERIC, NULL)); #endif /* USE_LOCALE_NUMERIC */ } else { @@ -507,23 +519,23 @@ Perl_init_i18nl10n(pTHX_ int printwarn) codeset = nl_langinfo(CODESET); #endif if (codeset) - utf8locale = (ibcmp(codeset, "UTF-8", 5) == 0 || - ibcmp(codeset, "UTF8", 4) == 0); + utf8locale = (foldEQ(codeset, STR_WITH_LEN("UTF-8")) + || foldEQ(codeset, STR_WITH_LEN("UTF8") )); #if defined(USE_LOCALE) else { /* nl_langinfo(CODESET) is supposed to correctly * interpret the locale environment variables, * but just in case it fails, let's do this manually. */ if (lang) - utf8locale = (ibcmp(lang, "UTF-8", 5) == 0 || - ibcmp(lang, "UTF8", 4) == 0); + utf8locale = (foldEQ(lang, STR_WITH_LEN("UTF-8")) + || foldEQ(lang, STR_WITH_LEN("UTF8") )); #ifdef USE_LOCALE_CTYPE if (curctype) - utf8locale = (ibcmp(curctype, "UTF-8", 5) == 0 || - ibcmp(curctype, "UTF8", 4) == 0); + utf8locale = (foldEQ(curctype, STR_WITH_LEN("UTF-8")) + || foldEQ(curctype, STR_WITH_LEN("UTF8") )); #endif if (lc_all) - utf8locale = (ibcmp(lc_all, "UTF-8", 5) == 0 || - ibcmp(lc_all, "UTF8", 4) == 0); + utf8locale = (foldEQ(lc_all, STR_WITH_LEN("UTF-8")) + || foldEQ(lc_all, STR_WITH_LEN("UTF8") )); } #endif /* USE_LOCALE */ if (utf8locale) @@ -535,31 +547,23 @@ Perl_init_i18nl10n(pTHX_ int printwarn) { const char *p = PerlEnv_getenv("PERL_UNICODE"); PL_unicode = p ? parse_unicode_opts(&p) : 0; + if (PL_unicode & PERL_UNICODE_UTF8CACHEASSERT_FLAG) + PL_utf8cache = -1; } #endif #ifdef USE_LOCALE_CTYPE - if (curctype != NULL) - Safefree(curctype); + Safefree(curctype); #endif /* USE_LOCALE_CTYPE */ #ifdef USE_LOCALE_COLLATE - if (curcoll != NULL) - Safefree(curcoll); + Safefree(curcoll); #endif /* USE_LOCALE_COLLATE */ #ifdef USE_LOCALE_NUMERIC - if (curnum != NULL) - Safefree(curnum); + Safefree(curnum); #endif /* USE_LOCALE_NUMERIC */ return ok; } -/* Backwards compatibility. */ -int -Perl_init_i18nl14n(pTHX_ int printwarn) -{ - return init_i18nl10n(printwarn); -} - #ifdef USE_LOCALE_COLLATE /* @@ -573,25 +577,28 @@ Perl_init_i18nl14n(pTHX_ int printwarn) char * Perl_mem_collxfrm(pTHX_ const char *s, STRLEN len, STRLEN *xlen) { + dVAR; char *xbuf; STRLEN xAlloc, xin, xout; /* xalloc is a reserved word in VC */ + PERL_ARGS_ASSERT_MEM_COLLXFRM; + /* the first sizeof(collationix) bytes are used by sv_collxfrm(). */ /* the +1 is for the terminating NUL. */ xAlloc = sizeof(PL_collation_ix) + PL_collxfrm_base + (PL_collxfrm_mult * len) + 1; - New(171, xbuf, xAlloc, char); + Newx(xbuf, xAlloc, char); if (! xbuf) goto bad; *(U32*)xbuf = PL_collation_ix; xout = sizeof(PL_collation_ix); for (xin = 0; xin < len; ) { - SSize_t xused; + Size_t xused; for (;;) { xused = strxfrm(xbuf + xout, s + xin, xAlloc - xout); - if (xused == -1) + if (xused >= PERL_INT_MAX) goto bad; if ((STRLEN)xused < xAlloc - xout) break; @@ -624,8 +631,8 @@ Perl_mem_collxfrm(pTHX_ const char *s, STRLEN len, STRLEN *xlen) * Local variables: * c-indentation-style: bsd * c-basic-offset: 4 - * indent-tabs-mode: t + * indent-tabs-mode: nil * End: * - * vim: ts=8 sts=4 sw=4 noet: -*/ + * ex: set ts=8 sts=4 sw=4 et: + */