Add missing syms to global.sym; update magic doc
[p5sagit/p5-mst-13.2.git] / pp_hot.c
index fb28bfe..f957deb 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -199,9 +199,9 @@ PP(pp_concat)
     }
     else if (SvGMAGICAL(TARG))
        mg_get(TARG);
-    else if (!SvOK(TARG)) {
-       s = SvPV_force(TARG, len);
+    else if (!SvOK(TARG) && SvTYPE(TARG) <= SVt_PVMG) {
        sv_setpv(TARG, "");     /* Suppress warning. */
+       s = SvPV_force(TARG, len);
     }
     s = SvPV(right,len);
     sv_catpvn(TARG,s,len);
@@ -269,7 +269,7 @@ PP(pp_add)
 {
     dSP; dATARGET; tryAMAGICbin(add,opASSIGN); 
     {
-      dPOPTOPnnrl;
+      dPOPTOPnnrl_ul;
       SETn( left + right );
       RETURN;
     }
@@ -725,8 +725,9 @@ PP(pp_aassign)
            SP = lastrelem;
        else
            SP = firstrelem + (lastlelem - firstlelem);
+       lelem = firstlelem + (relem - firstrelem);
        while (relem <= SP)
-           *relem++ = &sv_undef;
+           *relem++ = (lelem <= lastlelem) ? *lelem++ : &sv_undef;
        RETURN;
     }
     else {
@@ -894,8 +895,6 @@ play_it_again:
                else
                    mg->mg_flags &= ~MGf_MINMATCH;
            }
-           else
-               mg->mg_len = -1;
        }
        LEAVE_SCOPE(oldsave);
        RETPUSHYES;
@@ -932,13 +931,6 @@ nope:
        ++BmUSEFUL(pm->op_pmshort);
 
 ret_no:
-    if (global) {
-       if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) {
-           MAGIC* mg = mg_find(TARG, 'g');
-           if (mg)
-               mg->mg_len = -1;
-       }
-    }
     LEAVE_SCOPE(oldsave);
     if (gimme == G_ARRAY)
        RETURN;
@@ -1157,6 +1149,7 @@ do_readline()
            SvTAINTED_on(sv);
        }
        IoLINES(io)++;
+       SvSETMAGIC(sv);
        XPUSHs(sv);
        if (type == OP_GLOB) {
            char *tmps;
@@ -1314,12 +1307,12 @@ PP(pp_iter)
     cx = &cxstack[cxstack_ix];
     if (cx->cx_type != CXt_LOOP)
        DIE("panic: pp_iter");
+
     av = cx->blk_loop.iterary;
-    if (av == curstack && cx->blk_loop.iterix >= cx->blk_oldsp)
+    if (cx->blk_loop.iterix >= (av == curstack ? cx->blk_oldsp : AvFILL(av)))
        RETPUSHNO;
 
-    if (cx->blk_loop.iterix >= AvFILL(av))
-       RETPUSHNO;
+    SvREFCNT_dec(*cx->blk_loop.itervar);
 
     if (sv = AvARRAY(av)[++cx->blk_loop.iterix])
        SvTEMP_off(sv);
@@ -1327,6 +1320,10 @@ PP(pp_iter)
        sv = &sv_undef;
     if (av != curstack && SvIMMORTAL(sv)) {
        SV *lv = cx->blk_loop.iterlval;
+       if (lv && SvREFCNT(lv) > 1) {
+           SvREFCNT_dec(lv);
+           lv = Nullsv;
+       }
        if (lv)
            SvREFCNT_dec(LvTARG(lv));
        else {
@@ -1340,7 +1337,8 @@ PP(pp_iter)
        LvTARGLEN(lv) = 1;
        sv = (SV*)lv;
     }
-    *cx->blk_loop.itervar = sv;
+
+    *cx->blk_loop.itervar = SvREFCNT_inc(sv);
     RETPUSHYES;
 }
 
@@ -1360,6 +1358,7 @@ PP(pp_subst)
     I32 maxiters;
     register I32 i;
     bool once;
+    bool rxtainted;
     char *orig;
     I32 safebase;
     register REGEXP *rx = pm->op_pmregexp;
@@ -1427,116 +1426,105 @@ PP(pp_subst)
            pm->op_pmshort = Nullsv;    /* opt is being useless */
        }
     }
+
+    /* only replace once? */
     once = !(rpm->op_pmflags & PMf_GLOBAL);
-    if (rpm->op_pmflags & PMf_CONST) { /* known replacement string? */
-       c = SvPV(dstr, clen);
-       if (clen <= rx->minlen) {
-                                       /* can do inplace substitution */
-           if (pregexec(rx, s, strend, orig, 0,
-             SvSCREAM(TARG) ? TARG : Nullsv, safebase)) {
-               if (force_on_match) {
-                   force_on_match = 0;
-                   s = SvPV_force(TARG, len);
-                   goto force_it;
+
+    /* known replacement string? */
+    c = (rpm->op_pmflags & PMf_CONST) ? SvPV(dstr, clen) : Nullch;
+
+    /* can do inplace substitution? */
+    if (c && clen <= rx->minlen) {
+       if (! pregexec(rx, s, strend, orig, 0,
+                      SvSCREAM(TARG) ? TARG : Nullsv, safebase)) {
+           PUSHs(&sv_no);
+           LEAVE_SCOPE(oldsave);
+           RETURN;
+       }
+       if (force_on_match) {
+           force_on_match = 0;
+           s = SvPV_force(TARG, len);
+           goto force_it;
+       }
+       if (rx->subbase)        /* oops, no we can't */
+           goto long_way;
+       d = s;
+       curpm = pm;
+       SvSCREAM_off(TARG);     /* disable possible screamer */
+       if (once) {
+           rxtainted = rx->exec_tainted;
+           m = rx->startp[0];
+           d = rx->endp[0];
+           s = orig;
+           if (m - s > strend - d) {  /* faster to shorten from end */
+               if (clen) {
+                   Copy(c, m, clen, char);
+                   m += clen;
                }
-               if (rx->subbase)        /* oops, no we can't */
-                   goto long_way;
-               d = s;
-               curpm = pm;
-               SvSCREAM_off(TARG);     /* disable possible screamer */
-               if (once) {
-                   m = rx->startp[0];
-                   d = rx->endp[0];
-                   s = orig;
-                   if (m - s > strend - d) {   /* faster to shorten from end */
-                       if (clen) {
-                           Copy(c, m, clen, char);
-                           m += clen;
-                       }
-                       i = strend - d;
-                       if (i > 0) {
-                           Move(d, m, i, char);
-                           m += i;
-                       }
-                       *m = '\0';
-                       SvCUR_set(TARG, m - s);
-                       (void)SvPOK_only(TARG);
-                       SvSETMAGIC(TARG);
-                       PUSHs(&sv_yes);
-                       LEAVE_SCOPE(oldsave);
-                       RETURN;
-                   }
-                   /*SUPPRESS 560*/
-                   else if (i = m - s) {       /* faster from front */
-                       d -= clen;
-                       m = d;
-                       sv_chop(TARG, d-i);
-                       s += i;
-                       while (i--)
-                           *--d = *--s;
-                       if (clen)
-                           Copy(c, m, clen, char);
-                       (void)SvPOK_only(TARG);
-                       SvSETMAGIC(TARG);
-                       PUSHs(&sv_yes);
-                       LEAVE_SCOPE(oldsave);
-                       RETURN;
-                   }
-                   else if (clen) {
-                       d -= clen;
-                       sv_chop(TARG, d);
-                       Copy(c, d, clen, char);
-                       (void)SvPOK_only(TARG);
-                       SvSETMAGIC(TARG);
-                       PUSHs(&sv_yes);
-                       LEAVE_SCOPE(oldsave);
-                       RETURN;
-                   }
-                   else {
-                       sv_chop(TARG, d);
-                       (void)SvPOK_only(TARG);
-                       SvSETMAGIC(TARG);
-                       PUSHs(&sv_yes);
-                       LEAVE_SCOPE(oldsave);
-                       RETURN;
-                   }
-                   /* NOTREACHED */
+               i = strend - d;
+               if (i > 0) {
+                   Move(d, m, i, char);
+                   m += i;
                }
-               do {
-                   if (iters++ > maxiters)
-                       DIE("Substitution loop");
-                   m = rx->startp[0];
-                   /*SUPPRESS 560*/
-                   if (i = m - s) {
-                       if (s != d)
-                           Move(s, d, i, char);
-                       d += i;
-                   }
-                   if (clen) {
-                       Copy(c, d, clen, char);
-                       d += clen;
-                   }
-                   s = rx->endp[0];
-               } while (pregexec(rx, s, strend, orig, s == m,
-                   Nullsv, TRUE));     /* (don't match same null twice) */
-               if (s != d) {
-                   i = strend - s;
-                   SvCUR_set(TARG, d - SvPVX(TARG) + i);
-                   Move(s, d, i+1, char);              /* include the Null */
+               *m = '\0';
+               SvCUR_set(TARG, m - s);
+           }
+           /*SUPPRESS 560*/
+           else if (i = m - s) {       /* faster from front */
+               d -= clen;
+               m = d;
+               sv_chop(TARG, d-i);
+               s += i;
+               while (i--)
+                   *--d = *--s;
+               if (clen)
+                   Copy(c, m, clen, char);
+           }
+           else if (clen) {
+               d -= clen;
+               sv_chop(TARG, d);
+               Copy(c, d, clen, char);
+           }
+           else {
+               sv_chop(TARG, d);
+           }
+           PUSHs(&sv_yes);
+       }
+       else {
+           rxtainted = 0;
+           do {
+               if (iters++ > maxiters)
+                   DIE("Substitution loop");
+               rxtainted |= rx->exec_tainted;
+               m = rx->startp[0];
+               /*SUPPRESS 560*/
+               if (i = m - s) {
+                   if (s != d)
+                       Move(s, d, i, char);
+                   d += i;
                }
-               (void)SvPOK_only(TARG);
-               SvSETMAGIC(TARG);
-               PUSHs(sv_2mortal(newSViv((I32)iters)));
-               LEAVE_SCOPE(oldsave);
-               RETURN;
+               if (clen) {
+                   Copy(c, d, clen, char);
+                   d += clen;
+               }
+               s = rx->endp[0];
+           } while (pregexec(rx, s, strend, orig, s == m,
+                             Nullsv, TRUE)); /* don't match same null twice */
+           if (s != d) {
+               i = strend - s;
+               SvCUR_set(TARG, d - SvPVX(TARG) + i);
+               Move(s, d, i+1, char);          /* include the NUL */
            }
-           PUSHs(&sv_no);
-           LEAVE_SCOPE(oldsave);
-           RETURN;
+           PUSHs(sv_2mortal(newSViv((I32)iters)));
        }
+       (void)SvPOK_only(TARG);
+       SvSETMAGIC(TARG);
+       if (rxtainted)
+           SvTAINTED_on(TARG);
+       LEAVE_SCOPE(oldsave);
+       RETURN;
     }
-    else
-       c = Nullch;
+
     if (pregexec(rx, s, strend, orig, 0,
                 SvSCREAM(TARG) ? TARG : Nullsv, safebase)) {
     long_way:
@@ -1545,6 +1533,7 @@ PP(pp_subst)
            s = SvPV_force(TARG, len);
            goto force_it;
        }
+       rxtainted = rx->exec_tainted;
        dstr = NEWSV(25, sv_len(TARG));
        sv_setpvn(dstr, m, s-m);
        curpm = pm;
@@ -1556,6 +1545,7 @@ PP(pp_subst)
        do {
            if (iters++ > maxiters)
                DIE("Substitution loop");
+           rxtainted |= rx->exec_tainted;
            if (rx->subbase && rx->subbase != orig) {
                m = s;
                s = orig;
@@ -1583,6 +1573,8 @@ PP(pp_subst)
 
        (void)SvPOK_only(TARG);
        SvSETMAGIC(TARG);
+       if (rxtainted)
+           SvTAINTED_on(TARG);
        PUSHs(sv_2mortal(newSViv((I32)iters)));
        LEAVE_SCOPE(oldsave);
        RETURN;
@@ -1691,7 +1683,8 @@ PP(pp_entersub)
     register CV *cv;
     register CONTEXT *cx;
     I32 gimme;
-    I32 hasargs = (op->op_flags & OPf_STACKED) != 0;
+    bool hasargs = (op->op_flags & OPf_STACKED) != 0;
+    bool may_clone = TRUE;
 
     if (!sv)
        DIE("Not a CODE reference");
@@ -1711,14 +1704,17 @@ PP(pp_entersub)
            break;
        }
        cv = (CV*)SvRV(sv);
-       if (SvTYPE(cv) == SVt_PVCV)
+       if (SvTYPE(cv) == SVt_PVCV) {
+           may_clone = FALSE;
            break;
+       }
        /* FALL THROUGH */
     case SVt_PVHV:
     case SVt_PVAV:
        DIE("Not a CODE reference");
     case SVt_PVCV:
        cv = (CV*)sv;
+       may_clone = FALSE;
        break;
     case SVt_PVGV:
        if (!(cv = GvCV((GV*)sv)))
@@ -1729,6 +1725,9 @@ PP(pp_entersub)
     ENTER;
     SAVETMPS;
 
+    if (may_clone && cv && CvCLONE(cv))
+       cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
+
   retry:
     if (!cv)
        DIE("Not a CODE reference");
@@ -1762,12 +1761,16 @@ PP(pp_entersub)
 
     gimme = GIMME;
     if ((op->op_private & OPpENTERSUB_DB)) {
+       SV *oldsv = sv;
        sv = GvSV(DBsub);
        save_item(sv);
        gv = CvGV(cv);
-       if ( CvFLAGS(cv) & (CVf_ANON | CVf_CLONED)
-            || strEQ(GvNAME(gv), "END") ) {
-           /* GV is potentially non-unique */
+       if ( (CvFLAGS(cv) & (CVf_ANON | CVf_CLONED))
+            || strEQ(GvNAME(gv), "END") 
+            || ((GvCV(gv) != cv) && /* Could be imported, and old sub redefined. */
+                !( (SvTYPE(oldsv) == SVt_PVGV) && (GvCV((GV*)oldsv) == cv)
+                   && (gv = (GV*)oldsv) ))) { /* Use GV from the stack as a fallback. */
+           /* GV is potentially non-unique, or contain different CV. */
            sv_setsv(sv, newRV((SV*)cv));
        }
        else {
@@ -1903,7 +1906,7 @@ PP(pp_entersub)
            }
            cx->blk_sub.savearray = GvAV(defgv);
            cx->blk_sub.argarray = av;
-           GvAV(defgv) = cx->blk_sub.argarray;
+           GvAV(defgv) = (AV*)SvREFCNT_inc(av);
            ++MARK;
 
            if (items > AvMAX(av) + 1) {