This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Finalize perldelta
[perl5.git] / locale.c
index 429fdb7..a1fe449 100644 (file)
--- a/locale.c
+++ b/locale.c
@@ -272,6 +272,13 @@ Perl_new_ctype(pTHX_ const char *newctype)
 
     PERL_ARGS_ASSERT_NEW_CTYPE;
 
+    /* We will replace any bad locale warning with 1) nothing if the new one is
+     * ok; or 2) a new warning for the bad new locale */
+    if (PL_warn_locale) {
+        SvREFCNT_dec_NN(PL_warn_locale);
+        PL_warn_locale = NULL;
+    }
+
     PL_in_utf8_CTYPE_locale = _is_cur_LC_category_utf8(LC_CTYPE);
 
     /* A UTF-8 locale gets standard rules.  But note that code still has to
@@ -360,17 +367,9 @@ Perl_new_ctype(pTHX_ const char *newctype)
 #endif
 
         if (bad_count || multi_byte_locale) {
-
-            /* We have to save 'newctype' because the setlocale() just below
-             * may destroy it.  The next setlocale() further down should
-             * restore it properly so that the intermediate change here is
-             * transparent to this function's caller */
-            const char * const badlocale = savepv(newctype);
-
-            setlocale(LC_CTYPE, "C");
-            Perl_warner(aTHX_ packWARN(WARN_LOCALE),
+            PL_warn_locale = Perl_newSVpvf(aTHX_
                              "Locale '%s' may not work well.%s%s%s\n",
-                             badlocale,
+                             newctype,
                              (multi_byte_locale)
                               ? "  Some characters in it are not recognized by"
                                 " Perl."
@@ -384,7 +383,27 @@ Perl_new_ctype(pTHX_ const char *newctype)
                               ? bad_chars_list
                               : ""
                             );
-            setlocale(LC_CTYPE, badlocale);
+            /* If we are actually in the scope of the locale, output the
+             * message now.  Otherwise we save it to be output at the first
+             * operation using this locale, if that actually happens.  Most
+             * programs don't use locales, so they are immune to bad ones */
+            if (IN_LC(LC_CTYPE)) {
+
+                /* We have to save 'newctype' because the setlocale() just
+                 * below may destroy it.  The next setlocale() further down
+                 * should restore it properly so that the intermediate change
+                 * here is transparent to this function's caller */
+                const char * const badlocale = savepv(newctype);
+
+                setlocale(LC_CTYPE, "C");
+
+                /* The '0' below suppresses a bogus gcc compiler warning */
+                Perl_warner(aTHX_ packWARN(WARN_LOCALE), SvPVX(PL_warn_locale), 0);
+                setlocale(LC_CTYPE, badlocale);
+                Safefree(badlocale);
+                SvREFCNT_dec_NN(PL_warn_locale);
+                PL_warn_locale = NULL;
+            }
         }
     }
 
@@ -395,6 +414,32 @@ Perl_new_ctype(pTHX_ const char *newctype)
 }
 
 void
+Perl__warn_problematic_locale()
+{
+
+#ifdef USE_LOCALE_CTYPE
+
+    dTHX;
+
+    /* Internal-to-core function that outputs the message in PL_warn_locale,
+     * and then NULLS it.  Should be called only through the macro
+     * _CHECK_AND_WARN_PROBLEMATIC_LOCALE */
+
+    if (PL_warn_locale) {
+        /*GCC_DIAG_IGNORE(-Wformat-security);   Didn't work */
+        Perl_ck_warner(aTHX_ packWARN(WARN_LOCALE),
+                             SvPVX(PL_warn_locale),
+                             0 /* dummy to avoid compiler warning */ );
+        /* GCC_DIAG_RESTORE; */
+        SvREFCNT_dec_NN(PL_warn_locale);
+        PL_warn_locale = NULL;
+    }
+
+#endif
+
+}
+
+void
 Perl_new_collate(pTHX_ const char *newcoll)
 {
 #ifdef USE_LOCALE_COLLATE
@@ -463,7 +508,7 @@ Perl_my_setlocale(pTHX_ int category, const char* locale)
      * otherwise to use the particular category's variable if set; otherwise to
      * use the LANG variable. */
 
-    bool override_LC_ALL = 0;
+    bool override_LC_ALL = FALSE;
     char * result;
 
     if (locale && strEQ(locale, "")) {
@@ -529,7 +574,7 @@ Perl_my_setlocale(pTHX_ int category, const char* locale)
         return result;
     }
 
-    /* Here the input locale was LC_ALL, and we have set it to what is in the
+    /* Here the input category was LC_ALL, and we have set it to what is in the
      * LANG variable or the system default if there is no LANG.  But these have
      * lower priority than the other LC_foo variables, so override it for each
      * one that is set.  (If they are set to "", it means to use the same thing
@@ -609,7 +654,7 @@ Perl_init_i18nl10n(pTHX_ int printwarn)
     char *curnum     = NULL;
 #endif /* USE_LOCALE_NUMERIC */
 #ifdef __GLIBC__
-    char * const language   = PerlEnv_getenv("LANGUAGE");
+    const char * const language   = savepv(PerlEnv_getenv("LANGUAGE"));
 #endif
 
     /* NULL uses the existing already set up locale */
@@ -618,15 +663,22 @@ Perl_init_i18nl10n(pTHX_ int printwarn)
                                         : "";
     const char* trial_locales[5];   /* 5 = 1 each for "", LC_ALL, LANG, "", C */
     unsigned int trial_locales_count;
-    char * const lc_all     = PerlEnv_getenv("LC_ALL");
-    char * const lang       = PerlEnv_getenv("LANG");
+    const char * const lc_all     = savepv(PerlEnv_getenv("LC_ALL"));
+    const char * const lang       = savepv(PerlEnv_getenv("LANG"));
     bool setlocale_failure = FALSE;
     unsigned int i;
     char *p;
-    const bool locwarn = (printwarn > 1 ||
-                    (printwarn &&
-                     (!(p = PerlEnv_getenv("PERL_BADLANG")) ||
-                      grok_atou(p, NULL))));
+
+    /* A later getenv() could zap this, so only use here */
+    const char * const bad_lang_use_once = PerlEnv_getenv("PERL_BADLANG");
+
+    const bool locwarn = (printwarn > 1
+                          || (printwarn
+                              && (! bad_lang_use_once
+                                  || (
+                                    /* disallow with "" or "0" */
+                                    *bad_lang_use_once
+                                    && strNE("0", bad_lang_use_once)))));
     bool done = FALSE;
 #ifdef WIN32
     /* In some systems you can find out the system default locale
@@ -876,7 +928,7 @@ Perl_init_i18nl10n(pTHX_ int printwarn)
             }
 
             /* Calculate what fallback locales to try.  We have avoided this
-             * until we have to, becuase failure is quite unlikely.  This will
+             * until we have to, because failure is quite unlikely.  This will
              * usually change the upper bound of the loop we are in.
              *
              * Since the system's default way of setting the locale has not
@@ -1031,6 +1083,13 @@ Perl_init_i18nl10n(pTHX_ int printwarn)
     Safefree(curnum);
 #endif /* USE_LOCALE_NUMERIC */
 
+#ifdef __GLIBC__
+    Safefree(language);
+#endif
+
+    Safefree(lc_all);
+    Safefree(lang);
+
 #else  /* !USE_LOCALE */
     PERL_UNUSED_ARG(printwarn);
 #endif /* USE_LOCALE */