#define isa_lookup S_isa_lookup
#endif
#if defined(PERL_IN_UTIL_C) || defined(PERL_DECL_PROT)
+#define stdize_locale S_stdize_locale
#define mess_alloc S_mess_alloc
# if defined(LEAKTEST)
#define xstat S_xstat
#define isa_lookup(a,b,c,d) S_isa_lookup(aTHX_ a,b,c,d)
#endif
#if defined(PERL_IN_UTIL_C) || defined(PERL_DECL_PROT)
+#define stdize_locale(a) S_stdize_locale(aTHX_ a)
#define mess_alloc() S_mess_alloc(aTHX)
# if defined(LEAKTEST)
#define xstat(a) S_xstat(aTHX_ a)
#define isa_lookup S_isa_lookup
#endif
#if defined(PERL_IN_UTIL_C) || defined(PERL_DECL_PROT)
+#define S_stdize_locale CPerlObj::S_stdize_locale
+#define stdize_locale S_stdize_locale
#define S_mess_alloc CPerlObj::S_mess_alloc
#define mess_alloc S_mess_alloc
# if defined(LEAKTEST)
Apd |CV* |get_cv |const char* name|I32 create
Ap |int |init_i18nl10n |int printwarn
Ap |int |init_i18nl14n |int printwarn
-Ap |void |new_collate |const char* newcoll
-Ap |void |new_ctype |const char* newctype
-Ap |void |new_numeric |const char* newcoll
+Ap |void |new_collate |char* newcoll
+Ap |void |new_ctype |char* newctype
+Ap |void |new_numeric |char* newcoll
Ap |void |set_numeric_local
Ap |void |set_numeric_radix
Ap |void |set_numeric_standard
#endif
#if defined(PERL_IN_UTIL_C) || defined(PERL_DECL_PROT)
+s |char* |stdize_locale |char* locs
s |SV* |mess_alloc
# if defined(LEAKTEST)
s |void |xstat |int
#ifdef USE_LOCALE_NUMERIC
#define SET_NUMERIC_STANDARD() \
- STMT_START { \
- if (! PL_numeric_standard) \
- set_numeric_standard(); \
- } STMT_END
+ set_numeric_standard();
#define SET_NUMERIC_LOCAL() \
- STMT_START { \
- if (! PL_numeric_local) \
- set_numeric_local(); \
- } STMT_END
+ set_numeric_local();
#define IS_NUMERIC_RADIX(c) \
((PL_hints & HINT_LOCALE) && \
#define STORE_NUMERIC_LOCAL_SET_STANDARD() \
bool was_local = (PL_hints & HINT_LOCALE) && PL_numeric_local; \
- if (!was_local) SET_NUMERIC_STANDARD();
+ if (was_local) SET_NUMERIC_STANDARD();
#define STORE_NUMERIC_STANDARD_SET_LOCAL() \
- bool was_standard = !(PL_hints & HINT_LOCALE) || PL_numeric_standard; \
- if (!was_standard) SET_NUMERIC_LOCAL();
+ bool was_standard = (PL_hints & HINT_LOCALE) && PL_numeric_standard; \
+ if (was_standard) SET_NUMERIC_LOCAL();
#define RESTORE_NUMERIC_LOCAL() \
if (was_local) SET_NUMERIC_LOCAL();
PERL_CALLCONV CV* Perl_get_cv(pTHX_ const char* name, I32 create);
PERL_CALLCONV int Perl_init_i18nl10n(pTHX_ int printwarn);
PERL_CALLCONV int Perl_init_i18nl14n(pTHX_ int printwarn);
-PERL_CALLCONV void Perl_new_collate(pTHX_ const char* newcoll);
-PERL_CALLCONV void Perl_new_ctype(pTHX_ const char* newctype);
-PERL_CALLCONV void Perl_new_numeric(pTHX_ const char* newcoll);
+PERL_CALLCONV void Perl_new_collate(pTHX_ char* newcoll);
+PERL_CALLCONV void Perl_new_ctype(pTHX_ char* newctype);
+PERL_CALLCONV void Perl_new_numeric(pTHX_ char* newcoll);
PERL_CALLCONV void Perl_set_numeric_local(pTHX);
PERL_CALLCONV void Perl_set_numeric_radix(pTHX);
PERL_CALLCONV void Perl_set_numeric_standard(pTHX);
#endif
#if defined(PERL_IN_UTIL_C) || defined(PERL_DECL_PROT)
+STATIC char* S_stdize_locale(pTHX_ char* locs);
STATIC SV* S_mess_alloc(pTHX);
# if defined(LEAKTEST)
STATIC void S_xstat(pTHX_ int);
* Set up for a new ctype locale.
*/
void
-Perl_new_ctype(pTHX_ const char *newctype)
+Perl_new_ctype(pTHX_ char *newctype)
{
#ifdef USE_LOCALE_CTYPE
}
/*
+ * Standardize the locale name from a string returned by 'setlocale'.
+ *
+ * The standard return value of setlocale() is either
+ * (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 platforms it has a form like "LC_SOMETHING=Lang_Country.866\n",
+ * which is harmful for further use of the string in setlocale().
+ *
+ */
+STATIC char *
+S_stdize_locale(pTHX_ char *locs)
+{
+ char *s;
+ bool okay = TRUE;
+
+ if ((s = strchr(locs, '='))) {
+ char *t;
+
+ okay = FALSE;
+ if ((t = strchr(s, '.'))) {
+ char *u;
+
+ if ((u = strchr(t, '\n'))) {
+
+ if (u[1] == 0) {
+ STRLEN len = u - s;
+ Move(t + 1, locs, len, char);
+ locs[len] = 0;
+ okay = TRUE;
+ }
+ }
+ }
+ }
+
+ if (!okay)
+ Perl_croak(aTHX_ "Can't fix broken locale name \"%s\"", locs);
+
+ return locs;
+}
+
+/*
* Set up for a new collation locale.
*/
void
-Perl_new_collate(pTHX_ const char *newcoll)
+Perl_new_collate(pTHX_ char *newcoll)
{
#ifdef USE_LOCALE_COLLATE
++PL_collation_ix;
Safefree(PL_collation_name);
PL_collation_name = NULL;
- PL_collation_standard = TRUE;
- PL_collxfrm_base = 0;
- PL_collxfrm_mult = 2;
}
+ PL_collation_standard = TRUE;
+ PL_collxfrm_base = 0;
+ PL_collxfrm_mult = 2;
return;
}
if (! PL_collation_name || strNE(PL_collation_name, newcoll)) {
++PL_collation_ix;
Safefree(PL_collation_name);
- PL_collation_name = savepv(newcoll);
+ PL_collation_name = stdize_locale(savepv(newcoll));
PL_collation_standard = (strEQ(newcoll, "C") || strEQ(newcoll, "POSIX"));
{
* Set up for a new numeric locale.
*/
void
-Perl_new_numeric(pTHX_ const char *newnum)
+Perl_new_numeric(pTHX_ char *newnum)
{
#ifdef USE_LOCALE_NUMERIC
if (PL_numeric_name) {
Safefree(PL_numeric_name);
PL_numeric_name = NULL;
- PL_numeric_standard = TRUE;
- PL_numeric_local = TRUE;
}
+ PL_numeric_standard = TRUE;
+ PL_numeric_local = TRUE;
return;
}
if (! PL_numeric_name || strNE(PL_numeric_name, newnum)) {
Safefree(PL_numeric_name);
- PL_numeric_name = savepv(newnum);
+ PL_numeric_name = stdize_locale(savepv(newnum));
PL_numeric_standard = (strEQ(newnum, "C") || strEQ(newnum, "POSIX"));
PL_numeric_local = TRUE;
set_numeric_radix();
setlocale(LC_NUMERIC, "C");
PL_numeric_standard = TRUE;
PL_numeric_local = FALSE;
+ set_numeric_radix();
}
#endif /* USE_LOCALE_NUMERIC */