move intuit call from pp_match() into regexec()
authorDavid Mitchell <davem@iabyn.com>
Tue, 18 Jun 2013 13:44:12 +0000 (14:44 +0100)
committerDavid Mitchell <davem@iabyn.com>
Sun, 28 Jul 2013 09:33:35 +0000 (10:33 +0100)
Currently the main part of pp_match() looks like:

    if (can_use_intuit) {
        if (!intuit_start())
            goto nope;
        if (can_match_based_only_on_intuit_result) {
            ... set up $&, $-[0] etc ...
            goto gotcha;
        }
    }
    if (!regexec(..., REXEC_CHECKED|r_flags))
        goto nope;

  gotcha:
    ...

This rather breaks the regex API encapulation. The caller of the regex
engine shouldn't have to worry about whether to call intuit() or
regexec(), and to know to set $& in the intuit-only case.

So, move all the intuit-calling and $& setting into regexec itself.
This is cleaner, and will also shortly allow us to enable intuit-only
matches in pp_subst() too. After this change, the code above looks like
(in its entirety):

    if (!regexec(..., r_flags))
        goto nope;

    ...

There, isn't that nicer?

pp_hot.c
regexec.c

index 9994280..ddb0acd 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1324,7 +1324,7 @@ PP(pp_match)
     const char *s;
     const char *strend;
     I32 global;
-    U8 r_flags = REXEC_CHECKED;
+    U8 r_flags = 0;
     const char *truebase;                      /* Start of string  */
     REGEXP *rx = PM_GETRE(pm);
     bool rxtainted;
@@ -1432,40 +1432,11 @@ PP(pp_match)
        if (update_minmatch++)
            minmatch = had_zerolen;
     }
-    if (RX_EXTFLAGS(rx) & RXf_USE_INTUIT) {
-       s = CALLREG_INTUIT_START(rx, TARG, truebase,
-                        (char *)s, (char *)strend, r_flags, NULL);
 
-       if (!s)
-           goto nope;
-       if (RX_EXTFLAGS(rx) & RXf_CHECK_ALL) {
-            /* we can match based purely on the result of INTUIT.
-             * Fix up all the things that won't get set because we skip
-             * calling regexec() */
-            assert(!RX_NPARENS(rx));
-            /* match via INTUIT shouldn't have any captures.
-             * Let @-, @+, $^N know */
-            RX_LASTPAREN(rx) = RX_LASTCLOSEPAREN(rx) = 0;
-            RX_MATCH_UTF8_set(rx, cBOOL(DO_UTF8(TARG)));
-            if ( !(r_flags & REXEC_NOT_FIRST) )
-                Perl_reg_set_capture_string(aTHX_ rx,
-                                        (char*)truebase, (char *)strend,
-                                        TARG, r_flags, cBOOL(DO_UTF8(TARG)));
-
-            /* skipping regexec means that indices for $&, $-[0] etc not set */
-            RX_OFFS(rx)[0].start = s - truebase;
-            RX_OFFS(rx)[0].end =
-                RX_MATCH_UTF8(rx)
-                    ? (char*)utf8_hop((U8*)s, RX_MINLENRET(rx)) - truebase
-                    : s - truebase + RX_MINLENRET(rx);
-           goto gotcha;
-        }
-    }
     if (!CALLREGEXEC(rx, (char*)s, (char *)strend, (char*)truebase,
                     minmatch, TARG, NUM2PTR(void*, gpos), r_flags))
        goto nope;
 
-  gotcha:
     PL_curpm = pm;
     if (dynpm->op_pmflags & PMf_ONCE) {
 #ifdef USE_ITHREADS
index dc4d288..5a06f3b 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -2234,6 +2234,36 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend,
         "Matching");
     );
 
+    if ((RX_EXTFLAGS(rx) & RXf_USE_INTUIT)
+        && !(flags & REXEC_CHECKED))
+    {
+       stringarg = re_intuit_start(rx, sv, strbeg, stringarg, strend,
+                                    flags, NULL);
+       if (!stringarg)
+           return 0;
+
+       if (RX_EXTFLAGS(rx) & RXf_CHECK_ALL) {
+            /* we can match based purely on the result of INTUIT.
+             * Set up captures etc just for $& and $-[0]
+             * (an intuit-only match wont have $1,$2,..) */
+            assert(!prog->nparens);
+            /* match via INTUIT shouldn't have any captures.
+             * Let @-, @+, $^N know */
+            prog->lastparen = prog->lastcloseparen = 0;
+            RX_MATCH_UTF8_set(rx, utf8_target);
+            if ( !(flags & REXEC_NOT_FIRST) )
+                Perl_reg_set_capture_string(aTHX_ rx,
+                                        strbeg, strend,
+                                        sv, flags, utf8_target);
+
+            prog->offs[0].start = stringarg - strbeg;
+            prog->offs[0].end = utf8_target
+                ? (char*)utf8_hop((U8*)stringarg, prog->minlenret) - strbeg
+                : stringarg - strbeg + prog->minlenret;
+           return 1;
+        }
+    }
+
 
     /* at the end of this function, we'll do a LEAVE_SCOPE(oldsave),
      * which will call destuctors to reset PL_regmatch_state, free higher