Fix Win32 makefiles as per f86864acbf97469fd9e5d5233d51ff743f4d8d6e
[p5sagit/p5-mst-13.2.git] / mg.c
diff --git a/mg.c b/mg.c
index 55d46d2..f7d3634 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -383,15 +383,18 @@ Perl_mg_clear(pTHX_ SV *sv)
 {
     const I32 mgs_ix = SSNEW(sizeof(MGS));
     MAGIC* mg;
+    MAGIC *nextmg;
 
     PERL_ARGS_ASSERT_MG_CLEAR;
 
     save_magic(mgs_ix, sv);
 
-    for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
+    for (mg = SvMAGIC(sv); mg; mg = nextmg) {
         const MGVTBL* const vtbl = mg->mg_virtual;
        /* omit GSKIP -- never set here */
 
+       nextmg = mg->mg_moremagic; /* it may delete itself */
+
        if (vtbl && vtbl->svt_clear)
            CALL_FPTR(vtbl->svt_clear)(aTHX_ sv, mg);
     }
@@ -974,6 +977,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        {
            sv_setiv(sv, (IV)STATUS_CURRENT);
 #ifdef COMPLEX_STATUS
+           SvUPGRADE(sv, SVt_PVLV);
            LvTARGOFF(sv) = PL_statusvalue;
            LvTARGLEN(sv) = PL_statusvalue_vms;
 #endif
@@ -1234,10 +1238,14 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg)
 {
     dVAR;
     /* Are we fetching a signal entry? */
-    const I32 i = whichsig(MgPV_nolen_const(mg));
+    int i = (I16)mg->mg_private;
 
     PERL_ARGS_ASSERT_MAGIC_GETSIG;
 
+    if (!i) {
+       mg->mg_private = i = whichsig(MgPV_nolen_const(mg));
+    }
+
     if (i > 0) {
        if(PL_psig_ptr[i])
            sv_setsv(sv,PL_psig_ptr[i]);
@@ -1308,13 +1316,14 @@ Perl_csighandler(int sig)
 #endif
           (PL_signals & PERL_SIGNALS_UNSAFE_FLAG))
        /* Call the perl level handler now--
-        * with risk we may be in malloc() etc. */
+        * with risk we may be in malloc() or being destructed etc. */
 #if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
        (*PL_sighandlerp)(sig, NULL, NULL);
 #else
        (*PL_sighandlerp)(sig);
 #endif
     else {
+       if (!PL_psig_pend) return;
        /* Set a flag to say this signal is pending, that is awaiting delivery after
         * the current Perl opcode completes */
        PL_psig_pend[sig]++;
@@ -1322,7 +1331,7 @@ Perl_csighandler(int sig)
 #ifndef SIG_PENDING_DIE_COUNT
 #  define SIG_PENDING_DIE_COUNT 120
 #endif
-       /* And one to say _a_ signal is pending */
+       /* Add one to say _a_ signal is pending */
        if (++PL_sig_pending >= SIG_PENDING_DIE_COUNT)
            Perl_croak(aTHX_ "Maximal count of pending signals (%lu) exceeded",
                       (unsigned long)SIG_PENDING_DIE_COUNT);
@@ -1413,10 +1422,14 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
        }
     }
     else {
-       i = whichsig(s);        /* ...no, a brick */
+       i = (I16)mg->mg_private;
+       if (!i) {
+           i = whichsig(s);    /* ...no, a brick */
+           mg->mg_private = (U16)i;
+       }
        if (i <= 0) {
-           if (sv && ckWARN(WARN_SIGNAL))
-               Perl_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", s);
+           if (sv)
+               Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", s);
            return 0;
        }
 #ifdef HAS_SIGPROCMASK
@@ -1439,14 +1452,23 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
 #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
        PL_sig_defaulting[i] = 0;
 #endif
-       SvREFCNT_dec(PL_psig_name[i]);
        to_dec = PL_psig_ptr[i];
        if (sv) {
            PL_psig_ptr[i] = SvREFCNT_inc_simple_NN(sv);
            SvTEMP_off(sv); /* Make sure it doesn't go away on us */
-           PL_psig_name[i] = newSVpvn(s, len);
-           SvREADONLY_on(PL_psig_name[i]);
+
+           /* Signals don't change name during the program's execution, so once
+              they're cached in the appropriate slot of PL_psig_name, they can
+              stay there.
+
+              Ideally we'd find some way of making SVs at (C) compile time, or
+              at least, doing most of the work.  */
+           if (!PL_psig_name[i]) {
+               PL_psig_name[i] = newSVpvn(s, len);
+               SvREADONLY_on(PL_psig_name[i]);
+           }
        } else {
+           SvREFCNT_dec(PL_psig_name[i]);
            PL_psig_name[i] = NULL;
            PL_psig_ptr[i] = NULL;
        }
@@ -1454,61 +1476,56 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg)
     if (sv && (isGV_with_GP(sv) || SvROK(sv))) {
        if (i) {
            (void)rsignal(i, PL_csighandlerp);
-#ifdef HAS_SIGPROCMASK
-           LEAVE;
-#endif
        }
        else
            *svp = SvREFCNT_inc_simple_NN(sv);
-       if(to_dec)
-           SvREFCNT_dec(to_dec);
-       return 0;
-    }
-    if (sv && SvOK(sv)) {
-       s = SvPV_force(sv, len);
     } else {
-       sv = NULL;
-    }
-    if (sv && strEQ(s,"IGNORE")) {
-       if (i) {
+       if (sv && SvOK(sv)) {
+           s = SvPV_force(sv, len);
+       } else {
+           sv = NULL;
+       }
+       if (sv && strEQ(s,"IGNORE")) {
+           if (i) {
 #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
-           PL_sig_ignoring[i] = 1;
-           (void)rsignal(i, PL_csighandlerp);
+               PL_sig_ignoring[i] = 1;
+               (void)rsignal(i, PL_csighandlerp);
 #else
-           (void)rsignal(i, (Sighandler_t) SIG_IGN);
+               (void)rsignal(i, (Sighandler_t) SIG_IGN);
 #endif
+           }
        }
-    }
-    else if (!sv || strEQ(s,"DEFAULT") || !len) {
-       if (i) {
+       else if (!sv || strEQ(s,"DEFAULT") || !len) {
+           if (i) {
 #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS
-           PL_sig_defaulting[i] = 1;
-           (void)rsignal(i, PL_csighandlerp);
+               PL_sig_defaulting[i] = 1;
+               (void)rsignal(i, PL_csighandlerp);
 #else
-           (void)rsignal(i, (Sighandler_t) SIG_DFL);
+               (void)rsignal(i, (Sighandler_t) SIG_DFL);
 #endif
+           }
+       }
+       else {
+           /*
+            * We should warn if HINT_STRICT_REFS, but without
+            * access to a known hint bit in a known OP, we can't
+            * tell whether HINT_STRICT_REFS is in force or not.
+            */
+           if (!strchr(s,':') && !strchr(s,'\''))
+               Perl_sv_insert_flags(aTHX_ sv, 0, 0, STR_WITH_LEN("main::"),
+                                    SV_GMAGIC);
+           if (i)
+               (void)rsignal(i, PL_csighandlerp);
+           else
+               *svp = SvREFCNT_inc_simple_NN(sv);
        }
     }
-    else {
-       /*
-        * We should warn if HINT_STRICT_REFS, but without
-        * access to a known hint bit in a known OP, we can't
-        * tell whether HINT_STRICT_REFS is in force or not.
-        */
-       if (!strchr(s,':') && !strchr(s,'\''))
-           Perl_sv_insert_flags(aTHX_ sv, 0, 0, STR_WITH_LEN("main::"),
-                                SV_GMAGIC);
-       if (i)
-           (void)rsignal(i, PL_csighandlerp);
-       else
-           *svp = SvREFCNT_inc_simple_NN(sv);
-    }
+
 #ifdef HAS_SIGPROCMASK
     if(i)
        LEAVE;
 #endif
-    if(to_dec)
-       SvREFCNT_dec(to_dec);
+    SvREFCNT_dec(to_dec);
     return 0;
 }
 #endif /* !PERL_MICRO */
@@ -1517,38 +1534,17 @@ int
 Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg)
 {
     dVAR;
-    HV* stash;
-
     PERL_ARGS_ASSERT_MAGIC_SETISA;
     PERL_UNUSED_ARG(sv);
 
-    /* Bail out if destruction is going on */
-    if(PL_dirty) return 0;
-
     /* Skip _isaelem because _isa will handle it shortly */
     if (PL_delaymagic & DM_ARRAY && mg->mg_type == PERL_MAGIC_isaelem)
        return 0;
 
-    /* XXX Once it's possible, we need to
-       detect that our @ISA is aliased in
-       other stashes, and act on the stashes
-       of all of the aliases */
-
-    /* The first case occurs via setisa,
-       the second via setisa_elem, which
-       calls this same magic */
-    stash = GvSTASH(
-        SvTYPE(mg->mg_obj) == SVt_PVGV
-            ? (const GV *)mg->mg_obj
-            : (const GV *)mg_find(mg->mg_obj, PERL_MAGIC_isa)->mg_obj
-    );
-
-    if (stash)
-       mro_isa_changed_in(stash);
-
-    return 0;
+    return magic_clearisa(NULL, mg);
 }
 
+/* sv of NULL signifies that we're acting as magic_setisa.  */
 int
 Perl_magic_clearisa(pTHX_ SV *sv, MAGIC *mg)
 {
@@ -1560,9 +1556,17 @@ Perl_magic_clearisa(pTHX_ SV *sv, MAGIC *mg)
     /* Bail out if destruction is going on */
     if(PL_dirty) return 0;
 
-    av_clear(MUTABLE_AV(sv));
+    if (sv)
+       av_clear(MUTABLE_AV(sv));
+
+    /* XXX Once it's possible, we need to
+       detect that our @ISA is aliased in
+       other stashes, and act on the stashes
+       of all of the aliases */
 
-    /* XXX see comments in magic_setisa */
+    /* The first case occurs via setisa,
+       the second via setisa_elem, which
+       calls this same magic */
     stash = GvSTASH(
         SvTYPE(mg->mg_obj) == SVt_PVGV
             ? (const GV *)mg->mg_obj
@@ -1875,9 +1879,8 @@ Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg)
     if (obj) {
        av_fill(obj, SvIV(sv) - CopARYBASE_get(PL_curcop));
     } else {
-       if (ckWARN(WARN_MISC))
-           Perl_warner(aTHX_ packWARN(WARN_MISC),
-                       "Attempt to set length of freed array");
+       Perl_ck_warner(aTHX_ packWARN(WARN_MISC),
+                      "Attempt to set length of freed array");
     }
     return 0;
 }
@@ -2329,7 +2332,8 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 #ifdef DEBUGGING
        s = SvPV_nolen_const(sv);
        PL_debug = get_debug_opts(&s, 0) | DEBUG_TOP_FLAG;
-       DEBUG_x(dump_all());
+       if (DEBUG_x_TEST || DEBUG_B_TEST)
+           dump_all_perl(!DEBUG_B_TEST);
 #else
        PL_debug = (SvIV(sv)) | DEBUG_TOP_FLAG;
 #endif
@@ -2352,8 +2356,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 #endif
        }
        else if (strEQ(mg->mg_ptr+1, "NCODING")) {
-           if (PL_encoding)
-               SvREFCNT_dec(PL_encoding);
+           SvREFCNT_dec(PL_encoding);
            if (SvOK(sv) || SvGMAGICAL(sv)) {
                PL_encoding = newSVsv(sv);
            }
@@ -2386,31 +2389,23 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
            const char *const start = SvPV(sv, len);
            const char *out = (const char*)memchr(start, '\0', len);
            SV *tmp;
-           struct refcounted_he *tmp_he;
 
 
            PL_compiling.cop_hints |= HINT_LEXICAL_IO_IN | HINT_LEXICAL_IO_OUT;
-           PL_hints
-               |= HINT_LOCALIZE_HH | HINT_LEXICAL_IO_IN | HINT_LEXICAL_IO_OUT;
+           PL_hints |= HINT_LEXICAL_IO_IN | HINT_LEXICAL_IO_OUT;
 
            /* Opening for input is more common than opening for output, so
               ensure that hints for input are sooner on linked list.  */
            tmp = out ? newSVpvn_flags(out + 1, start + len - out - 1,
-                                      SVs_TEMP | SvUTF8(sv))
-               : newSVpvs_flags("", SVs_TEMP | SvUTF8(sv));
-
-           tmp_he
-               = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, 
-                                        newSVpvs_flags("open>", SVs_TEMP),
-                                        tmp);
+                                      SvUTF8(sv))
+               : newSVpvs_flags("", SvUTF8(sv));
+           (void)hv_stores(GvHV(PL_hintgv), "open>", tmp);
+           mg_set(tmp);
 
-           /* The UTF-8 setting is carried over  */
-           sv_setpvn(tmp, start, out ? (STRLEN)(out - start) : len);
-
-           PL_compiling.cop_hints_hash
-               = Perl_refcounted_he_new(aTHX_ tmp_he,
-                                        newSVpvs_flags("open<", SVs_TEMP),
-                                        tmp);
+           tmp = newSVpvn_flags(start, out ? (STRLEN)(out - start) : len,
+                                       SvUTF8(sv));
+           (void)hv_stores(GvHV(PL_hintgv), "open<", tmp);
+           mg_set(tmp);
        }
        break;
     case '\020':       /* ^P */
@@ -2540,8 +2535,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        PL_rs = newSVsv(sv);
        break;
     case '\\':
-       if (PL_ors_sv)
-           SvREFCNT_dec(PL_ors_sv);
+       SvREFCNT_dec(PL_ors_sv);
        if (SvOK(sv) || SvGMAGICAL(sv)) {
            PL_ors_sv = newSVsv(sv);
        }
@@ -2555,6 +2549,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
     case '?':
 #ifdef COMPLEX_STATUS
        if (PL_localizing == 2) {
+           SvUPGRADE(sv, SVt_PVLV);
            PL_statusvalue = LvTARGOFF(sv);
            PL_statusvalue_vms = LvTARGLEN(sv);
        }
@@ -2669,11 +2664,19 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        {
            const char *p = SvPV_const(sv, len);
             Groups_t *gary = NULL;
+#ifdef _SC_NGROUPS_MAX
+           int maxgrp = sysconf(_SC_NGROUPS_MAX);
+
+           if (maxgrp < 0)
+               maxgrp = NGROUPS;
+#else
+           int maxgrp = NGROUPS;
+#endif
 
             while (isSPACE(*p))
                 ++p;
             PL_egid = Atol(p);
-            for (i = 0; i < NGROUPS; ++i) {
+            for (i = 0; i < maxgrp; ++i) {
                 while (*p && !isSPACE(*p))
                     ++p;
                 while (isSPACE(*p))
@@ -2864,12 +2867,11 @@ Perl_sighandler(int sig)
     }
 
     if (!cv || !CvROOT(cv)) {
-       if (ckWARN(WARN_SIGNAL))
-           Perl_warner(aTHX_ packWARN(WARN_SIGNAL), "SIG%s handler \"%s\" not defined.\n",
-               PL_sig_name[sig], (gv ? GvENAME(gv)
-                               : ((cv && CvGV(cv))
-                                  ? GvENAME(CvGV(cv))
-                                  : "__ANON__")));
+       Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL), "SIG%s handler \"%s\" not defined.\n",
+                      PL_sig_name[sig], (gv ? GvENAME(gv)
+                                         : ((cv && CvGV(cv))
+                                            ? GvENAME(CvGV(cv))
+                                            : "__ANON__")));
        goto cleanup;
     }
 
@@ -3090,6 +3092,26 @@ Perl_magic_clearhint(pTHX_ SV *sv, MAGIC *mg)
 }
 
 /*
+=for apidoc magic_clearhints
+
+Triggered by clearing %^H, resets C<PL_compiling.cop_hints_hash>.
+
+=cut
+*/
+int
+Perl_magic_clearhints(pTHX_ SV *sv, MAGIC *mg)
+{
+    PERL_ARGS_ASSERT_MAGIC_CLEARHINTS;
+    PERL_UNUSED_ARG(sv);
+    PERL_UNUSED_ARG(mg);
+    if (PL_compiling.cop_hints_hash) {
+       Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash);
+       PL_compiling.cop_hints_hash = NULL;
+    }
+    return 0;
+}
+
+/*
  * Local variables:
  * c-indentation-style: bsd
  * c-basic-offset: 4