Minor cleanups
[p5sagit/p5-mst-13.2.git] / pp_hot.c
index c9750e6..2f735a3 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.
@@ -160,8 +160,7 @@ PP(pp_sassign)
     }
     if (tainting && tainted && !SvTAINTED(left))
        TAINT_NOT;
-    SvSetSV(right, left);
-    SvSETMAGIC(right);
+    SvSetMagicSV(right, left);
     SETs(right);
     RETURN;
 }
@@ -204,7 +203,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 +220,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_private & OPpDEREF);
     }
     RETURN;
 }
@@ -234,7 +236,7 @@ PP(pp_eq)
     dSP; tryAMAGICbinSET(eq,0); 
     {
       dPOPnv;
-      SETs((TOPn == value) ? &sv_yes : &sv_no);
+      SETs(boolSV(TOPn == value));
       RETURN;
     }
 }
@@ -242,7 +244,7 @@ PP(pp_eq)
 PP(pp_preinc)
 {
     dSP;
-    if (SvREADONLY(TOPs))
+    if (SvREADONLY(TOPs) || SvTYPE(TOPs) > SVt_PVLV)
        croak(no_modify);
     if (SvIOK(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs) &&
        SvIVX(TOPs) != IV_MAX)
@@ -330,17 +332,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))) {
@@ -412,7 +419,6 @@ PP(pp_print)
 PP(pp_rv2av)
 {
     dSP; dPOPss;
-
     AV *av;
 
     if (SvROK(sv)) {
@@ -450,6 +456,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;
@@ -487,9 +495,7 @@ PP(pp_rv2av)
 
 PP(pp_rv2hv)
 {
-
     dSP; dTOPss;
-
     HV *hv;
 
     if (SvROK(sv)) {
@@ -527,6 +533,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;
@@ -557,7 +565,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
@@ -581,6 +589,7 @@ PP(pp_aassign)
     register SV *sv;
     register AV *ary;
 
+    I32 gimme;
     HV *hash;
     I32 i;
     int magic;
@@ -735,7 +744,16 @@ PP(pp_aassign)
        tainting |= (uid && (euid != uid || egid != gid));
     }
     delaymagic = 0;
-    if (GIMME == G_ARRAY) {
+
+    gimme = GIMME_V;
+    if (gimme == G_VOID)
+       SP = firstrelem - 1;
+    else if (gimme == G_SCALAR) {
+       dTARGET;
+       SP = firstrelem;
+       SETi(lastrelem - firstrelem + 1);
+    }
+    else {
        if (ary || hash)
            SP = lastrelem;
        else
@@ -743,15 +761,8 @@ PP(pp_aassign)
        lelem = firstlelem + (relem - firstrelem);
        while (relem <= SP)
            *relem++ = (lelem <= lastlelem) ? *lelem++ : &sv_undef;
-       RETURN;
-    }
-    else {
-       dTARGET;
-       SP = firstrelem;
-               
-       SETi(lastrelem - firstrelem + 1);
-       RETURN;
     }
+    RETURN;
 }
 
 PP(pp_match)
@@ -967,6 +978,7 @@ do_readline()
     PerlIO *fp;
     register IO *io = GvIO(last_in_gv);
     register I32 type = op->op_type;
+    I32 gimme = GIMME_V;
     MAGIC *mg;
 
     if (SvMAGICAL(last_in_gv) && (mg = mg_find((SV*)last_in_gv, 'q'))) {
@@ -974,11 +986,11 @@ do_readline()
        XPUSHs(mg->mg_obj);
        PUTBACK;
        ENTER;
-       perl_call_method("READLINE", GIMME);
+       perl_call_method("READLINE", gimme);
        LEAVE;
        SPAGAIN;
-       if (GIMME == G_SCALAR)
-           SvSetSV_nosteal(TARG, TOPs);
+       if (gimme == G_SCALAR)
+           SvSetMagicSV_nosteal(TARG, TOPs);
        RETURN;
     }
     fp = Nullfp;
@@ -1125,18 +1137,16 @@ do_readline()
     if (!fp) {
        if (dowarn && io && !(IoFLAGS(io) & IOf_START))
            warn("Read on closed filehandle <%s>", GvENAME(last_in_gv));
-       if (GIMME == G_SCALAR) {
+       if (gimme == G_SCALAR) {
            (void)SvOK_off(TARG);
            PUSHTARG;
        }
        RETURN;
     }
-    if (GIMME == G_ARRAY) {
-       sv = sv_2mortal(NEWSV(57, 80));
-       offset = 0;
-    }
-    else {
+    if (gimme == G_SCALAR) {
        sv = TARG;
+       if (SvROK(sv))
+           sv_unref(sv);
        (void)SvUPGRADE(sv, SVt_PV);
        tmplen = SvLEN(sv);     /* remember if already alloced */
        if (!tmplen)
@@ -1146,6 +1156,10 @@ do_readline()
        else
            offset = 0;
     }
+    else {
+       sv = sv_2mortal(NEWSV(57, 80));
+       offset = 0;
+    }
     for (;;) {
        if (!sv_gets(sv, fp, offset)) {
            PerlIO_clearerr(fp);
@@ -1159,7 +1173,7 @@ do_readline()
            else if (type == OP_GLOB) {
                (void)do_close(last_in_gv, FALSE);
            }
-           if (GIMME == G_SCALAR) {
+           if (gimme == G_SCALAR) {
                (void)SvOK_off(TARG);
                PUSHTARG;
            }
@@ -1192,7 +1206,7 @@ do_readline()
                continue;
            }
        }
-       if (GIMME == G_ARRAY) {
+       if (gimme == G_ARRAY) {
            if (SvLEN(sv) - SvCUR(sv) > 20) {
                SvLEN_set(sv, SvCUR(sv)+1);
                Renew(SvPVX(sv), SvLEN(sv), char);
@@ -1200,7 +1214,7 @@ do_readline()
            sv = sv_2mortal(NEWSV(58, 80));
            continue;
        }
-       else if (!tmplen && SvLEN(sv) - SvCUR(sv) > 80) {
+       else if (gimme == G_SCALAR && !tmplen && SvLEN(sv) - SvCUR(sv) > 80) {
            /* try to reclaim a bit of scalar space (only on 1st alloc) */
            if (SvCUR(sv) < 60)
                SvLEN_set(sv, 80);
@@ -1216,19 +1230,14 @@ PP(pp_enter)
 {
     dSP;
     register CONTEXT *cx;
-    I32 gimme;
+    I32 gimme = OP_GIMME(op, -1);
 
-    /*
-     * We don't just use the GIMME macro here because it assumes there's
-     * already a context, which ain't necessarily so at initial startup.
-     */
-
-    if (op->op_flags & OPf_KNOW)
-       gimme = op->op_flags & OPf_LIST;
-    else if (cxstack_ix >= 0)
-       gimme = cxstack[cxstack_ix].blk_gimme;
-    else
-       gimme = G_SCALAR;
+    if (gimme == -1) {
+       if (cxstack_ix >= 0)
+           gimme = cxstack[cxstack_ix].blk_gimme;
+       else
+           gimme = G_SCALAR;
+    }
 
     ENTER;
 
@@ -1244,14 +1253,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));
@@ -1259,7 +1282,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;
@@ -1281,31 +1304,30 @@ PP(pp_leave)
 
     POPBLOCK(cx,newpm);
 
-    if (op->op_flags & OPf_KNOW)
-       gimme = op->op_flags & OPf_LIST;
-    else if (cxstack_ix >= 0)
-       gimme = cxstack[cxstack_ix].blk_gimme;
-    else
-       gimme = G_SCALAR;
+    gimme = OP_GIMME(op, -1);
+    if (gimme == -1) {
+       if (cxstack_ix >= 0)
+           gimme = cxstack[cxstack_ix].blk_gimme;
+       else
+           gimme = G_SCALAR;
+    }
 
-    if (gimme == G_SCALAR) {
-       if (op->op_private & OPpLEAVE_VOID)
-           SP = newsp;
+    if (gimme == G_VOID)
+       SP = newsp;
+    else if (gimme == G_SCALAR) {
+       MARK = newsp + 1;
+       if (MARK <= SP)
+           if (SvFLAGS(TOPs) & (SVs_PADTMP|SVs_TEMP))
+               *MARK = TOPs;
+           else
+               *MARK = sv_mortalcopy(TOPs);
        else {
-           MARK = newsp + 1;
-           if (MARK <= SP)
-               if (SvFLAGS(TOPs) & (SVs_PADTMP|SVs_TEMP))
-                   *MARK = TOPs;
-               else
-                   *MARK = sv_mortalcopy(TOPs);
-           else {
-               MEXTEND(mark,0);
-               *MARK = &sv_undef;
-           }
-           SP = MARK;
+           MEXTEND(mark,0);
+           *MARK = &sv_undef;
        }
+       SP = MARK;
     }
-    else {
+    else if (gimme == G_ARRAY) {
        for (mark = newsp + 1; mark <= SP; mark++)
            if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP)))
                *mark = sv_mortalcopy(*mark);
@@ -1349,14 +1371,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;
     }
 
@@ -1396,8 +1418,12 @@ 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;
 
@@ -1628,18 +1654,19 @@ PP(pp_grepwhile)
     /* All done yet? */
     if (stack_base + *markstack_ptr > sp) {
        I32 items;
+       I32 gimme = GIMME_V;
 
        LEAVE;                                  /* exit outer scope */
        (void)POPMARK;                          /* pop src */
        items = --*markstack_ptr - markstack_ptr[-1];
        (void)POPMARK;                          /* pop dst */
        SP = stack_base + POPMARK;              /* pop original mark */
-       if (GIMME != G_ARRAY) {
+       if (gimme == G_SCALAR) {
            dTARGET;
            XPUSHi(items);
-           RETURN;
        }
-       SP += items;
+       else if (gimme == G_ARRAY)
+           SP += items;
        RETURN;
     }
     else {
@@ -1679,7 +1706,7 @@ PP(pp_leavesub)
        }
        SP = MARK;
     }
-    else {
+    else if (gimme == G_ARRAY) {
        for (MARK = newsp + 1; MARK <= SP; MARK++) {
            if (!SvTEMP(*MARK))
                *MARK = sv_mortalcopy(*MARK);
@@ -1762,7 +1789,9 @@ PP(pp_entersub)
            goto retry;
        }
        /* should call AUTOLOAD now? */
-       if ((autogv = gv_autoload(GvESTASH(gv), GvNAME(gv), GvNAMELEN(gv)))) {
+       if ((autogv = gv_autoload4(GvSTASH(gv), GvNAME(gv), GvNAMELEN(gv),
+                                  FALSE)))
+       {
            cv = GvCV(autogv);
            goto retry;
        }
@@ -1772,7 +1801,7 @@ PP(pp_entersub)
        DIE("Undefined subroutine &%s called", SvPVX(subname));
     }
 
-    gimme = GIMME;
+    gimme = GIMME_V;
     if ((op->op_private & OPpENTERSUB_DB) && GvCV(DBsub) && !CvNODEBUG(cv)) {
        SV *oldsv = sv;
        sv = GvSV(DBsub);
@@ -1966,30 +1995,43 @@ 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);
@@ -2003,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;