This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
op.c:ck_eval: remove redundant null check
[perl5.git] / pp_hot.c
index c43de40..5010606 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1332,6 +1332,7 @@ PP(pp_match)
     STRLEN len;
     const I32 oldsave = PL_savestack_ix;
     I32 had_zerolen = 0;
+    MAGIC *mg = NULL;
 
     if (PL_op->op_flags & OPf_STACKED)
        TARG = POPs;
@@ -1385,7 +1386,7 @@ PP(pp_match)
 
     /* get pos() if //g */
     if (global) {
-        MAGIC * const mg = mg_find_mglob(TARG);
+        mg = mg_find_mglob(TARG);
         if (mg && mg->mg_len >= 0) {
             curpos = mg->mg_len;
             /* last time pos() was set, it was zero-length match */
@@ -1398,6 +1399,7 @@ PP(pp_match)
     if (       RX_NPARENS(rx)
             || PL_sawampersand
             || (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY))
+            || (dynpm->op_pmflags & PMf_KEEPCOPY)
     )
 #endif
     {
@@ -1409,26 +1411,29 @@ PP(pp_match)
         if (! (global && gimme == G_ARRAY))
             r_flags |= REXEC_COPY_SKIP_POST;
     };
+#ifdef PERL_SAWAMPERSAND
+    if (dynpm->op_pmflags & PMf_KEEPCOPY)
+        /* handle KEEPCOPY in pmop but not rx, eg $r=qr/a/; /$r/p */
+        r_flags &= ~(REXEC_COPY_SKIP_PRE|REXEC_COPY_SKIP_POST);
+#endif
 
     s = truebase;
 
   play_it_again:
-    if (global) {
+    if (global)
        s = truebase + curpos;
-    }
 
     if (!CALLREGEXEC(rx, (char*)s, (char *)strend, (char*)truebase,
                     had_zerolen, TARG, NULL, r_flags))
        goto nope;
 
     PL_curpm = pm;
-    if (dynpm->op_pmflags & PMf_ONCE) {
+    if (dynpm->op_pmflags & PMf_ONCE)
 #ifdef USE_ITHREADS
        SvREADONLY_on(PL_regex_pad[dynpm->op_pmoffset]);
 #else
        dynpm->op_pmflags |= PMf_USED;
 #endif
-    }
 
     if (rxtainted)
        RX_MATCH_TAINTED_on(rx);
@@ -1437,18 +1442,13 @@ PP(pp_match)
     /* update pos */
 
     if (global && (gimme != G_ARRAY || (dynpm->op_pmflags & PMf_CONTINUE))) {
-        MAGIC *mg = mg_find_mglob(TARG);
-        if (!mg) {
+        if (!mg)
             mg = sv_magicext_mglob(TARG);
-        }
-        assert(RX_OFFS(rx)[0].start != -1); /* XXX get rid of next line? */
-        if (RX_OFFS(rx)[0].start != -1) {
-            mg->mg_len = RX_OFFS(rx)[0].end;
-            if (RX_ZERO_LEN(rx))
-                mg->mg_flags |= MGf_MINMATCH;
-            else
-                mg->mg_flags &= ~MGf_MINMATCH;
-        }
+        mg->mg_len = RX_OFFS(rx)[0].end;
+        if (RX_ZERO_LEN(rx))
+            mg->mg_flags |= MGf_MINMATCH;
+        else
+            mg->mg_flags &= ~MGf_MINMATCH;
     }
 
     if ((!RX_NPARENS(rx) && !global) || gimme != G_ARRAY) {
@@ -1495,9 +1495,10 @@ PP(pp_match)
 
 nope:
     if (global && !(dynpm->op_pmflags & PMf_CONTINUE)) {
-           MAGIC* const mg = mg_find_mglob(TARG);
-           if (mg)
-               mg->mg_len = -1;
+        if (!mg)
+            mg = mg_find_mglob(TARG);
+        if (mg)
+            mg->mg_len = -1;
     }
     LEAVE_SCOPE(oldsave);
     if (gimme == G_ARRAY)
@@ -2014,12 +2015,10 @@ PP(pp_subst)
     PMOP *rpm = pm;
     char *s;
     char *strend;
-    char *m;
     const char *c;
     STRLEN clen;
     I32 iters = 0;
     I32 maxiters;
-    I32 i;
     bool once;
     U8 rxtainted = 0; /* holds various SUBST_TAINT_* flag bits.
                        See "how taint works" above */
@@ -2110,6 +2109,7 @@ PP(pp_subst)
     r_flags = (    RX_NPARENS(rx)
                 || PL_sawampersand
                 || (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY))
+                || (rpm->op_pmflags & PMf_KEEPCOPY)
               )
           ? REXEC_COPY_STR
           : 0;
@@ -2117,17 +2117,13 @@ PP(pp_subst)
     r_flags = REXEC_COPY_STR;
 #endif
 
-    m = s = orig;
-
-    if (!CALLREGEXEC(rx, s, strend, orig, 0, TARG, NULL, r_flags))
+    if (!CALLREGEXEC(rx, orig, strend, orig, 0, TARG, NULL, r_flags))
     {
        SPAGAIN;
        PUSHs(rpm->op_pmflags & PMf_NONDESTRUCT ? TARG : &PL_sv_no);
        LEAVE_SCOPE(oldsave);
        RETURN;
     }
-    s = RX_OFFS(rx)[0].start + orig;
-
     PL_curpm = pm;
 
     /* known replacement string? */
@@ -2184,13 +2180,14 @@ PP(pp_subst)
        }
 
        if (once) {
-            char *d;
+            char *d, *m;
            if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */
                rxtainted |= SUBST_TAINT_PAT;
            m = orig + RX_OFFS(rx)[0].start;
            d = orig + RX_OFFS(rx)[0].end;
            s = orig;
            if (m - s > strend - d) {  /* faster to shorten from end */
+                I32 i;
                if (clen) {
                    Copy(c, m, clen, char);
                    m += clen;
@@ -2203,28 +2200,23 @@ PP(pp_subst)
                *m = '\0';
                SvCUR_set(TARG, m - s);
            }
-           else if ((i = m - s)) {     /* faster from front */
+           else {      /* faster from front */
+                I32 i = m - s;
                d -= clen;
-               m = d;
-               Move(s, d - i, i, char);
+                if (i > 0)
+                    Move(s, d - i, i, char);
                sv_chop(TARG, d-i);
                if (clen)
-                   Copy(c, m, clen, char);
-           }
-           else if (clen) {
-               d -= clen;
-               sv_chop(TARG, d);
-               Copy(c, d, clen, char);
-           }
-           else {
-               sv_chop(TARG, d);
+                   Copy(c, d, clen, char);
            }
            SPAGAIN;
            PUSHs(&PL_sv_yes);
        }
        else {
-            char *d = s;
+            char *d, *m;
+            d = s = RX_OFFS(rx)[0].start + orig;
            do {
+                I32 i;
                if (iters++ > maxiters)
                    DIE(aTHX_ "Substitution loop");
                if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */
@@ -2243,9 +2235,9 @@ PP(pp_subst)
            } while (CALLREGEXEC(rx, s, strend, orig, s == m,
                                 TARG, NULL,
                                 /* don't match same null twice */
-                                REXEC_NOT_FIRST|REXEC_IGNOREPOS));
+                     REXEC_NOT_FIRST|REXEC_IGNOREPOS|REXEC_FAIL_ON_UNDERFLOW));
            if (s != d) {
-               i = strend - s;
+                I32 i = strend - s;
                SvCUR_set(TARG, d - SvPVX_const(TARG) + i);
                Move(s, d, i+1, char);          /* include the NUL */
            }
@@ -2255,6 +2247,7 @@ PP(pp_subst)
     }
     else {
        bool first;
+        char *m;
        SV *repl;
        if (force_on_match) {
             /* redo the first match, this time with the orig var
@@ -2277,10 +2270,13 @@ PP(pp_subst)
        if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */
            rxtainted |= SUBST_TAINT_PAT;
        repl = dstr;
-       dstr = newSVpvn_flags(m, s-m, SVs_TEMP | (DO_UTF8(TARG) ? SVf_UTF8 : 0));
+        s = RX_OFFS(rx)[0].start + orig;
+       dstr = newSVpvn_flags(orig, s-orig,
+                    SVs_TEMP | (DO_UTF8(TARG) ? SVf_UTF8 : 0));
        if (!c) {
            PERL_CONTEXT *cx;
            SPAGAIN;
+            m = orig;
            /* note that a whole bunch of local vars are saved here for
             * use by pp_substcont: here's a list of them in case you're
             * searching for places in this sub that uses a particular var:
@@ -2289,7 +2285,6 @@ PP(pp_subst)
            PUSHSUBST(cx);
            RETURNOP(cPMOP->op_pmreplrootu.op_pmreplroot);
        }
-       r_flags |= REXEC_IGNOREPOS | REXEC_NOT_FIRST;
        first = TRUE;
        do {
            if (iters++ > maxiters)
@@ -2297,12 +2292,13 @@ PP(pp_subst)
            if (RX_MATCH_TAINTED(rx))
                rxtainted |= SUBST_TAINT_PAT;
            if (RX_MATCH_COPIED(rx) && RX_SUBBEG(rx) != orig) {
-               m = s;
-               s = orig;
+               char *old_s    = s;
+               char *old_orig = orig;
                 assert(RX_SUBOFFSET(rx) == 0);
+
                orig = RX_SUBBEG(rx);
-               s = orig + (m - s);
-               strend = s + (strend - m);
+               s = orig + (old_s - old_orig);
+               strend = s + (strend - old_s);
            }
            m = RX_OFFS(rx)[0].start + orig;
            sv_catpvn_nomg_maybeutf8(dstr, s, m - s, DO_UTF8(TARG));
@@ -2327,7 +2323,8 @@ PP(pp_subst)
            if (once)
                break;
        } while (CALLREGEXEC(rx, s, strend, orig, s == m,
-                            TARG, NULL, r_flags));
+                            TARG, NULL,
+                    REXEC_NOT_FIRST|REXEC_IGNOREPOS|REXEC_FAIL_ON_UNDERFLOW));
        sv_catpvn_nomg_maybeutf8(dstr, s, strend - s, DO_UTF8(TARG));
 
        if (rpm->op_pmflags & PMf_NONDESTRUCT) {