This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add ENTER_with_name and LEAVE_with_name to automaticly check for matching ENTER/LEAVE...
[perl5.git] / pp.c
diff --git a/pp.c b/pp.c
index d720b70..4b6d11f 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -202,7 +202,7 @@ PP(pp_rv2gv)
            }
            else {
                if (PL_op->op_private & HINT_STRICT_REFS)
            }
            else {
                if (PL_op->op_private & HINT_STRICT_REFS)
-                   DIE(aTHX_ PL_no_symref_sv, sv, "a symbol");
+                   DIE(aTHX_ PL_no_symref_sv, sv, (SvCUR(sv)>32 ? "..." : ""), "a symbol");
                if ((PL_op->op_private & (OPpLVAL_INTRO|OPpDONT_INIT_GV))
                    == OPpDONT_INIT_GV) {
                    /* We are the target of a coderef assignment.  Return
                if ((PL_op->op_private & (OPpLVAL_INTRO|OPpDONT_INIT_GV))
                    == OPpDONT_INIT_GV) {
                    /* We are the target of a coderef assignment.  Return
@@ -232,7 +232,7 @@ Perl_softref2xv(pTHX_ SV *const sv, const char *const what,
 
     if (PL_op->op_private & HINT_STRICT_REFS) {
        if (SvOK(sv))
 
     if (PL_op->op_private & HINT_STRICT_REFS) {
        if (SvOK(sv))
-           Perl_die(aTHX_ PL_no_symref_sv, sv, what);
+           Perl_die(aTHX_ PL_no_symref_sv, sv, (SvCUR(sv)>32 ? "..." : ""), what);
        else
            Perl_die(aTHX_ PL_no_usym, what);
     }
        else
            Perl_die(aTHX_ PL_no_usym, what);
     }
@@ -321,12 +321,19 @@ PP(pp_av2arylen)
 {
     dVAR; dSP;
     AV * const av = MUTABLE_AV(TOPs);
 {
     dVAR; dSP;
     AV * const av = MUTABLE_AV(TOPs);
-    SV ** const sv = Perl_av_arylen_p(aTHX_ MUTABLE_AV(av));
-    if (!*sv) {
-       *sv = newSV_type(SVt_PVMG);
-       sv_magic(*sv, MUTABLE_SV(av), PERL_MAGIC_arylen, NULL, 0);
+    const I32 lvalue = PL_op->op_flags & OPf_MOD || LVRET;
+    if (lvalue) {
+       SV ** const sv = Perl_av_arylen_p(aTHX_ MUTABLE_AV(av));
+       if (!*sv) {
+           *sv = newSV_type(SVt_PVMG);
+           sv_magic(*sv, MUTABLE_SV(av), PERL_MAGIC_arylen, NULL, 0);
+       }
+       SETs(*sv);
+    } else {
+       SETs(sv_2mortal(newSViv(
+           AvFILL(MUTABLE_AV(av)) + CopARYBASE_get(PL_curcop)
+       )));
     }
     }
-    SETs(*sv);
     RETURN;
 }
 
     RETURN;
 }
 
@@ -342,8 +349,7 @@ PP(pp_pos)
 
        LvTYPE(TARG) = '.';
        if (LvTARG(TARG) != sv) {
 
        LvTYPE(TARG) = '.';
        if (LvTARG(TARG) != sv) {
-           if (LvTARG(TARG))
-               SvREFCNT_dec(LvTARG(TARG));
+           SvREFCNT_dec(LvTARG(TARG));
            LvTARG(TARG) = SvREFCNT_inc_simple(sv);
        }
        PUSHs(TARG);    /* no SvSETMAGIC */
            LvTARG(TARG) = SvREFCNT_inc_simple(sv);
        }
        PUSHs(TARG);    /* no SvSETMAGIC */
@@ -422,6 +428,10 @@ PP(pp_prototype)
                    ret = newSVpvs_flags("_;$", SVs_TEMP);
                    goto set;
                }
                    ret = newSVpvs_flags("_;$", SVs_TEMP);
                    goto set;
                }
+               if (code == -KEY_keys || code == -KEY_values || code == -KEY_each) {
+                   ret = newSVpvs_flags("\\[@%]", SVs_TEMP);
+                   goto set;
+               }
                if (code == -KEY_readpipe) {
                    s = "CORE::backtick";
                }
                if (code == -KEY_readpipe) {
                    s = "CORE::backtick";
                }
@@ -3190,8 +3200,7 @@ PP(pp_substr)
            sv_insert_flags(sv, pos, rem, repl, repl_len, 0);
            if (repl_is_utf8)
                SvUTF8_on(sv);
            sv_insert_flags(sv, pos, rem, repl, repl_len, 0);
            if (repl_is_utf8)
                SvUTF8_on(sv);
-           if (repl_sv_copy)
-               SvREFCNT_dec(repl_sv_copy);
+           SvREFCNT_dec(repl_sv_copy);
        }
        else if (lvalue) {              /* it's an lvalue! */
            if (!SvGMAGICAL(sv)) {
        }
        else if (lvalue) {              /* it's an lvalue! */
            if (!SvGMAGICAL(sv)) {
@@ -3215,8 +3224,7 @@ PP(pp_substr)
 
            LvTYPE(TARG) = 'x';
            if (LvTARG(TARG) != sv) {
 
            LvTYPE(TARG) = 'x';
            if (LvTARG(TARG) != sv) {
-               if (LvTARG(TARG))
-                   SvREFCNT_dec(LvTARG(TARG));
+               SvREFCNT_dec(LvTARG(TARG));
                LvTARG(TARG) = SvREFCNT_inc_simple(sv);
            }
            LvTARGOFF(TARG) = upos;
                LvTARG(TARG) = SvREFCNT_inc_simple(sv);
            }
            LvTARGOFF(TARG) = upos;
@@ -3246,8 +3254,7 @@ PP(pp_vec)
        }
        LvTYPE(TARG) = 'v';
        if (LvTARG(TARG) != src) {
        }
        LvTYPE(TARG) = 'v';
        if (LvTARG(TARG) != src) {
-           if (LvTARG(TARG))
-               SvREFCNT_dec(LvTARG(TARG));
+           SvREFCNT_dec(LvTARG(TARG));
            LvTARG(TARG) = SvREFCNT_inc_simple(src);
        }
        LvTARGOFF(TARG) = offset;
            LvTARG(TARG) = SvREFCNT_inc_simple(src);
        }
        LvTARGOFF(TARG) = offset;
@@ -3373,8 +3380,7 @@ PP(pp_index)
        if (retval > 0 && big_utf8)
            sv_pos_b2u(big, &retval);
     }
        if (retval > 0 && big_utf8)
            sv_pos_b2u(big, &retval);
     }
-    if (temp)
-       SvREFCNT_dec(temp);
+    SvREFCNT_dec(temp);
  fail:
     PUSHi(retval + arybase);
     RETURN;
  fail:
     PUSHi(retval + arybase);
     RETURN;
@@ -4517,9 +4523,9 @@ PP(pp_splice)
        *MARK-- = SvTIED_obj(MUTABLE_SV(ary), mg);
        PUSHMARK(MARK);
        PUTBACK;
        *MARK-- = SvTIED_obj(MUTABLE_SV(ary), mg);
        PUSHMARK(MARK);
        PUTBACK;
-       ENTER;
+       ENTER_with_name("call_SPLICE");
        call_method("SPLICE",GIMME_V);
        call_method("SPLICE",GIMME_V);
-       LEAVE;
+       LEAVE_with_name("call_SPLICE");
        SPAGAIN;
        RETURN;
     }
        SPAGAIN;
        RETURN;
     }
@@ -4713,9 +4719,9 @@ PP(pp_push)
        *MARK-- = SvTIED_obj(MUTABLE_SV(ary), mg);
        PUSHMARK(MARK);
        PUTBACK;
        *MARK-- = SvTIED_obj(MUTABLE_SV(ary), mg);
        PUSHMARK(MARK);
        PUTBACK;
-       ENTER;
+       ENTER_with_name("call_PUSH");
        call_method("PUSH",G_SCALAR|G_DISCARD);
        call_method("PUSH",G_SCALAR|G_DISCARD);
-       LEAVE;
+       LEAVE_with_name("call_PUSH");
        SPAGAIN;
     }
     else {
        SPAGAIN;
     }
     else {
@@ -4762,9 +4768,9 @@ PP(pp_unshift)
        *MARK-- = SvTIED_obj(MUTABLE_SV(ary), mg);
        PUSHMARK(MARK);
        PUTBACK;
        *MARK-- = SvTIED_obj(MUTABLE_SV(ary), mg);
        PUSHMARK(MARK);
        PUTBACK;
-       ENTER;
+       ENTER_with_name("call_UNSHIFT");
        call_method("UNSHIFT",G_SCALAR|G_DISCARD);
        call_method("UNSHIFT",G_SCALAR|G_DISCARD);
-       LEAVE;
+       LEAVE_with_name("call_UNSHIFT");
        SPAGAIN;
     }
     else {
        SPAGAIN;
     }
     else {
@@ -4785,17 +4791,76 @@ PP(pp_unshift)
 PP(pp_reverse)
 {
     dVAR; dSP; dMARK;
 PP(pp_reverse)
 {
     dVAR; dSP; dMARK;
-    SV ** const oldsp = SP;
 
     if (GIMME == G_ARRAY) {
 
     if (GIMME == G_ARRAY) {
-       MARK++;
-       while (MARK < SP) {
-           register SV * const tmp = *MARK;
-           *MARK++ = *SP;
-           *SP-- = tmp;
+       if (PL_op->op_private & OPpREVERSE_INPLACE) {
+           AV *av;
+
+           /* See pp_sort() */
+           assert( MARK+1 == SP && *SP && SvTYPE(*SP) == SVt_PVAV);
+           (void)POPMARK; /* remove mark associated with ex-OP_AASSIGN */
+           av = MUTABLE_AV((*SP));
+           /* In-place reversing only happens in void context for the array
+            * assignment. We don't need to push anything on the stack. */
+           SP = MARK;
+
+           if (SvMAGICAL(av)) {
+               I32 i, j;
+               register SV *tmp = sv_newmortal();
+               /* For SvCANEXISTDELETE */
+               HV *stash;
+               const MAGIC *mg;
+               bool can_preserve = SvCANEXISTDELETE(av);
+
+               for (i = 0, j = av_len(av); i < j; ++i, --j) {
+                   register SV *begin, *end;
+
+                   if (can_preserve) {
+                       if (!av_exists(av, i)) {
+                           if (av_exists(av, j)) {
+                               register SV *sv = av_delete(av, j, 0);
+                               begin = *av_fetch(av, i, TRUE);
+                               sv_setsv_mg(begin, sv);
+                           }
+                           continue;
+                       }
+                       else if (!av_exists(av, j)) {
+                           register SV *sv = av_delete(av, i, 0);
+                           end = *av_fetch(av, j, TRUE);
+                           sv_setsv_mg(end, sv);
+                           continue;
+                       }
+                   }
+
+                   begin = *av_fetch(av, i, TRUE);
+                   end   = *av_fetch(av, j, TRUE);
+                   sv_setsv(tmp,      begin);
+                   sv_setsv_mg(begin, end);
+                   sv_setsv_mg(end,   tmp);
+               }
+           }
+           else {
+               SV **begin = AvARRAY(av);
+               SV **end   = begin + AvFILLp(av);
+
+               while (begin < end) {
+                   register SV * const tmp = *begin;
+                   *begin++ = *end;
+                   *end--   = tmp;
+               }
+           }
+       }
+       else {
+           SV **oldsp = SP;
+           MARK++;
+           while (MARK < SP) {
+               register SV * const tmp = *MARK;
+               *MARK++ = *SP;
+               *SP--   = tmp;
+           }
+           /* safe as long as stack cannot get extended in the above */
+           SP = oldsp;
        }
        }
-       /* safe as long as stack cannot get extended in the above */
-       SP = oldsp;
     }
     else {
        register char *up;
     }
     else {
        register char *up;
@@ -4883,7 +4948,7 @@ PP(pp_split)
     I32 realarray = 0;
     I32 base;
     const I32 gimme = GIMME_V;
     I32 realarray = 0;
     I32 base;
     const I32 gimme = GIMME_V;
-    const bool gimme_scalar = (GIMME_V == G_SCALAR);
+    bool gimme_scalar;
     const I32 oldsave = PL_savestack_ix;
     U32 make_mortal = SVs_TEMP;
     bool multiline = 0;
     const I32 oldsave = PL_savestack_ix;
     U32 make_mortal = SVs_TEMP;
     bool multiline = 0;
@@ -4957,6 +5022,8 @@ PP(pp_split)
        multiline = 1;
     }
 
        multiline = 1;
     }
 
+    gimme_scalar = gimme == G_SCALAR && !ary;
+
     if (!limit)
        limit = maxiters + 2;
     if (RX_EXTFLAGS(rx) & RXf_WHITE) {
     if (!limit)
        limit = maxiters + 2;
     if (RX_EXTFLAGS(rx) & RXf_WHITE) {
@@ -5263,9 +5330,9 @@ PP(pp_split)
        }
        else {
            PUTBACK;
        }
        else {
            PUTBACK;
-           ENTER;
+           ENTER_with_name("call_PUSH");
            call_method("PUSH",G_SCALAR|G_DISCARD);
            call_method("PUSH",G_SCALAR|G_DISCARD);
-           LEAVE;
+           LEAVE_with_name("call_PUSH");
            SPAGAIN;
            if (gimme == G_ARRAY) {
                I32 i;
            SPAGAIN;
            if (gimme == G_ARRAY) {
                I32 i;
@@ -5323,6 +5390,25 @@ PP(unimplemented_op)
     dVAR;
     DIE(aTHX_ "panic: unimplemented op %s (#%d) called", OP_NAME(PL_op),
        PL_op->op_type);
     dVAR;
     DIE(aTHX_ "panic: unimplemented op %s (#%d) called", OP_NAME(PL_op),
        PL_op->op_type);
+    return NORMAL;
+}
+
+PP(pp_boolkeys)
+{
+    dVAR;
+    dSP;
+    HV * const hv = (HV*)POPs;
+    
+    if (SvRMAGICAL(hv)) {
+       MAGIC * const mg = mg_find((SV*)hv, PERL_MAGIC_tied);
+       if (mg) {
+            XPUSHs(magic_scalarpack(hv, mg));
+           RETURN;
+        }          
+    }
+
+    XPUSHs(boolSV(HvKEYS(hv) != 0));
+    RETURN;
 }
 
 /*
 }
 
 /*