This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix use_ok() in vmsish.t broken by 46d4dcbda33f17cc.
[perl5.git] / pp_hot.c
index a3fea5c..66198a2 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -315,7 +315,7 @@ PP(pp_readline)
 {
     dVAR;
     dSP; SvGETMAGIC(TOPs);
-    tryAMAGICunTARGET(iter, 0);
+    tryAMAGICunTARGET(iter_amg, 0, 0);
     PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--);
     if (!isGV_with_GP(PL_last_in_gv)) {
        if (SvROK(PL_last_in_gv) && isGV_with_GP(SvRV(PL_last_in_gv)))
@@ -324,7 +324,7 @@ PP(pp_readline)
            dSP;
            XPUSHs(MUTABLE_SV(PL_last_in_gv));
            PUTBACK;
-           pp_rv2gv();
+           Perl_pp_rv2gv(aTHX);
            PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--);
        }
     }
@@ -334,7 +334,7 @@ PP(pp_readline)
 PP(pp_eq)
 {
     dVAR; dSP;
-    tryAMAGICbin_MG(eq_amg, AMGf_set);
+    tryAMAGICbin_MG(eq_amg, AMGf_set|AMGf_numeric);
 #ifndef NV_PRESERVES_UV
     if (SvROK(TOPs) && !SvAMAGIC(TOPs) && SvROK(TOPm1s) && !SvAMAGIC(TOPm1s)) {
         SP--;
@@ -710,13 +710,13 @@ PP(pp_pushre)
 PP(pp_print)
 {
     dVAR; dSP; dMARK; dORIGMARK;
-    IO *io;
     register PerlIO *fp;
     MAGIC *mg;
     GV * const gv
        = (PL_op->op_flags & OPf_STACKED) ? MUTABLE_GV(*++MARK) : PL_defoutgv;
+    IO *io = GvIO(gv);
 
-    if (gv && (io = GvIO(gv))
+    if (io
        && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar)))
     {
       had_magic:
@@ -729,39 +729,25 @@ PP(pp_print)
            Move(MARK, MARK + 1, (SP - MARK) + 1, SV*);
            ++SP;
        }
-       PUSHMARK(MARK - 1);
-       *MARK = SvTIED_obj(MUTABLE_SV(io), mg);
-       PUTBACK;
-       ENTER_with_name("call_PRINT");
-       if( PL_op->op_type == OP_SAY ) {
-               /* local $\ = "\n" */
-               SAVEGENERICSV(PL_ors_sv);
-               PL_ors_sv = newSVpvs("\n");
-       }
-       call_method("PRINT", G_SCALAR);
-       LEAVE_with_name("call_PRINT");
-       SPAGAIN;
-       MARK = ORIGMARK + 1;
-       *MARK = *SP;
-       SP = MARK;
-       RETURN;
+       return Perl_tied_method(aTHX_ "PRINT", mark - 1, MUTABLE_SV(io),
+                               mg,
+                               (G_SCALAR | TIED_METHOD_ARGUMENTS_ON_STACK
+                                | (PL_op->op_type == OP_SAY
+                                   ? TIED_METHOD_SAY : 0)), sp - mark);
     }
-    if (!(io = GvIO(gv))) {
+    if (!io) {
         if ( gv && GvEGVx(gv) && (io = GvIO(GvEGV(gv)))
            && (mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar)))
             goto had_magic;
-       if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
-           report_evil_fh(gv, io, PL_op->op_type);
+       report_evil_fh(gv);
        SETERRNO(EBADF,RMS_IFI);
        goto just_say_no;
     }
     else if (!(fp = IoOFP(io))) {
-       if (ckWARN2(WARN_CLOSED, WARN_IO))  {
-           if (IoIFP(io))
-               report_evil_fh(gv, io, OP_phoney_INPUT_ONLY);
-           else if (ckWARN2(WARN_UNOPENED,WARN_CLOSED))
-               report_evil_fh(gv, io, PL_op->op_type);
-       }
+       if (IoIFP(io))
+           report_wrongway_fh(gv, '<');
+       else
+           report_evil_fh(gv);
        SETERRNO(EBADF,IoIFP(io)?RMS_FAC:RMS_IFI);
        goto just_say_no;
     }
@@ -827,8 +813,10 @@ PP(pp_rv2av)
     if (!(PL_op->op_private & OPpDEREFed))
        SvGETMAGIC(sv);
     if (SvROK(sv)) {
-       tryAMAGICunDEREF_var(is_pp_rv2av ? to_av_amg : to_hv_amg);
-
+       if (SvAMAGIC(sv)) {
+           sv = amagic_deref_call(sv, is_pp_rv2av ? to_av_amg : to_hv_amg);
+           SPAGAIN;
+       }
        sv = SvRV(sv);
        if (SvTYPE(sv) != type)
            DIE(aTHX_ "Not %s reference", is_pp_rv2av ? an_array : a_hash);
@@ -889,45 +877,45 @@ PP(pp_rv2av)
 
     if (is_pp_rv2av) {
        AV *const av = MUTABLE_AV(sv);
-       /* The guts of pp_rv2av, with no intenting change to preserve history
+       /* The guts of pp_rv2av, with no intending change to preserve history
           (until such time as we get tools that can do blame annotation across
           whitespace changes.  */
-    if (gimme == G_ARRAY) {
-       const I32 maxarg = AvFILL(av) + 1;
-       (void)POPs;                     /* XXXX May be optimized away? */
-       EXTEND(SP, maxarg);
-       if (SvRMAGICAL(av)) {
-           U32 i;
-           for (i=0; i < (U32)maxarg; i++) {
-               SV ** const svp = av_fetch(av, i, FALSE);
-               /* See note in pp_helem, and bug id #27839 */
-               SP[i+1] = svp
-                   ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp
-                   : &PL_sv_undef;
+       if (gimme == G_ARRAY) {
+           const I32 maxarg = AvFILL(av) + 1;
+           (void)POPs;                 /* XXXX May be optimized away? */
+           EXTEND(SP, maxarg);
+           if (SvRMAGICAL(av)) {
+               U32 i;
+               for (i=0; i < (U32)maxarg; i++) {
+                   SV ** const svp = av_fetch(av, i, FALSE);
+                   /* See note in pp_helem, and bug id #27839 */
+                   SP[i+1] = svp
+                       ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp
+                       : &PL_sv_undef;
+               }
            }
+           else {
+               Copy(AvARRAY(av), SP+1, maxarg, SV*);
+           }
+           SP += maxarg;
        }
-       else {
-           Copy(AvARRAY(av), SP+1, maxarg, SV*);
+       else if (gimme == G_SCALAR) {
+           dTARGET;
+           const I32 maxarg = AvFILL(av) + 1;
+           SETi(maxarg);
        }
-       SP += maxarg;
-    }
-    else if (gimme == G_SCALAR) {
-       dTARGET;
-       const I32 maxarg = AvFILL(av) + 1;
-       SETi(maxarg);
-    }
     } else {
        /* The guts of pp_rv2hv  */
-    if (gimme == G_ARRAY) { /* array wanted */
-       *PL_stack_sp = sv;
-       return do_kv();
-    }
-    else if (gimme == G_SCALAR) {
-       dTARGET;
-    TARG = Perl_hv_scalar(aTHX_ MUTABLE_HV(sv));
-       SPAGAIN;
-       SETTARG;
-    }
+       if (gimme == G_ARRAY) { /* array wanted */
+           *PL_stack_sp = sv;
+           return Perl_do_kv(aTHX);
+       }
+       else if (gimme == G_SCALAR) {
+           dTARGET;
+           TARG = Perl_hv_scalar(aTHX_ MUTABLE_HV(sv));
+           SPAGAIN;
+           SETTARG;
+       }
     }
     RETURN;
 
@@ -1579,21 +1567,15 @@ Perl_do_readline(pTHX)
     const I32 gimme = GIMME_V;
 
     if (io) {
-       MAGIC * const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar);
+       const MAGIC *const mg = SvTIED_mg((const SV *)io, PERL_MAGIC_tiedscalar);
        if (mg) {
-           PUSHMARK(SP);
-           XPUSHs(SvTIED_obj(MUTABLE_SV(io), mg));
-           PUTBACK;
-           ENTER_with_name("call_READLINE");
-           call_method("READLINE", gimme);
-           LEAVE_with_name("call_READLINE");
-           SPAGAIN;
+           Perl_tied_method(aTHX_ "READLINE", SP, MUTABLE_SV(io), mg, gimme, 0);
            if (gimme == G_SCALAR) {
-               SV* const result = POPs;
-               SvSetSV_nosteal(TARG, result);
-               PUSHTARG;
+               SPAGAIN;
+               SvSetSV_nosteal(TARG, TOPs);
+               SETTARG;
            }
-           RETURN;
+           return NORMAL;
        }
     }
     fp = NULL;
@@ -1622,8 +1604,8 @@ Perl_do_readline(pTHX)
        }
        else if (type == OP_GLOB)
            SP--;
-       else if (ckWARN(WARN_IO) && IoTYPE(io) == IoTYPE_WRONLY) {
-           report_evil_fh(PL_last_in_gv, io, OP_phoney_OUTPUT_ONLY);
+       else if (IoTYPE(io) == IoTYPE_WRONLY) {
+           report_wrongway_fh(PL_last_in_gv, '>');
        }
     }
     if (!fp) {
@@ -1635,7 +1617,7 @@ Perl_do_readline(pTHX)
                            "glob failed (can't start child: %s)",
                            Strerror(errno));
            else
-               report_evil_fh(PL_last_in_gv, io, PL_op->op_type);
+               report_evil_fh(PL_last_in_gv);
        }
        if (gimme == G_SCALAR) {
            /* undef TARG, and push that undefined value */
@@ -2179,7 +2161,7 @@ PP(pp_subst)
        s = CALLREG_INTUIT_START(rx, TARG, s, strend, r_flags, NULL);
 
        if (!s)
-           goto nope;
+           goto ret_no;
        /* How to do it in subst? */
 /*     if ( (RX_EXTFLAGS(rx) & RXf_CHECK_ALL)
             && !PL_sawampersand
@@ -2203,12 +2185,13 @@ PP(pp_subst)
         * http://www.nntp.perl.org/group/perl.perl5.porters/2010/04/msg158809.html
         */
        if (matched && DO_UTF8(dstr) && ! DO_UTF8(TARG)) {
-           const STRLEN new_len = sv_utf8_upgrade(TARG);
+           char * const orig_pvx =  SvPVX(TARG);
+           const STRLEN new_len = sv_utf8_upgrade_nomg(TARG);
 
            /* If the lengths are the same, the pattern contains only
             * invariants, can keep going; otherwise, various internal markers
             * could be off, so redo */
-           if (new_len != len) {
+           if (new_len != len || orig_pvx != SvPVX(TARG)) {
                goto setup_match;
            }
        }
@@ -2234,6 +2217,14 @@ PP(pp_subst)
        doutf8 = FALSE;
     }
     
+    if (!matched) {
+      ret_no:
+       SPAGAIN;
+       PUSHs(rpm->op_pmflags & PMf_NONDESTRUCT ? TARG : &PL_sv_no);
+       LEAVE_SCOPE(oldsave);
+       RETURN;
+    }
+
     /* can do inplace substitution? */
     if (c
 #ifdef PERL_OLD_COPY_ON_WRITE
@@ -2241,17 +2232,9 @@ PP(pp_subst)
 #endif
        && (I32)clen <= RX_MINLENRET(rx) && (once || !(r_flags & REXEC_COPY_STR))
        && !(RX_EXTFLAGS(rx) & RXf_LOOKBEHIND_SEEN)
-       && (!doutf8 || SvUTF8(TARG))) {
-       if (!matched)
-       {
-           SPAGAIN;
-           if (rpm->op_pmflags & PMf_NONDESTRUCT)
-               PUSHs(TARG);
-           else
-               PUSHs(&PL_sv_no);
-           LEAVE_SCOPE(oldsave);
-           RETURN;
-       }
+       && (!doutf8 || SvUTF8(TARG)))
+    {
+
 #ifdef PERL_OLD_COPY_ON_WRITE
        if (SvIsCOW(TARG)) {
            assert (!force_on_match);
@@ -2302,10 +2285,7 @@ PP(pp_subst)
            }
            TAINT_IF(rxtainted & 1);
            SPAGAIN;
-           if (rpm->op_pmflags & PMf_NONDESTRUCT)
-               PUSHs(TARG);
-           else
-               PUSHs(&PL_sv_yes);
+           PUSHs(rpm->op_pmflags & PMf_NONDESTRUCT ? TARG : &PL_sv_yes);
        }
        else {
            do {
@@ -2339,22 +2319,8 @@ PP(pp_subst)
            else
                mPUSHi((I32)iters);
        }
-       (void)SvPOK_only_UTF8(TARG);
-       TAINT_IF(rxtainted);
-       if (SvSMAGICAL(TARG)) {
-           PUTBACK;
-           mg_set(TARG);
-           SPAGAIN;
-       }
-       SvTAINT(TARG);
-       if (doutf8)
-           SvUTF8_on(TARG);
-       LEAVE_SCOPE(oldsave);
-       RETURN;
     }
-
-    if (matched)
-    {
+    else {
        if (force_on_match) {
            force_on_match = 0;
            s = SvPV_force(TARG, len);
@@ -2427,25 +2393,13 @@ PP(pp_subst)
            PUSHs(TARG);
        else
            mPUSHi((I32)iters);
-
-       (void)SvPOK_only(TARG);
-       if (doutf8)
-           SvUTF8_on(TARG);
-       TAINT_IF(rxtainted);
-       SvSETMAGIC(TARG);
-       SvTAINT(TARG);
-       LEAVE_SCOPE(oldsave);
-       RETURN;
     }
-    goto ret_no;
-
-nope:
-ret_no:
-    SPAGAIN;
-    if (rpm->op_pmflags & PMf_NONDESTRUCT)
-       PUSHs(TARG);
-    else
-       PUSHs(&PL_sv_no);
+    (void)SvPOK_only_UTF8(TARG);
+    if (doutf8)
+       SvUTF8_on(TARG);
+    TAINT_IF(rxtainted);
+    SvSETMAGIC(TARG);
+    SvTAINT(TARG);
     LEAVE_SCOPE(oldsave);
     RETURN;
 }
@@ -2594,6 +2548,29 @@ PP(pp_leavesublv)
        if (gimme == G_SCALAR)
            goto temporise;
        if (gimme == G_ARRAY) {
+           mark = newsp + 1;
+           /* We want an array here, but padav will have left us an arrayref for an lvalue,
+            * so we need to expand it */
+           if(SvTYPE(*mark) == SVt_PVAV) {
+               AV *const av = MUTABLE_AV(*mark);
+               const I32 maxarg = AvFILL(av) + 1;
+               (void)POPs; /* get rid of the array ref */
+               EXTEND(SP, maxarg);
+               if (SvRMAGICAL(av)) {
+                   U32 i;
+                   for (i=0; i < (U32)maxarg; i++) {
+                       SV ** const svp = av_fetch(av, i, FALSE);
+                       SP[i+1] = svp
+                           ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp
+                           : &PL_sv_undef;
+                   }
+               }
+               else {
+                   Copy(AvARRAY(av), SP+1, maxarg, SV*);
+               }
+               SP += maxarg;
+               PUTBACK;
+           }
            if (!CvLVALUE(cx->blk_sub.cv))
                goto temporise_array;
            EXTEND_MORTAL(SP - newsp);
@@ -2770,8 +2747,10 @@ PP(pp_entersub)
        }
        SvGETMAGIC(sv);
        if (SvROK(sv)) {
-           SV * const * sp = &sv;      /* Used in tryAMAGICunDEREF macro. */
-           tryAMAGICunDEREF(to_cv);
+           if (SvAMAGIC(sv)) {
+               sv = amagic_deref_call(sv, to_cv_amg);
+               /* Don't SPAGAIN here.  */
+           }
        }
        else {
            const char *sym;
@@ -2801,6 +2780,8 @@ PP(pp_entersub)
     SAVETMPS;
 
   retry:
+    if (CvCLONE(cv) && ! CvCLONED(cv))
+       DIE(aTHX_ "Closure prototype called");
     if (!CvROOT(cv) && !CvXSUB(cv)) {
        GV* autogv;
        SV* sub_name;