Mention and discourage use of term 'soft reference'
[p5sagit/p5-mst-13.2.git] / pp_hot.c
index b9e3b87..7f9f513 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1,6 +1,6 @@
 /*    pp_hot.c
  *
- *    Copyright (c) 1991-1994, Larry Wall
+ *    Copyright (c) 1991-1997, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -204,7 +204,10 @@ PP(pp_concat)
        s = SvPV_force(TARG, len);
     }
     s = SvPV(right,len);
-    sv_catpvn(TARG,s,len);
+    if (SvOK(TARG))
+       sv_catpvn(TARG,s,len);
+    else
+       sv_setpvn(TARG,s,len);  /* suppress warning */
     SETTARG;
     RETURN;
   }
@@ -218,7 +221,7 @@ PP(pp_padsv)
        if (op->op_private & OPpLVAL_INTRO)
            SAVECLEARSV(curpad[op->op_targ]);
         else if (op->op_private & OPpDEREF)
-           provide_ref(op, curpad[op->op_targ]);
+           vivify_ref(curpad[op->op_targ], op->op_flags & OPpDEREF);
     }
     RETURN;
 }
@@ -242,6 +245,8 @@ PP(pp_eq)
 PP(pp_preinc)
 {
     dSP;
+    if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
+       croak(no_modify);
     if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) &&
        SvIVX(TOPs) != IV_MAX)
     {
@@ -297,7 +302,19 @@ PP(pp_join)
 PP(pp_pushre)
 {
     dSP;
+#ifdef DEBUGGING
+    /*
+     * We ass_u_me that LvTARGOFF() comes first, and that two STRLENs
+     * will be enough to hold an OP*.
+     */
+    SV* sv = sv_newmortal();
+    sv_upgrade(sv, SVt_PVLV);
+    LvTYPE(sv) = '/';
+    Copy(&op, &LvTARGOFF(sv), 1, OP*);
+    XPUSHs(sv);
+#else
     XPUSHs((SV*)op);
+#endif
     RETURN;
 }
 
@@ -316,17 +333,22 @@ PP(pp_print)
     else
        gv = defoutgv;
     if (SvMAGICAL(gv) && (mg = mg_find((SV*)gv, 'q'))) {
-       SV *sv;
-
-       PUSHMARK(MARK-1);
+       if (MARK == ORIGMARK) {
+           EXTEND(SP, 1);
+           ++MARK;
+           Move(MARK, MARK + 1, (SP - MARK) + 1, SV*);
+           ++SP;
+       }
+       PUSHMARK(MARK - 1);
        *MARK = mg->mg_obj;
+       PUTBACK;
        ENTER;
        perl_call_method("PRINT", G_SCALAR);
        LEAVE;
        SPAGAIN;
-       sv = POPs;
-       SP = ORIGMARK;
-       PUSHs(sv);
+       MARK = ORIGMARK + 1;
+       *MARK = *SP;
+       SP = MARK;
        RETURN;
     }
     if (!(io = GvIO(gv))) {
@@ -398,7 +420,6 @@ PP(pp_print)
 PP(pp_rv2av)
 {
     dSP; dPOPss;
-
     AV *av;
 
     if (SvROK(sv)) {
@@ -436,6 +457,8 @@ PP(pp_rv2av)
                    if (op->op_flags & OPf_REF ||
                      op->op_private & HINT_STRICT_REFS)
                        DIE(no_usym, "an ARRAY");
+                   if (dowarn)
+                       warn(warn_uninit);
                    if (GIMME == G_ARRAY)
                        RETURN;
                    RETPUSHUNDEF;
@@ -473,9 +496,7 @@ PP(pp_rv2av)
 
 PP(pp_rv2hv)
 {
-
     dSP; dTOPss;
-
     HV *hv;
 
     if (SvROK(sv)) {
@@ -513,6 +534,8 @@ PP(pp_rv2hv)
                    if (op->op_flags & OPf_REF ||
                      op->op_private & HINT_STRICT_REFS)
                        DIE(no_usym, "a HASH");
+                   if (dowarn)
+                       warn(warn_uninit);
                    if (GIMME == G_ARRAY) {
                        SP--;
                        RETURN;
@@ -543,7 +566,7 @@ PP(pp_rv2hv)
     else {
        dTARGET;
        if (HvFILL(hv)) {
-           sprintf(buf, "%d/%d", HvFILL(hv), HvMAX(hv)+1);
+           sprintf(buf, "%ld/%ld", (long)HvFILL(hv), (long)HvMAX(hv)+1);
            sv_setpv(TARG, buf);
        }
        else
@@ -598,6 +621,7 @@ PP(pp_aassign)
            magic = SvMAGICAL(ary) != 0;
            
            av_clear(ary);
+           av_extend(ary, lastrelem - relem);
            i = 0;
            while (relem <= lastrelem) {        /* gobble up all the rest */
                sv = NEWSV(28,0);
@@ -754,6 +778,7 @@ PP(pp_match)
     STRLEN len;
     I32 minmatch = 0;
     I32 oldsave = savestack_ix;
+    I32 update_minmatch = 1;
 
     if (op->op_flags & OPf_STACKED)
        TARG = POPs;
@@ -765,6 +790,7 @@ PP(pp_match)
     strend = s + len;
     if (!s)
        DIE("panic: do_match");
+    TAINT_NOT;
 
     if (pm->op_pmflags & PMf_USED) {
        if (gimme == G_ARRAY)
@@ -784,6 +810,7 @@ PP(pp_match)
            if (mg && mg->mg_len >= 0) {
                rx->endp[0] = rx->startp[0] = s + mg->mg_len; 
                minmatch = (mg->mg_flags & MGf_MINMATCH);
+               update_minmatch = 0;
            }
        }
     }
@@ -800,7 +827,8 @@ play_it_again:
        t = s = rx->endp[0];
        if (s >= strend)
            goto nope;
-       minmatch = (s == rx->startp[0]);
+       if (update_minmatch++)
+           minmatch = (s == rx->startp[0]);
     }
     if (pm->op_pmshort) {
        if (pm->op_pmflags & PMf_SCANFIRST) {
@@ -850,10 +878,10 @@ play_it_again:
     /*NOTREACHED*/
 
   gotcha:
+    TAINT_IF(rx->exec_tainted);
     if (gimme == G_ARRAY) {
        I32 iters, i, len;
 
-       TAINT_IF(rx->exec_tainted);
        iters = rx->nparens;
        if (global && !iters)
            i = 1;
@@ -901,6 +929,7 @@ play_it_again:
     }
 
 yup:
+    TAINT_IF(rx->exec_tainted);
     ++BmUSEFUL(pm->op_pmshort);
     curpm = pm;
     if (pm->op_pmflags & PMf_ONCE)
@@ -1037,7 +1066,7 @@ do_readline()
                            *(end++) = '\n';  *end = '\0';
                            for (cp = rstr; *cp; cp++) *cp = _tolower(*cp);
                            if (hasdir) {
-                             if (isunix) trim_unixpath(rstr,SvPVX(tmpglob));
+                             if (isunix) trim_unixpath(rstr,SvPVX(tmpglob),1);
                              begin = rstr;
                            }
                            else {
@@ -1061,6 +1090,7 @@ do_readline()
                           PerlIO_rewind(tmpfp);
                           IoTYPE(io) = '<';
                           IoIFP(io) = fp = tmpfp;
+                          IoFLAGS(io) &= ~IOf_UNTAINT;  /* maybe redundant */
                        }
                    }
                }
@@ -1116,6 +1146,8 @@ do_readline()
     }
     else {
        sv = TARG;
+       if (SvROK(sv))
+           sv_unref(sv);
        (void)SvUPGRADE(sv, SVt_PV);
        tmplen = SvLEN(sv);     /* remember if already alloced */
        if (!tmplen)
@@ -1223,14 +1255,28 @@ PP(pp_helem)
     HE* he;
     SV *keysv = POPs;
     HV *hv = (HV*)POPs;
-    I32 lval = op->op_flags & OPf_MOD;
+    U32 lval = op->op_flags & OPf_MOD;
+    U32 defer = op->op_private & OPpLVAL_DEFER;
 
     if (SvTYPE(hv) != SVt_PVHV)
        RETPUSHUNDEF;
-    he = hv_fetch_ent(hv, keysv, lval, 0);
+    he = hv_fetch_ent(hv, keysv, lval && !defer, 0);
     if (lval) {
-       if (!he || HeVAL(he) == &sv_undef)
-           DIE(no_helem, SvPV(keysv, na));
+       if (!he || HeVAL(he) == &sv_undef) {
+           SV* lv;
+           SV* key2;
+           if (!defer)
+               DIE(no_helem, SvPV(keysv, na));
+           lv = sv_newmortal();
+           sv_upgrade(lv, SVt_PVLV);
+           LvTYPE(lv) = 'y';
+           sv_magic(lv, key2 = newSVsv(keysv), 'y', Nullch, 0);
+           SvREFCNT_dec(key2); /* sv_magic() increments refcount */
+           LvTARG(lv) = SvREFCNT_inc(hv);
+           LvTARGLEN(lv) = 1;
+           PUSHs(lv);
+           RETURN;
+       }
        if (op->op_private & OPpLVAL_INTRO) {
            if (HvNAME(hv) && isGV(HeVAL(he)))
                save_gp((GV*)HeVAL(he), !(op->op_flags & OPf_SPECIAL));
@@ -1238,7 +1284,7 @@ PP(pp_helem)
                save_svref(&HeVAL(he));
        }
        else if (op->op_private & OPpDEREF)
-           provide_ref(op, HeVAL(he));
+           vivify_ref(HeVAL(he), op->op_private & OPpDEREF);
     }
     PUSHs(he ? HeVAL(he) : &sv_undef);
     RETURN;
@@ -1328,14 +1374,14 @@ PP(pp_iter)
        if (lv)
            SvREFCNT_dec(LvTARG(lv));
        else {
-           lv = cx->blk_loop.iterlval = newSVsv(sv);
+           lv = cx->blk_loop.iterlval = NEWSV(26, 0);
            sv_upgrade(lv, SVt_PVLV);
-           sv_magic(lv, Nullsv, 'y', Nullch, 0);
            LvTYPE(lv) = 'y';
+           sv_magic(lv, Nullsv, 'y', Nullch, 0);
        }
        LvTARG(lv) = SvREFCNT_inc(av);
        LvTARGOFF(lv) = cx->blk_loop.iterix;
-       LvTARGLEN(lv) = 1;
+       LvTARGLEN(lv) = -1;
        sv = (SV*)lv;
     }
 
@@ -1375,9 +1421,14 @@ PP(pp_subst)
        TARG = GvSV(defgv);
        EXTEND(SP,1);
     }
+    if (SvREADONLY(TARG)
+       || (SvTYPE(TARG) > SVt_PVLV
+           && !(SvTYPE(TARG) == SVt_PVGV && SvFAKE(TARG))))
+       croak(no_modify);
     s = SvPV(TARG, len);
-    if (!SvPOKp(TARG) || SvREADONLY(TARG) || (SvTYPE(TARG) == SVt_PVGV))
+    if (!SvPOKp(TARG) || SvTYPE(TARG) == SVt_PVGV)
        force_on_match = 1;
+    TAINT_NOT;
 
   force_it:
     if (!pm || !s)
@@ -1489,6 +1540,7 @@ PP(pp_subst)
            else {
                sv_chop(TARG, d);
            }
+           TAINT_IF(rxtainted);
            PUSHs(&sv_yes);
        }
        else {
@@ -1516,12 +1568,12 @@ PP(pp_subst)
                SvCUR_set(TARG, d - SvPVX(TARG) + i);
                Move(s, d, i+1, char);          /* include the NUL */
            }
+           TAINT_IF(rxtainted);
            PUSHs(sv_2mortal(newSViv((I32)iters)));
        }
        (void)SvPOK_only(TARG);
        SvSETMAGIC(TARG);
-       if (rxtainted)
-           SvTAINTED_on(TARG);
+       SvTAINT(TARG);
        LEAVE_SCOPE(oldsave);
        RETURN;
     }
@@ -1564,6 +1616,8 @@ PP(pp_subst)
        } while (pregexec(rx, s, strend, orig, s == m, Nullsv, safebase));
        sv_catpvn(dstr, s, strend - s);
 
+       TAINT_IF(rxtainted);
+
        (void)SvOOK_off(TARG);
        Safefree(SvPVX(TARG));
        SvPVX(TARG) = SvPVX(dstr);
@@ -1574,12 +1628,12 @@ PP(pp_subst)
 
        (void)SvPOK_only(TARG);
        SvSETMAGIC(TARG);
-       if (rxtainted)
-           SvTAINTED_on(TARG);
+       SvTAINT(TARG);
        PUSHs(sv_2mortal(newSViv((I32)iters)));
        LEAVE_SCOPE(oldsave);
        RETURN;
     }
+
     PUSHs(&sv_no);
     LEAVE_SCOPE(oldsave);
     RETURN;
@@ -1639,40 +1693,33 @@ PP(pp_leavesub)
     PMOP *newpm;
     I32 gimme;
     register CONTEXT *cx;
+    struct block_sub cxsub;
 
     POPBLOCK(cx,newpm);
-    POPSUB(cx);
-
+    POPSUB1(cx);       /* Delay POPSUB2 until stack values are safe */
     if (gimme == G_SCALAR) {
        MARK = newsp + 1;
        if (MARK <= SP)
-           if (SvFLAGS(TOPs) & SVs_TEMP)
-               *MARK = TOPs;
-           else
-               *MARK = sv_mortalcopy(TOPs);
+           *MARK = SvTEMP(TOPs) ? TOPs : sv_mortalcopy(TOPs);
        else {
-           MEXTEND(mark,0);
+           MEXTEND(MARK, 0);
            *MARK = &sv_undef;
        }
        SP = MARK;
     }
     else {
-       for (mark = newsp + 1; mark <= SP; mark++)
-           if (!(SvFLAGS(*mark) & SVs_TEMP))
-               *mark = sv_mortalcopy(*mark);
-               /* in case LEAVE wipes old return values */
-    }
-
-    if (cx->blk_sub.hasargs) {         /* You don't exist; go away. */
-       AV* av = cx->blk_sub.argarray;
-
-       av_clear(av);
-       AvREAL_off(av);
+       for (MARK = newsp + 1; MARK <= SP; MARK++) {
+           if (!SvTEMP(*MARK))
+               *MARK = sv_mortalcopy(*MARK);
+       }
     }
-    curpm = newpm;     /* Don't pop $1 et al till now */
+    PUTBACK;
+    
+    POPSUB2();         /* Stack values are safe: release CV and @_ ... */
+    curpm = newpm;     /* ... and pop $1 et al */
 
     LEAVE;
-    PUTBACK;
     return pop_return();
 }
 
@@ -1685,7 +1732,6 @@ PP(pp_entersub)
     register CONTEXT *cx;
     I32 gimme;
     bool hasargs = (op->op_flags & OPf_STACKED) != 0;
-    bool may_clone = TRUE;
 
     if (!sv)
        DIE("Not a CODE reference");
@@ -1696,26 +1742,28 @@ PP(pp_entersub)
 
            if (sv == &sv_yes)          /* unfound import, ignore */
                RETURN;
-           if (!SvOK(sv))
+           if (SvGMAGICAL(sv)) {
+               mg_get(sv);
+               sym = SvPOKp(sv) ? SvPVX(sv) : Nullch;
+           }
+           else
+               sym = SvPV(sv, na);
+           if (!sym)
                DIE(no_usym, "a subroutine");
-           sym = SvPV(sv,na);
            if (op->op_private & HINT_STRICT_REFS)
                DIE(no_symref, sym, "a subroutine");
            cv = perl_get_cv(sym, TRUE);
            break;
        }
        cv = (CV*)SvRV(sv);
-       if (SvTYPE(cv) == SVt_PVCV) {
-           may_clone = FALSE;
+       if (SvTYPE(cv) == SVt_PVCV)
            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 = GvCVu((GV*)sv)))
@@ -1723,9 +1771,6 @@ PP(pp_entersub)
        break;
     }
 
-    if (may_clone && cv && CvCLONE(cv))
-       cv = (CV*)sv_2mortal((SV*)cv_clone(cv));
-
     ENTER;
     SAVETMPS;
 
@@ -1734,30 +1779,30 @@ PP(pp_entersub)
        DIE("Not a CODE reference");
 
     if (!CvROOT(cv) && !CvXSUB(cv)) {
-       if (gv = CvGV(cv)) {
-           SV *tmpstr;
-           GV *ngv;
-           if (cv != GvCV(gv)) {       /* autoloaded stub? */
-               cv = GvCV(gv);
-               goto retry;
-           }
-           tmpstr = sv_newmortal();
-           gv_efullname3(tmpstr, gv, Nullch);
-           ngv = gv_fetchmethod(GvESTASH(gv), "AUTOLOAD");
-           if (ngv && ngv != gv && (cv = GvCV(ngv))) { /* One more chance... */
-               gv = ngv;
-               sv_setsv(GvSV(CvGV(cv)), tmpstr);       /* Set CV's $AUTOLOAD */
-               SvTAINTED_off(GvSV(CvGV(cv)));
-               goto retry;
-           }
-           else
-               DIE("Undefined subroutine &%s called",SvPVX(tmpstr));
+       GV* autogv;
+       SV* subname;
+
+       /* anonymous or undef'd function leaves us no recourse */
+       if (CvANON(cv) || !(gv = CvGV(cv)))
+           DIE("Undefined subroutine called");
+       /* autoloaded stub? */
+       if (cv != GvCV(gv)) {
+           cv = GvCV(gv);
+           goto retry;
        }
-       DIE("Undefined subroutine called");
+       /* should call AUTOLOAD now? */
+       if ((autogv = gv_autoload(GvESTASH(gv), GvNAME(gv), GvNAMELEN(gv)))) {
+           cv = GvCV(autogv);
+           goto retry;
+       }
+       /* sorry */
+       subname = sv_newmortal();
+       gv_efullname3(subname, gv, Nullch);
+       DIE("Undefined subroutine &%s called", SvPVX(subname));
     }
 
     gimme = GIMME;
-    if ((op->op_private & OPpENTERSUB_DB) && !CvNODEBUG(cv)) {
+    if ((op->op_private & OPpENTERSUB_DB) && GvCV(DBsub) && !CvNODEBUG(cv)) {
        SV *oldsv = sv;
        sv = GvSV(DBsub);
        save_item(sv);
@@ -1851,8 +1896,8 @@ PP(pp_entersub)
            (void)SvREFCNT_inc(cv);
        else {  /* save temporaries on recursion? */
            if (CvDEPTH(cv) == 100 && dowarn 
-               && !(perldb && cv == GvCV(DBsub)))
-               warn("Deep recursion on subroutine \"%s\"",GvENAME(CvGV(cv)));
+                 && !(perldb && cv == GvCV(DBsub)))
+               sub_crush_depth(cv);
            if (CvDEPTH(cv) > AvFILL(padlist)) {
                AV *av;
                AV *newpad = newAV();
@@ -1932,35 +1977,61 @@ PP(pp_entersub)
     }
 }
 
+void
+sub_crush_depth(cv)
+CV* cv;
+{
+    if (CvANON(cv))
+       warn("Deep recursion on anonymous subroutine");
+    else {
+       SV* tmpstr = sv_newmortal();
+       gv_efullname3(tmpstr, CvGV(cv), Nullch);
+       warn("Deep recursion on subroutine \"%s\"", SvPVX(tmpstr));
+    }
+}
+
 PP(pp_aelem)
 {
     dSP;
     SV** svp;
     I32 elem = POPi;
-    AV *av = (AV*)POPs;
-    I32 lval = op->op_flags & OPf_MOD;
+    AV* av = (AV*)POPs;
+    U32 lval = op->op_flags & OPf_MOD;
+    U32 defer = (op->op_private & OPpLVAL_DEFER) && (elem > AvFILL(av));
 
     if (elem > 0)
        elem -= curcop->cop_arybase;
     if (SvTYPE(av) != SVt_PVAV)
        RETPUSHUNDEF;
-    svp = av_fetch(av, elem, lval);
+    svp = av_fetch(av, elem, lval && !defer);
     if (lval) {
-       if (!svp || *svp == &sv_undef)
-           DIE(no_aelem, elem);
+       if (!svp || *svp == &sv_undef) {
+           SV* lv;
+           if (!defer)
+               DIE(no_aelem, elem);
+           lv = sv_newmortal();
+           sv_upgrade(lv, SVt_PVLV);
+           LvTYPE(lv) = 'y';
+           sv_magic(lv, Nullsv, 'y', Nullch, 0);
+           LvTARG(lv) = SvREFCNT_inc(av);
+           LvTARGOFF(lv) = elem;
+           LvTARGLEN(lv) = 1;
+           PUSHs(lv);
+           RETURN;
+       }
        if (op->op_private & OPpLVAL_INTRO)
            save_svref(svp);
        else if (op->op_private & OPpDEREF)
-           provide_ref(op, *svp);
+           vivify_ref(*svp, op->op_private & OPpDEREF);
     }
     PUSHs(svp ? *svp : &sv_undef);
     RETURN;
 }
 
 void
-provide_ref(op, sv)
-OP* op;
+vivify_ref(sv, to_what)
 SV* sv;
+U32 to_what;
 {
     if (SvGMAGICAL(sv))
        mg_get(sv);
@@ -1974,8 +2045,7 @@ SV* sv;
            Safefree(SvPVX(sv));
            SvLEN(sv) = SvCUR(sv) = 0;
        }
-       switch (op->op_private & OPpDEREF)
-       {
+       switch (to_what) {
        case OPpDEREF_SV:
            SvRV(sv) = newSV(0);
            break;