This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #96230] Stop s/$qr// from reusing last pattern
[perl5.git] / pp.c
diff --git a/pp.c b/pp.c
index 26df2aa..28a774e 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -29,6 +29,7 @@
 #include "keywords.h"
 
 #include "reentr.h"
+#include "regcharclass.h"
 
 /* XXX I can't imagine anyone who doesn't have this actually _needs_
    it, since pid_t is an integral type.
@@ -131,6 +132,11 @@ PP(pp_padhv)
     if (gimme == G_ARRAY) {
        RETURNOP(Perl_do_kv(aTHX));
     }
+    else if ((PL_op->op_private & OPpTRUEBOOL
+         || (  PL_op->op_private & OPpMAYBE_TRUEBOOL
+            && block_gimme() == G_VOID  ))
+         && (!SvRMAGICAL(TARG) || !mg_find(TARG, PERL_MAGIC_tied)))
+       SETs(HvUSEDKEYS(TARG) ? &PL_sv_yes : sv_2mortal(newSViv(0)));
     else if (gimme == G_SCALAR) {
        SV* const sv = Perl_hv_scalar(aTHX_ MUTABLE_HV(TARG));
        SETs(sv);
@@ -138,6 +144,48 @@ PP(pp_padhv)
     RETURN;
 }
 
+PP(pp_padcv)
+{
+    dVAR; dSP; dTARGET;
+    assert(SvTYPE(TARG) == SVt_PVCV);
+    XPUSHs(TARG);
+    RETURN;
+}
+
+PP(pp_introcv)
+{
+    dVAR; dTARGET;
+    SvPADSTALE_off(TARG);
+    return NORMAL;
+}
+
+PP(pp_clonecv)
+{
+    dVAR; dTARGET;
+    MAGIC * const mg =
+       mg_find(PadlistNAMESARRAY(CvPADLIST(find_runcv(NULL)))[ARGTARG],
+               PERL_MAGIC_proto);
+    assert(SvTYPE(TARG) == SVt_PVCV);
+    assert(mg);
+    assert(mg->mg_obj);
+    if (CvISXSUB(mg->mg_obj)) { /* constant */
+       /* XXX Should we clone it here? */
+       /* If this changes to use SAVECLEARSV, we can move the SAVECLEARSV
+          to introcv and remove the SvPADSTALE_off. */
+       SAVEPADSVANDMORTALIZE(ARGTARG);
+       PAD_SVl(ARGTARG) = mg->mg_obj;
+    }
+    else {
+       if (CvROOT(mg->mg_obj)) {
+           assert(CvCLONE(mg->mg_obj));
+           assert(!CvCLONED(mg->mg_obj));
+       }
+       cv_clone_into((CV *)mg->mg_obj,(CV *)TARG);
+       SAVECLEARSV(PAD_SVl(ARGTARG));
+    }
+    return NORMAL;
+}
+
 /* Translations. */
 
 static const char S_no_symref_sv[] =
@@ -278,8 +326,7 @@ Perl_softref2xv(pTHX_ SV *const sv, const char *const what,
     }
     if (!SvOK(sv)) {
        if (
-         PL_op->op_flags & OPf_REF &&
-         PL_op->op_next->op_type != OP_BOOLKEYS
+         PL_op->op_flags & OPf_REF
        )
            Perl_die(aTHX_ PL_no_usym, what);
        if (ckWARN(WARN_UNINITIALIZED))
@@ -922,16 +969,20 @@ PP(pp_undef)
        {
            /* let user-undef'd sub keep its identity */
            GV* const gv = CvGV((const CV *)sv);
+           HEK * const hek = CvNAME_HEK((CV *)sv);
+           if (hek) share_hek_hek(hek);
            cv_undef(MUTABLE_CV(sv));
-           CvGV_set(MUTABLE_CV(sv), gv);
+           if (gv) CvGV_set(MUTABLE_CV(sv), gv);
+           else if (hek) {
+               SvANY((CV *)sv)->xcv_gv_u.xcv_hek = hek;
+               CvNAMED_on(sv);
+           }
        }
        break;
     case SVt_PVGV:
-       if (SvFAKE(sv)) {
-           SvSetMagicSV(sv, &PL_sv_undef);
-           break;
-       }
-       else if (isGV_with_GP(sv)) {
+       assert(isGV_with_GP(sv));
+       assert(!SvFAKE(sv));
+       {
            GP *gp;
             HV *stash;
 
@@ -969,7 +1020,6 @@ PP(pp_undef)
 
            break;
        }
-       /* FALL THROUGH */
     default:
        if (SvTYPE(sv) >= SVt_PV && SvPVX_const(sv) && SvLEN(sv)) {
            SvPV_free(sv);
@@ -2360,7 +2410,7 @@ PP(pp_i_divide)
     }
 }
 
-#if defined(__GLIBC__) && IVSIZE == 8
+#if defined(__GLIBC__) && IVSIZE == 8 && !defined(PERL_DEBUG_READONLY_OPS)
 STATIC
 PP(pp_i_modulo_0)
 #else
@@ -2383,7 +2433,7 @@ PP(pp_i_modulo)
      }
 }
 
-#if defined(__GLIBC__) && IVSIZE == 8
+#if defined(__GLIBC__) && IVSIZE == 8 && !defined(PERL_DEBUG_READONLY_OPS)
 STATIC
 PP(pp_i_modulo_1)
 
@@ -2863,7 +2913,7 @@ PP(pp_length)
            SETi(len);
     } else if (SvOK(sv)) {
        /* Neither magic nor overloaded.  */
-       if (DO_UTF8(sv))
+       if (!IN_BYTES)
            SETi(sv_len_utf8(sv));
        else
            SETi(sv_len(sv));
@@ -2964,7 +3014,6 @@ PP(pp_substr)
     STRLEN repl_len;
     int num_args = PL_op->op_private & 7;
     bool repl_need_utf8_upgrade = FALSE;
-    bool repl_is_utf8 = FALSE;
 
     if (num_args > 2) {
        if (num_args > 3) {
@@ -2985,17 +3034,7 @@ PP(pp_substr)
        repl_sv = POPs;
     }
     PUTBACK;
-    if (repl_sv) {
-       repl = SvPV_const(repl_sv, repl_len);
-       repl_is_utf8 = DO_UTF8(repl_sv) && repl_len;
-       if (repl_is_utf8) {
-           if (!DO_UTF8(sv))
-               sv_utf8_upgrade(sv);
-       }
-       else if (DO_UTF8(sv))
-           repl_need_utf8_upgrade = TRUE;
-    }
-    else if (lvalue) {
+    if (lvalue && !repl_sv) {
        SV * ret;
        ret = sv_2mortal(newSV_type(SVt_PVLV));  /* Not TARG RT#67838 */
        sv_magic(ret, NULL, PERL_MAGIC_substr, NULL, 0);
@@ -3014,9 +3053,26 @@ PP(pp_substr)
        PUSHs(ret);    /* avoid SvSETMAGIC here */
        RETURN;
     }
-    tmps = SvPV_const(sv, curlen);
+    if (repl_sv) {
+       repl = SvPV_const(repl_sv, repl_len);
+       SvGETMAGIC(sv);
+       if (SvROK(sv))
+           Perl_ck_warner(aTHX_ packWARN(WARN_SUBSTR),
+                           "Attempt to use reference as lvalue in substr"
+           );
+       tmps = SvPV_force_nomg(sv, curlen);
+       if (DO_UTF8(repl_sv) && repl_len) {
+           if (!DO_UTF8(sv)) {
+               sv_utf8_upgrade_nomg(sv);
+               curlen = SvCUR(sv);
+           }
+       }
+       else if (DO_UTF8(sv))
+           repl_need_utf8_upgrade = TRUE;
+    }
+    else tmps = SvPV_const(sv, curlen);
     if (DO_UTF8(sv)) {
-        utf8_curlen = sv_len_utf8(sv);
+        utf8_curlen = sv_or_pv_len_utf8(sv, tmps, curlen);
        if (utf8_curlen == curlen)
            utf8_curlen = 0;
        else
@@ -3034,7 +3090,7 @@ PP(pp_substr)
 
        byte_len = len;
        byte_pos = utf8_curlen
-           ? sv_pos_u2b_flags(sv, pos, &byte_len, SV_CONST_RETURN) : pos;
+           ? sv_or_pv_pos_u2b(sv, tmps, pos, &byte_len) : pos;
 
        tmps += byte_pos;
 
@@ -3056,17 +3112,10 @@ PP(pp_substr)
                repl_sv_copy = newSVsv(repl_sv);
                sv_utf8_upgrade(repl_sv_copy);
                repl = SvPV_const(repl_sv_copy, repl_len);
-               repl_is_utf8 = DO_UTF8(repl_sv_copy) && repl_len;
            }
-           if (SvROK(sv))
-               Perl_ck_warner(aTHX_ packWARN(WARN_SUBSTR),
-                           "Attempt to use reference as lvalue in substr"
-               );
            if (!SvOK(sv))
                sv_setpvs(sv, "");
            sv_insert_flags(sv, byte_pos, byte_len, repl, repl_len, 0);
-           if (repl_is_utf8)
-               SvUTF8_on(sv);
            SvREFCNT_dec(repl_sv_copy);
        }
     }
@@ -4037,7 +4086,7 @@ PP(pp_quotemeta)
                        to_quote = TRUE;
                    }
                }
-               else if (_is_utf8_quotemeta((U8 *) s)) {
+               else if (is_QUOTEMETA_high(s)) {
                    to_quote = TRUE;
                }
 
@@ -5246,6 +5295,7 @@ PP(pp_split)
     STRLEN len;
     const char *s = SvPV_const(sv, len);
     const bool do_utf8 = DO_UTF8(sv);
+    const bool skipwhite = PL_op->op_flags & OPf_SPECIAL;
     const char *strend = s + len;
     PMOP *pm;
     REGEXP *rx;
@@ -5276,7 +5326,7 @@ PP(pp_split)
     rx = PM_GETRE(pm);
 
     TAINT_IF(get_regex_charset(RX_EXTFLAGS(rx)) == REGEX_LOCALE_CHARSET &&
-            (RX_EXTFLAGS(rx) & (RXf_WHITE | RXf_SKIPWHITE)));
+            (RX_EXTFLAGS(rx) & RXf_WHITE || skipwhite));
 
     RX_MATCH_UTF8_set(rx, do_utf8);
 
@@ -5316,7 +5366,7 @@ PP(pp_split)
     }
     base = SP - PL_stack_base;
     orig = s;
-    if (RX_EXTFLAGS(rx) & RXf_SKIPWHITE) {
+    if (skipwhite) {
        if (do_utf8) {
            while (*s == ' ' || is_utf8_space((U8*)s))
                s += UTF8SKIP(s);
@@ -5338,7 +5388,7 @@ PP(pp_split)
 
     if (!limit)
        limit = maxiters + 2;
-    if (RX_EXTFLAGS(rx) & RXf_WHITE) {
+    if (RX_EXTFLAGS(rx) & RXf_WHITE || skipwhite) {
        while (--limit) {
            m = s;
            /* this one uses 'm' and is a negative test */
@@ -5545,13 +5595,9 @@ PP(pp_split)
            if (rex_return == 0)
                break;
            TAINT_IF(RX_MATCH_TAINTED(rx));
-           if (RX_MATCH_COPIED(rx) && RX_SUBBEG(rx) != orig) {
-               m = s;
-               s = orig;
-               orig = RX_SUBBEG(rx);
-               s = orig + (m - s);
-               strend = s + (strend - m);
-           }
+            /* we never pass the REXEC_COPY_STR flag, so it should
+             * never get copied */
+            assert(!RX_MATCH_COPIED(rx));
            m = RX_OFFS(rx)[0].start + orig;
 
            if (gimme_scalar) {
@@ -5718,26 +5764,6 @@ PP(unimplemented_op)
     DIE(aTHX_ "panic: unimplemented op %s (#%d) called", name, op_type);
 }
 
-PP(pp_boolkeys)
-{
-    dVAR;
-    dSP;
-    HV * const hv = (HV*)POPs;
-    
-    if (SvTYPE(hv) != SVt_PVHV) { XPUSHs(&PL_sv_no); RETURN; }
-
-    if (SvRMAGICAL(hv)) {
-       MAGIC * const mg = mg_find((SV*)hv, PERL_MAGIC_tied);
-       if (mg) {
-            XPUSHs(magic_scalarpack(hv, mg));
-           RETURN;
-        }          
-    }
-
-    XPUSHs(boolSV(HvUSEDKEYS(hv) != 0));
-    RETURN;
-}
-
 /* For sorting out arguments passed to a &CORE:: subroutine */
 PP(pp_coreargs)
 {
@@ -5799,7 +5825,7 @@ PP(pp_coreargs)
          try_defsv:
            if (!numargs && defgv && whicharg == minargs + 1) {
                PUSHs(find_rundefsv2(
-                   find_runcv_where(FIND_RUNCV_level_eq, (void *)1, NULL),
+                   find_runcv_where(FIND_RUNCV_level_eq, 1, NULL),
                    cxstack[cxstack_ix].blk_oldcop->cop_seq
                ));
            }
@@ -5888,7 +5914,7 @@ PP(pp_runcv)
     dSP;
     CV *cv;
     if (PL_op->op_private & OPpOFFBYONE) {
-       cv = find_runcv_where(FIND_RUNCV_level_eq, (void *)1, NULL);
+       cv = find_runcv_where(FIND_RUNCV_level_eq, 1, NULL);
     }
     else cv = find_runcv(NULL);
     XPUSHs(CvEVAL(cv) ? &PL_sv_undef : sv_2mortal(newRV((SV *)cv)));