This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
'Unknown PerlIO layer "encoding"...' message
[perl5.git] / regexec.c
index bd061fd..b9ac0a8 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -56,7 +56,7 @@
  ****    Alterations to Henry's code are...
  ****
  ****    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
  ****    Alterations to Henry's code are...
  ****
  ****    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- ****    2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
+ ****    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by Larry Wall and others
  ****
  ****    You may distribute under the terms of either the GNU General Public
  ****    License or the Artistic License, as specified in the README file.
  ****
  ****    You may distribute under the terms of either the GNU General Public
  ****    License or the Artistic License, as specified in the README file.
 /* TODO: Combine JUMPABLE and HAS_TEXT to cache OP(rn) */
 
 /* for use after a quantifier and before an EXACT-like node -- japhy */
 /* TODO: Combine JUMPABLE and HAS_TEXT to cache OP(rn) */
 
 /* for use after a quantifier and before an EXACT-like node -- japhy */
-#define JUMPABLE(rn) ( \
-    OP(rn) == OPEN || OP(rn) == CLOSE || OP(rn) == EVAL || \
+/* it would be nice to rework regcomp.sym to generate this stuff. sigh */
+#define JUMPABLE(rn) (      \
+    OP(rn) == OPEN ||       \
+    (OP(rn) == CLOSE && (!cur_eval || cur_eval->u.eval.close_paren != ARG(rn))) || \
+    OP(rn) == EVAL ||   \
     OP(rn) == SUSPEND || OP(rn) == IFMATCH || \
     OP(rn) == PLUS || OP(rn) == MINMOD || \
     OP(rn) == SUSPEND || OP(rn) == IFMATCH || \
     OP(rn) == PLUS || OP(rn) == MINMOD || \
+    OP(rn) == KEEPS || (PL_regkind[OP(rn)] == VERB) || \
     (PL_regkind[OP(rn)] == CURLY && ARG1(rn) > 0) \
 )
     (PL_regkind[OP(rn)] == CURLY && ARG1(rn) > 0) \
 )
+#define IS_EXACT(rn) (PL_regkind[OP(rn)] == EXACT)
 
 
-#define HAS_TEXT(rn) ( \
-    PL_regkind[OP(rn)] == EXACT || PL_regkind[OP(rn)] == REF \
-)
+#define HAS_TEXT(rn) ( IS_EXACT(rn) || PL_regkind[OP(rn)] == REF )
+
+#if 0 
+/* Currently these are only used when PL_regkind[OP(rn)] == EXACT so
+   we don't need this definition. */
+#define IS_TEXT(rn)   ( OP(rn)==EXACT   || OP(rn)==REF   || OP(rn)==NREF   )
+#define IS_TEXTF(rn)  ( OP(rn)==EXACTF  || OP(rn)==REFF  || OP(rn)==NREFF  )
+#define IS_TEXTFL(rn) ( OP(rn)==EXACTFL || OP(rn)==REFFL || OP(rn)==NREFFL )
+
+#else
+/* ... so we use this as its faster. */
+#define IS_TEXT(rn)   ( OP(rn)==EXACT   )
+#define IS_TEXTF(rn)  ( OP(rn)==EXACTF  )
+#define IS_TEXTFL(rn) ( OP(rn)==EXACTFL )
+
+#endif
 
 /*
   Search for mandatory following text node; for lookahead, the text must
 
 /*
   Search for mandatory following text node; for lookahead, the text must
@@ -168,13 +186,14 @@ S_regcppush(pTHX_ I32 parenfloor)
 
 #define REGCP_OTHER_ELEMS 8
     SSGROW(paren_elems_to_push + REGCP_OTHER_ELEMS);
 
 #define REGCP_OTHER_ELEMS 8
     SSGROW(paren_elems_to_push + REGCP_OTHER_ELEMS);
+    
     for (p = PL_regsize; p > parenfloor; p--) {
 /* REGCP_PARENS_ELEMS are pushed per pairs of parentheses. */
        SSPUSHINT(PL_regendp[p]);
        SSPUSHINT(PL_regstartp[p]);
        SSPUSHPTR(PL_reg_start_tmp[p]);
        SSPUSHINT(p);
     for (p = PL_regsize; p > parenfloor; p--) {
 /* REGCP_PARENS_ELEMS are pushed per pairs of parentheses. */
        SSPUSHINT(PL_regendp[p]);
        SSPUSHINT(PL_regstartp[p]);
        SSPUSHPTR(PL_reg_start_tmp[p]);
        SSPUSHINT(p);
-       DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log,
+       DEBUG_BUFFERS_r(PerlIO_printf(Perl_debug_log,
          "     saving \\%"UVuf" %"IVdf"(%"IVdf")..%"IVdf"\n",
                      (UV)p, (IV)PL_regstartp[p],
                      (IV)(PL_reg_start_tmp[p] - PL_bostr),
          "     saving \\%"UVuf" %"IVdf"(%"IVdf")..%"IVdf"\n",
                      (UV)p, (IV)PL_regstartp[p],
                      (IV)(PL_reg_start_tmp[p] - PL_bostr),
@@ -217,7 +236,7 @@ STATIC char *
 S_regcppop(pTHX_ const regexp *rex)
 {
     dVAR;
 S_regcppop(pTHX_ const regexp *rex)
 {
     dVAR;
-    I32 i;
+    U32 i;
     char *input;
 
     GET_RE_DEBUG_FLAGS_DECL;
     char *input;
 
     GET_RE_DEBUG_FLAGS_DECL;
@@ -244,7 +263,7 @@ S_regcppop(pTHX_ const regexp *rex)
        tmps = SSPOPINT;
        if (paren <= *PL_reglastparen)
            PL_regendp[paren] = tmps;
        tmps = SSPOPINT;
        if (paren <= *PL_reglastparen)
            PL_regendp[paren] = tmps;
-       DEBUG_EXECUTE_r(
+       DEBUG_BUFFERS_r(
            PerlIO_printf(Perl_debug_log,
                          "     restoring \\%"UVuf" to %"IVdf"(%"IVdf")..%"IVdf"%s\n",
                          (UV)paren, (IV)PL_regstartp[paren],
            PerlIO_printf(Perl_debug_log,
                          "     restoring \\%"UVuf" to %"IVdf"(%"IVdf")..%"IVdf"%s\n",
                          (UV)paren, (IV)PL_regstartp[paren],
@@ -253,7 +272,7 @@ S_regcppop(pTHX_ const regexp *rex)
                          (paren > *PL_reglastparen ? "(no)" : ""));
        );
     }
                          (paren > *PL_reglastparen ? "(no)" : ""));
        );
     }
-    DEBUG_EXECUTE_r(
+    DEBUG_BUFFERS_r(
        if (*PL_reglastparen + 1 <= rex->nparens) {
            PerlIO_printf(Perl_debug_log,
                          "     restoring \\%"IVdf"..\\%"IVdf" to undef\n",
        if (*PL_reglastparen + 1 <= rex->nparens) {
            PerlIO_printf(Perl_debug_log,
                          "     restoring \\%"IVdf"..\\%"IVdf" to undef\n",
@@ -271,7 +290,7 @@ S_regcppop(pTHX_ const regexp *rex)
      * building DynaLoader will fail:
      * "Error: '*' not in typemap in DynaLoader.xs, line 164"
      * --jhi */
      * building DynaLoader will fail:
      * "Error: '*' not in typemap in DynaLoader.xs, line 164"
      * --jhi */
-    for (i = *PL_reglastparen + 1; (U32)i <= rex->nparens; i++) {
+    for (i = *PL_reglastparen + 1; i <= rex->nparens; i++) {
        if (i > PL_regsize)
            PL_regstartp[i] = -1;
        PL_regendp[i] = -1;
        if (i > PL_regsize)
            PL_regstartp[i] = -1;
        PL_regendp[i] = -1;
@@ -330,7 +349,11 @@ Perl_pregexec(pTHX_ register regexp *prog, char *stringarg, register char *stren
        RExen without fixed substrings.  Similarly, it is assumed that
        lengths of all the strings are no more than minlen, thus they
        cannot come from lookahead.
        RExen without fixed substrings.  Similarly, it is assumed that
        lengths of all the strings are no more than minlen, thus they
        cannot come from lookahead.
-       (Or minlen should take into account lookahead.) */
+       (Or minlen should take into account lookahead.) 
+  NOTE: Some of this comment is not correct. minlen does now take account
+  of lookahead/behind. Further research is required. -- demerphq
+
+*/
 
 /* A failure to find a constant substring means that there is no need to make
    an expensive call to REx engine, thus we celebrate a failure.  Similarly,
 
 /* A failure to find a constant substring means that there is no need to make
    an expensive call to REx engine, thus we celebrate a failure.  Similarly,
@@ -366,7 +389,8 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
     I32 ml_anch;
     register char *other_last = NULL;  /* other substr checked before this */
     char *check_at = NULL;             /* check substr found at this pos */
     I32 ml_anch;
     register char *other_last = NULL;  /* other substr checked before this */
     char *check_at = NULL;             /* check substr found at this pos */
-    const I32 multiline = prog->reganch & PMf_MULTILINE;
+    const I32 multiline = prog->extflags & RXf_PMf_MULTILINE;
+    RXi_GET_DECL(prog,progi);
 #ifdef DEBUGGING
     const char * const i_strpos = strpos;
 #endif
 #ifdef DEBUGGING
     const char * const i_strpos = strpos;
 #endif
@@ -375,7 +399,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
 
     RX_MATCH_UTF8_set(prog,do_utf8);
 
 
     RX_MATCH_UTF8_set(prog,do_utf8);
 
-    if (prog->reganch & ROPT_UTF8) {
+    if (prog->extflags & RXf_UTF8) {
        PL_reg_flags |= RF_utf8;
     }
     DEBUG_EXECUTE_r( 
        PL_reg_flags |= RF_utf8;
     }
     DEBUG_EXECUTE_r( 
@@ -407,14 +431,14 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
                "Non-utf8 string cannot match utf8 check string\n"));
        goto fail;
     }
                "Non-utf8 string cannot match utf8 check string\n"));
        goto fail;
     }
-    if (prog->reganch & ROPT_ANCH) {   /* Match at beg-of-str or after \n */
-       ml_anch = !( (prog->reganch & ROPT_ANCH_SINGLE)
-                    || ( (prog->reganch & ROPT_ANCH_BOL)
+    if (prog->extflags & RXf_ANCH) {   /* Match at beg-of-str or after \n */
+       ml_anch = !( (prog->extflags & RXf_ANCH_SINGLE)
+                    || ( (prog->extflags & RXf_ANCH_BOL)
                          && !multiline ) );    /* Check after \n? */
 
        if (!ml_anch) {
                          && !multiline ) );    /* Check after \n? */
 
        if (!ml_anch) {
-         if ( !(prog->reganch & (ROPT_ANCH_GPOS /* Checked by the caller */
-                                 | ROPT_IMPLICIT)) /* not a real BOL */
+         if ( !(prog->extflags & RXf_ANCH_GPOS) /* Checked by the caller */
+               && !(prog->intflags & PREGf_IMPLICIT) /* not a real BOL */
               /* SvCUR is not set on references: SvRV and SvPVX_const overlap */
               && sv && !SvROK(sv)
               && (strpos != strbeg)) {
               /* SvCUR is not set on references: SvRV and SvPVX_const overlap */
               && sv && !SvROK(sv)
               && (strpos != strbeg)) {
@@ -422,7 +446,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
              goto fail;
          }
          if (prog->check_offset_min == prog->check_offset_max &&
              goto fail;
          }
          if (prog->check_offset_min == prog->check_offset_max &&
-             !(prog->reganch & ROPT_CANY_SEEN)) {
+             !(prog->extflags & RXf_CANY_SEEN)) {
            /* Substring at constant offset from beg-of-str... */
            I32 slen;
 
            /* Substring at constant offset from beg-of-str... */
            I32 slen;
 
@@ -477,7 +501,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
        /* end shift should be non negative here */
     }
 
        /* end shift should be non negative here */
     }
 
-#ifdef DEBUGGING       /* 7/99: reports of failure (with the older version) */
+#ifdef QDEBUGGING      /* 7/99: reports of failure (with the older version) */
     if (end_shift < 0)
        Perl_croak(aTHX_ "panic: end_shift: %"IVdf" pattern:\n%s\n ",
                   (IV)end_shift, prog->precomp);
     if (end_shift < 0)
        Perl_croak(aTHX_ "panic: end_shift: %"IVdf" pattern:\n%s\n ",
                   (IV)end_shift, prog->precomp);
@@ -523,7 +547,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
     else {
         U8* start_point;
         U8* end_point;
     else {
         U8* start_point;
         U8* end_point;
-        if (prog->reganch & ROPT_CANY_SEEN) {
+        if (prog->extflags & RXf_CANY_SEEN) {
             start_point= (U8*)(s + srch_start_shift);
             end_point= (U8*)(strend - srch_end_shift);
         } else {
             start_point= (U8*)(s + srch_start_shift);
             end_point= (U8*)(strend - srch_end_shift);
         } else {
@@ -809,17 +833,17 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
        if (ml_anch && sv && !SvROK(sv) /* See prev comment on SvROK */
            && (strpos != strbeg) && strpos[-1] != '\n'
            /* May be due to an implicit anchor of m{.*foo}  */
        if (ml_anch && sv && !SvROK(sv) /* See prev comment on SvROK */
            && (strpos != strbeg) && strpos[-1] != '\n'
            /* May be due to an implicit anchor of m{.*foo}  */
-           && !(prog->reganch & ROPT_IMPLICIT))
+           && !(prog->intflags & PREGf_IMPLICIT))
        {
            t = strpos;
            goto find_anchor;
        }
        DEBUG_EXECUTE_r( if (ml_anch)
            PerlIO_printf(Perl_debug_log, "Position at offset %ld does not contradict /%s^%s/m...\n",
        {
            t = strpos;
            goto find_anchor;
        }
        DEBUG_EXECUTE_r( if (ml_anch)
            PerlIO_printf(Perl_debug_log, "Position at offset %ld does not contradict /%s^%s/m...\n",
-                       (long)(strpos - i_strpos), PL_colors[0], PL_colors[1]);
+                         (long)(strpos - i_strpos), PL_colors[0], PL_colors[1]);
        );
       success_at_start:
        );
       success_at_start:
-       if (!(prog->reganch & ROPT_NAUGHTY)     /* XXXX If strpos moved? */
+       if (!(prog->intflags & PREGf_NAUGHTY)   /* XXXX If strpos moved? */
            && (do_utf8 ? (
                prog->check_utf8                /* Could be deleted already */
                && --BmUSEFUL(prog->check_utf8) < 0
            && (do_utf8 ? (
                prog->check_utf8                /* Could be deleted already */
                && --BmUSEFUL(prog->check_utf8) < 0
@@ -842,7 +866,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
            /* XXXX This is a remnant of the old implementation.  It
                    looks wasteful, since now INTUIT can use many
                    other heuristics. */
            /* XXXX This is a remnant of the old implementation.  It
                    looks wasteful, since now INTUIT can use many
                    other heuristics. */
-           prog->reganch &= ~RE_USE_INTUIT;
+           prog->extflags &= ~RXf_USE_INTUIT;
        }
        else
            s = strpos;
        }
        else
            s = strpos;
@@ -852,7 +876,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
     /* XXXX BmUSEFUL already changed, maybe multiple change is meaningful... */
     /* trie stclasses are too expensive to use here, we are better off to
        leave it to regmatch itself */
     /* XXXX BmUSEFUL already changed, maybe multiple change is meaningful... */
     /* trie stclasses are too expensive to use here, we are better off to
        leave it to regmatch itself */
-    if (prog->regstclass && PL_regkind[OP(prog->regstclass)]!=TRIE) {
+    if (progi->regstclass && PL_regkind[OP(progi->regstclass)]!=TRIE) {
        /* minlen == 0 is possible if regstclass is \b or \B,
           and the fixed substr is ''$.
           Since minlen is already taken into account, s+1 is before strend;
        /* minlen == 0 is possible if regstclass is \b or \B,
           and the fixed substr is ''$.
           Since minlen is already taken into account, s+1 is before strend;
@@ -861,9 +885,9 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
           regstclass does not come from lookahead...  */
        /* If regstclass takes bytelength more than 1: If charlength==1, OK.
           This leaves EXACTF only, which is dealt with in find_byclass().  */
           regstclass does not come from lookahead...  */
        /* If regstclass takes bytelength more than 1: If charlength==1, OK.
           This leaves EXACTF only, which is dealt with in find_byclass().  */
-        const U8* const str = (U8*)STRING(prog->regstclass);
-        const int cl_l = (PL_regkind[OP(prog->regstclass)] == EXACT
-                   ? CHR_DIST(str+STR_LEN(prog->regstclass), str)
+        const U8* const str = (U8*)STRING(progi->regstclass);
+        const int cl_l = (PL_regkind[OP(progi->regstclass)] == EXACT
+                   ? CHR_DIST(str+STR_LEN(progi->regstclass), str)
                    : 1);
        char * endpos;
        if (prog->anchored_substr || prog->anchored_utf8 || ml_anch)
                    : 1);
        char * endpos;
        if (prog->anchored_substr || prog->anchored_utf8 || ml_anch)
@@ -873,11 +897,11 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
         else 
             endpos= strend;
                    
         else 
             endpos= strend;
                    
-        DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log, "start_shift: %"IVdf" check_at: %d s: %d endpos: %d\n",
-                                     (IV)start_shift, check_at - strbeg, s - strbeg, endpos - strbeg));
+        DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log, "start_shift: %"IVdf" check_at: %"IVdf" s: %"IVdf" endpos: %"IVdf"\n",
+                                     (IV)start_shift, (IV)(check_at - strbeg), (IV)(s - strbeg), (IV)(endpos - strbeg)));
        
        t = s;
        
        t = s;
-        s = find_byclass(prog, prog->regstclass, s, endpos, NULL);
+        s = find_byclass(prog, progi->regstclass, s, endpos, NULL);
        if (!s) {
 #ifdef DEBUGGING
            const char *what = NULL;
        if (!s) {
 #ifdef DEBUGGING
            const char *what = NULL;
@@ -889,7 +913,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
            }
            DEBUG_EXECUTE_r( PerlIO_printf(Perl_debug_log,
                                   "This position contradicts STCLASS...\n") );
            }
            DEBUG_EXECUTE_r( PerlIO_printf(Perl_debug_log,
                                   "This position contradicts STCLASS...\n") );
-           if ((prog->reganch & ROPT_ANCH) && !ml_anch)
+           if ((prog->extflags & RXf_ANCH) && !ml_anch)
                goto fail;
            /* Contradict one of substrings */
            if (prog->anchored_substr || prog->anchored_utf8) {
                goto fail;
            /* Contradict one of substrings */
            if (prog->anchored_substr || prog->anchored_utf8) {
@@ -970,8 +994,8 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
 
 
 
 
 
 
-#define REXEC_TRIE_READ_CHAR(trie_type, trie, uc, uscan, len, uvc, charid,  \
-foldlen, foldbuf, uniflags) STMT_START {                                    \
+#define REXEC_TRIE_READ_CHAR(trie_type, trie, widecharmap, uc, uscan, len,  \
+uvc, charid, foldlen, foldbuf, uniflags) STMT_START {                       \
     switch (trie_type) {                                                    \
     case trie_utf8_fold:                                                    \
        if ( foldlen>0 ) {                                                  \
     switch (trie_type) {                                                    \
     case trie_utf8_fold:                                                    \
        if ( foldlen>0 ) {                                                  \
@@ -999,8 +1023,8 @@ foldlen, foldbuf, uniflags) STMT_START {                                    \
     }                                                                       \
     else {                                                                  \
        charid = 0;                                                         \
     }                                                                       \
     else {                                                                  \
        charid = 0;                                                         \
-       if (trie->widecharmap) {                                            \
-           SV** const svpp = hv_fetch(trie->widecharmap,                   \
+       if (widecharmap) {                                                  \
+           SV** const svpp = hv_fetch(widecharmap,                         \
                        (char*)&uvc, sizeof(UV), 0);                        \
            if (svpp)                                                       \
                charid = (U16)SvIV(*svpp);                                  \
                        (char*)&uvc, sizeof(UV), 0);                        \
            if (svpp)                                                       \
                charid = (U16)SvIV(*svpp);                                  \
@@ -1013,7 +1037,7 @@ foldlen, foldbuf, uniflags) STMT_START {                                    \
         && (ln == len ||                              \
             ibcmp_utf8(s, NULL, 0,  do_utf8,          \
                        m, NULL, ln, (bool)UTF))       \
         && (ln == len ||                              \
             ibcmp_utf8(s, NULL, 0,  do_utf8,          \
                        m, NULL, ln, (bool)UTF))       \
-        && (!reginfo || regtry(reginfo, s)) )         \
+        && (!reginfo || regtry(reginfo, &s)) )         \
        goto got_it;                                   \
     else {                                             \
         U8 foldbuf[UTF8_MAXBYTES_CASE+1];             \
        goto got_it;                                   \
     else {                                             \
         U8 foldbuf[UTF8_MAXBYTES_CASE+1];             \
@@ -1026,7 +1050,7 @@ foldlen, foldbuf, uniflags) STMT_START {                                    \
                              NULL, foldlen, do_utf8,  \
                              m,                       \
                              NULL, ln, (bool)UTF))    \
                              NULL, foldlen, do_utf8,  \
                              m,                       \
                              NULL, ln, (bool)UTF))    \
-             && (!reginfo || regtry(reginfo, s)) )    \
+             && (!reginfo || regtry(reginfo, &s)) )    \
              goto got_it;                             \
     }                                                  \
     s += len
              goto got_it;                             \
     }                                                  \
     s += len
@@ -1038,7 +1062,7 @@ STMT_START {                                              \
             && (ln == 1 || !(OP(c) == EXACTF             \
                              ? ibcmp(s, m, ln)           \
                              : ibcmp_locale(s, m, ln)))  \
             && (ln == 1 || !(OP(c) == EXACTF             \
                              ? ibcmp(s, m, ln)           \
                              : ibcmp_locale(s, m, ln)))  \
-            && (!reginfo || regtry(reginfo, s)) )        \
+            && (!reginfo || regtry(reginfo, &s)) )        \
            goto got_it;                                  \
        s++;                                              \
     }                                                     \
            goto got_it;                                  \
        s++;                                              \
     }                                                     \
@@ -1063,7 +1087,7 @@ STMT_START {                                          \
 #define REXEC_FBC_UTF8_CLASS_SCAN(CoNd)               \
 REXEC_FBC_UTF8_SCAN(                                  \
     if (CoNd) {                                       \
 #define REXEC_FBC_UTF8_CLASS_SCAN(CoNd)               \
 REXEC_FBC_UTF8_SCAN(                                  \
     if (CoNd) {                                       \
-       if (tmp && (!reginfo || regtry(reginfo, s)))  \
+       if (tmp && (!reginfo || regtry(reginfo, &s)))  \
            goto got_it;                              \
        else                                          \
            tmp = doevery;                            \
            goto got_it;                              \
        else                                          \
            tmp = doevery;                            \
@@ -1075,7 +1099,7 @@ REXEC_FBC_UTF8_SCAN(                                  \
 #define REXEC_FBC_CLASS_SCAN(CoNd)                    \
 REXEC_FBC_SCAN(                                       \
     if (CoNd) {                                       \
 #define REXEC_FBC_CLASS_SCAN(CoNd)                    \
 REXEC_FBC_SCAN(                                       \
     if (CoNd) {                                       \
-       if (tmp && (!reginfo || regtry(reginfo, s)))  \
+       if (tmp && (!reginfo || regtry(reginfo, &s)))  \
            goto got_it;                              \
        else                                          \
            tmp = doevery;                            \
            goto got_it;                              \
        else                                          \
            tmp = doevery;                            \
@@ -1085,7 +1109,7 @@ REXEC_FBC_SCAN(                                       \
 )
 
 #define REXEC_FBC_TRYIT               \
 )
 
 #define REXEC_FBC_TRYIT               \
-if ((!reginfo || regtry(reginfo, s))) \
+if ((!reginfo || regtry(reginfo, &s))) \
     goto got_it
 
 #define REXEC_FBC_CSCAN_PRELOAD(UtFpReLoAd,CoNdUtF8,CoNd)      \
     goto got_it
 
 #define REXEC_FBC_CSCAN_PRELOAD(UtFpReLoAd,CoNdUtF8,CoNd)      \
@@ -1118,10 +1142,10 @@ if ((!reginfo || regtry(reginfo, s))) \
 
 STATIC char *
 S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, 
 
 STATIC char *
 S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, 
-    const char *strend, const regmatch_info *reginfo)
+    const char *strend, regmatch_info *reginfo)
 {
        dVAR;
 {
        dVAR;
-       const I32 doevery = (prog->reganch & ROPT_SKIP) == 0;
+       const I32 doevery = (prog->intflags & PREGf_SKIP) == 0;
        char *m;
        STRLEN ln;
        STRLEN lnc;
        char *m;
        STRLEN ln;
        STRLEN lnc;
@@ -1131,7 +1155,8 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
        char *e;
        register I32 tmp = 1;   /* Scratch variable? */
        register const bool do_utf8 = PL_reg_match_utf8;
        char *e;
        register I32 tmp = 1;   /* Scratch variable? */
        register const bool do_utf8 = PL_reg_match_utf8;
-
+        RXi_GET_DECL(prog,progi);
+        
        /* We know what class it must start with. */
        switch (OP(c)) {
        case ANYOF:
        /* We know what class it must start with. */
        switch (OP(c)) {
        case ANYOF:
@@ -1150,7 +1175,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
                           /* The assignment of 2 is intentional:
                            * for the folded sharp s, the skip is 2. */
                           (skip = SHARP_S_SKIP))) {
                           /* The assignment of 2 is intentional:
                            * for the folded sharp s, the skip is 2. */
                           (skip = SHARP_S_SKIP))) {
-                          if (tmp && (!reginfo || regtry(reginfo, s)))
+                          if (tmp && (!reginfo || regtry(reginfo, &s)))
                                goto got_it;
                           else
                                tmp = doevery;
                                goto got_it;
                           else
                                tmp = doevery;
@@ -1163,7 +1188,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
            break;
        case CANY:
            REXEC_FBC_SCAN(
            break;
        case CANY:
            REXEC_FBC_SCAN(
-               if (tmp && (!reginfo || regtry(reginfo, s)))
+               if (tmp && (!reginfo || regtry(reginfo, &s)))
                    goto got_it;
                else
                    tmp = doevery;
                    goto got_it;
                else
                    tmp = doevery;
@@ -1297,7 +1322,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
                }
                );
            }
                }
                );
            }
-           if ((!prog->minlen && tmp) && (!reginfo || regtry(reginfo, s)))
+           if ((!prog->minlen && tmp) && (!reginfo || regtry(reginfo, &s)))
                goto got_it;
            break;
        case NBOUNDL:
                goto got_it;
            break;
        case NBOUNDL:
@@ -1333,7 +1358,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
                    else REXEC_FBC_TRYIT;
                );
            }
                    else REXEC_FBC_TRYIT;
                );
            }
-           if ((!prog->minlen && !tmp) && (!reginfo || regtry(reginfo, s)))
+           if ((!prog->minlen && !tmp) && (!reginfo || regtry(reginfo, &s)))
                goto got_it;
            break;
        case ALNUM:
                goto got_it;
            break;
        case ALNUM:
@@ -1411,8 +1436,10 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
                        : trie_plain;
                 /* what trie are we using right now */
                reg_ac_data *aho
                        : trie_plain;
                 /* what trie are we using right now */
                reg_ac_data *aho
-                   = (reg_ac_data*)prog->data->data[ ARG( c ) ];
-               reg_trie_data *trie=aho->trie;
+                   = (reg_ac_data*)progi->data->data[ ARG( c ) ];
+               reg_trie_data *trie
+                   = (reg_trie_data*)progi->data->data[ aho->trie ];
+               HV *widecharmap = (HV*) progi->data->data[ aho->trie + 1 ];
 
                const char *last_start = strend - trie->minlen;
 #ifdef DEBUGGING
 
                const char *last_start = strend - trie->minlen;
 #ifdef DEBUGGING
@@ -1515,8 +1542,9 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
                             
                         }
                         points[pointpos++ % maxlen]= uc;
                             
                         }
                         points[pointpos++ % maxlen]= uc;
-                       REXEC_TRIE_READ_CHAR(trie_type, trie, uc, uscan, len,
-                           uvc, charid, foldlen, foldbuf, uniflags);
+                       REXEC_TRIE_READ_CHAR(trie_type, trie, widecharmap, uc,
+                                            uscan, len, uvc, charid, foldlen,
+                                            foldbuf, uniflags);
                         DEBUG_TRIE_EXECUTE_r({
                             dump_exec_pos( (char *)uc, c, strend, real_start, 
                                 s,   do_utf8 );
                         DEBUG_TRIE_EXECUTE_r({
                             dump_exec_pos( (char *)uc, c, strend, real_start, 
                                 s,   do_utf8 );
@@ -1589,11 +1617,11 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
                         s = (char*)leftmost;
                         DEBUG_TRIE_EXECUTE_r({
                             PerlIO_printf( 
                         s = (char*)leftmost;
                         DEBUG_TRIE_EXECUTE_r({
                             PerlIO_printf( 
-                                Perl_debug_log,"Matches word #%"UVxf" at position %d. Trying full pattern...\n",
-                                (UV)accepted_word, s - real_start
+                                Perl_debug_log,"Matches word #%"UVxf" at position %"IVdf". Trying full pattern...\n",
+                                (UV)accepted_word, (IV)(s - real_start)
                             );
                         });
                             );
                         });
-                        if (!reginfo || regtry(reginfo, s)) {
+                        if (!reginfo || regtry(reginfo, &s)) {
                             FREETMPS;
                            LEAVE;
                             goto got_it;
                             FREETMPS;
                            LEAVE;
                             goto got_it;
@@ -1621,6 +1649,33 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
        return s;
 }
 
        return s;
 }
 
+static void 
+S_swap_match_buff (pTHX_ regexp *prog) {
+    I32 *t;
+    RXi_GET_DECL(prog,progi);
+
+    if (!progi->swap) {
+    /* We have to be careful. If the previous successful match
+       was from this regex we don't want a subsequent paritally
+       successful match to clobber the old results. 
+       So when we detect this possibility we add a swap buffer
+       to the re, and switch the buffer each match. If we fail
+       we switch it back, otherwise we leave it swapped.
+    */
+        Newxz(progi->swap, 1, regexp_paren_ofs);
+        /* no need to copy these */
+        Newxz(progi->swap->startp, prog->nparens + 1, I32);
+        Newxz(progi->swap->endp, prog->nparens + 1, I32);
+    }
+    t = progi->swap->startp;
+    progi->swap->startp = prog->startp;
+    prog->startp = t;
+    t = progi->swap->endp;
+    progi->swap->endp = prog->endp;
+    prog->endp = t;
+}    
+
+
 /*
  - regexec_flags - match a regexp against a string
  */
 /*
  - regexec_flags - match a regexp against a string
  */
@@ -1630,13 +1685,15 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
 /* strend: pointer to null at end of string */
 /* strbeg: real beginning of string */
 /* minend: end of match must be >=minend after stringarg. */
 /* strend: pointer to null at end of string */
 /* strbeg: real beginning of string */
 /* minend: end of match must be >=minend after stringarg. */
-/* data: May be used for some additional optimizations. */
+/* data: May be used for some additional optimizations. 
+         Currently its only used, with a U32 cast, for transmitting 
+         the ganch offset when doing a /g match. This will change */
 /* nosave: For optimizations. */
 {
     dVAR;
 /* nosave: For optimizations. */
 {
     dVAR;
-    register char *s;
+    /*register*/ char *s;
     register regnode *c;
     register regnode *c;
-    register char *startpos = stringarg;
+    /*register*/ char *startpos = stringarg;
     I32 minlen;                /* must match at least this many chars */
     I32 dontbother = 0;        /* how many characters not to try at end */
     I32 end_shift = 0;                 /* Same for the end. */         /* CC */
     I32 minlen;                /* must match at least this many chars */
     I32 dontbother = 0;        /* how many characters not to try at end */
     I32 end_shift = 0;                 /* Same for the end. */         /* CC */
@@ -1645,8 +1702,9 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
     SV* const oreplsv = GvSV(PL_replgv);
     const bool do_utf8 = (bool)DO_UTF8(sv);
     I32 multiline;
     SV* const oreplsv = GvSV(PL_replgv);
     const bool do_utf8 = (bool)DO_UTF8(sv);
     I32 multiline;
-
+    RXi_GET_DECL(prog,progi);
     regmatch_info reginfo;  /* create some info to pass to regtry etc */
     regmatch_info reginfo;  /* create some info to pass to regtry etc */
+    bool swap_on_fail = 0;
 
     GET_RE_DEBUG_FLAGS_DECL;
 
 
     GET_RE_DEBUG_FLAGS_DECL;
 
@@ -1658,7 +1716,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
        return 0;
     }
 
        return 0;
     }
 
-    multiline = prog->reganch & PMf_MULTILINE;
+    multiline = prog->extflags & RXf_PMf_MULTILINE;
     reginfo.prog = prog;
 
     RX_MATCH_UTF8_set(prog, do_utf8);
     reginfo.prog = prog;
 
     RX_MATCH_UTF8_set(prog, do_utf8);
@@ -1677,7 +1735,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
 
     
     /* Check validity of program. */
 
     
     /* Check validity of program. */
-    if (UCHARAT(prog->program) != REG_MAGIC) {
+    if (UCHARAT(progi->program) != REG_MAGIC) {
        Perl_croak(aTHX_ "corrupted regexp program");
     }
 
        Perl_croak(aTHX_ "corrupted regexp program");
     }
 
@@ -1685,7 +1743,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
     PL_reg_eval_set = 0;
     PL_reg_maxiter = 0;
 
     PL_reg_eval_set = 0;
     PL_reg_maxiter = 0;
 
-    if (prog->reganch & ROPT_UTF8)
+    if (prog->extflags & RXf_UTF8)
        PL_reg_flags |= RF_utf8;
 
     /* Mark beginning of line for ^ and lookbehind. */
        PL_reg_flags |= RF_utf8;
 
     /* Mark beginning of line for ^ and lookbehind. */
@@ -1702,26 +1760,32 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
     /* If there is a "must appear" string, look for it. */
     s = startpos;
 
     /* If there is a "must appear" string, look for it. */
     s = startpos;
 
-    if (prog->reganch & ROPT_GPOS_SEEN) { /* Need to set reginfo->ganch */
+    if (prog->extflags & RXf_GPOS_SEEN) { /* Need to set reginfo->ganch */
        MAGIC *mg;
 
        if (flags & REXEC_IGNOREPOS)    /* Means: check only at start */
        MAGIC *mg;
 
        if (flags & REXEC_IGNOREPOS)    /* Means: check only at start */
-           reginfo.ganch = startpos;
+           reginfo.ganch = startpos + prog->gofs;
        else if (sv && SvTYPE(sv) >= SVt_PVMG
                  && SvMAGIC(sv)
                  && (mg = mg_find(sv, PERL_MAGIC_regex_global))
                  && mg->mg_len >= 0) {
            reginfo.ganch = strbeg + mg->mg_len;        /* Defined pos() */
        else if (sv && SvTYPE(sv) >= SVt_PVMG
                  && SvMAGIC(sv)
                  && (mg = mg_find(sv, PERL_MAGIC_regex_global))
                  && mg->mg_len >= 0) {
            reginfo.ganch = strbeg + mg->mg_len;        /* Defined pos() */
-           if (prog->reganch & ROPT_ANCH_GPOS) {
+           if (prog->extflags & RXf_ANCH_GPOS) {
                if (s > reginfo.ganch)
                    goto phooey;
                if (s > reginfo.ganch)
                    goto phooey;
-               s = reginfo.ganch;
+               s = reginfo.ganch - prog->gofs;
            }
        }
            }
        }
-       else                            /* pos() not defined */
+       else if (data) {
+           reginfo.ganch = strbeg + PTR2UV(data);
+       } else                          /* pos() not defined */
            reginfo.ganch = strbeg;
     }
            reginfo.ganch = strbeg;
     }
-
+    if (PL_curpm && (PM_GETRE(PL_curpm) == prog)) {
+        swap_on_fail = 1;
+        swap_match_buff(prog); /* do we need a save destructor here for
+                                  eval dies? */
+    }
     if (!(flags & REXEC_CHECKED) && (prog->check_substr != NULL || prog->check_utf8 != NULL)) {
        re_scream_pos_data d;
 
     if (!(flags & REXEC_CHECKED) && (prog->check_substr != NULL || prog->check_utf8 != NULL)) {
        re_scream_pos_data d;
 
@@ -1738,11 +1802,11 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
 
     /* Simplest case:  anchored match need be tried only once. */
     /*  [unless only anchor is BOL and multiline is set] */
 
     /* Simplest case:  anchored match need be tried only once. */
     /*  [unless only anchor is BOL and multiline is set] */
-    if (prog->reganch & (ROPT_ANCH & ~ROPT_ANCH_GPOS)) {
-       if (s == startpos && regtry(&reginfo, startpos))
+    if (prog->extflags & (RXf_ANCH & ~RXf_ANCH_GPOS)) {
+       if (s == startpos && regtry(&reginfo, &startpos))
            goto got_it;
            goto got_it;
-       else if (multiline || (prog->reganch & ROPT_IMPLICIT)
-                || (prog->reganch & ROPT_ANCH_MBOL)) /* XXXX SBOL? */
+       else if (multiline || (prog->intflags & PREGf_IMPLICIT)
+                || (prog->extflags & RXf_ANCH_MBOL)) /* XXXX SBOL? */
        {
            char *end;
 
        {
            char *end;
 
@@ -1754,12 +1818,12 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
                if (s == startpos)
                    goto after_try;
                while (1) {
                if (s == startpos)
                    goto after_try;
                while (1) {
-                   if (regtry(&reginfo, s))
+                   if (regtry(&reginfo, &s))
                        goto got_it;
                  after_try:
                    if (s >= end)
                        goto phooey;
                        goto got_it;
                  after_try:
                    if (s >= end)
                        goto phooey;
-                   if (prog->reganch & RE_USE_INTUIT) {
+                   if (prog->extflags & RXf_USE_INTUIT) {
                        s = re_intuit_start(prog, sv, s + 1, strend, flags, NULL);
                        if (!s)
                            goto phooey;
                        s = re_intuit_start(prog, sv, s + 1, strend, flags, NULL);
                        if (!s)
                            goto phooey;
@@ -1772,25 +1836,26 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
                    s--;
                while (s < end) {
                    if (*s++ == '\n') { /* don't need PL_utf8skip here */
                    s--;
                while (s < end) {
                    if (*s++ == '\n') { /* don't need PL_utf8skip here */
-                       if (regtry(&reginfo, s))
+                       if (regtry(&reginfo, &s))
                            goto got_it;
                    }
                }               
            }
        }
        goto phooey;
                            goto got_it;
                    }
                }               
            }
        }
        goto phooey;
-    } else if (ROPT_GPOS_CHECK == (prog->reganch & ROPT_GPOS_CHECK)) 
+    } else if (RXf_GPOS_CHECK == (prog->extflags & RXf_GPOS_CHECK)) 
     {
         /* the warning about reginfo.ganch being used without intialization
     {
         /* the warning about reginfo.ganch being used without intialization
-           is bogus -- we set it above, when prog->reganch & ROPT_GPOS_SEEN 
+           is bogus -- we set it above, when prog->extflags & RXf_GPOS_SEEN 
            and we only enter this block when the same bit is set. */
            and we only enter this block when the same bit is set. */
-       if (regtry(&reginfo, reginfo.ganch))
+        char *tmp_s = reginfo.ganch - prog->gofs;
+       if (regtry(&reginfo, &tmp_s))
            goto got_it;
        goto phooey;
     }
 
     /* Messy cases:  unanchored match. */
            goto got_it;
        goto phooey;
     }
 
     /* Messy cases:  unanchored match. */
-    if ((prog->anchored_substr || prog->anchored_utf8) && prog->reganch & ROPT_SKIP) {
+    if ((prog->anchored_substr || prog->anchored_utf8) && prog->intflags & PREGf_SKIP) {
        /* we have /x+whatever/ */
        /* it must be a one character string (XXXX Except UTF?) */
        char ch;
        /* we have /x+whatever/ */
        /* it must be a one character string (XXXX Except UTF?) */
        char ch;
@@ -1805,7 +1870,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
            REXEC_FBC_SCAN(
                if (*s == ch) {
                    DEBUG_EXECUTE_r( did_match = 1 );
            REXEC_FBC_SCAN(
                if (*s == ch) {
                    DEBUG_EXECUTE_r( did_match = 1 );
-                   if (regtry(&reginfo, s)) goto got_it;
+                   if (regtry(&reginfo, &s)) goto got_it;
                    s += UTF8SKIP(s);
                    while (s < strend && *s == ch)
                        s += UTF8SKIP(s);
                    s += UTF8SKIP(s);
                    while (s < strend && *s == ch)
                        s += UTF8SKIP(s);
@@ -1816,7 +1881,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
            REXEC_FBC_SCAN(
                if (*s == ch) {
                    DEBUG_EXECUTE_r( did_match = 1 );
            REXEC_FBC_SCAN(
                if (*s == ch) {
                    DEBUG_EXECUTE_r( did_match = 1 );
-                   if (regtry(&reginfo, s)) goto got_it;
+                   if (regtry(&reginfo, &s)) goto got_it;
                    s++;
                    while (s < strend && *s == ch)
                        s++;
                    s++;
                    while (s < strend && *s == ch)
                        s++;
@@ -1898,14 +1963,14 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
            }
            if (do_utf8) {
                while (s <= last1) {
            }
            if (do_utf8) {
                while (s <= last1) {
-                   if (regtry(&reginfo, s))
+                   if (regtry(&reginfo, &s))
                        goto got_it;
                    s += UTF8SKIP(s);
                }
            }
            else {
                while (s <= last1) {
                        goto got_it;
                    s += UTF8SKIP(s);
                }
            }
            else {
                while (s <= last1) {
-                   if (regtry(&reginfo, s))
+                   if (regtry(&reginfo, &s))
                        goto got_it;
                    s++;
                }
                        goto got_it;
                    s++;
                }
@@ -1921,9 +1986,9 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
         });                
        goto phooey;
     }
         });                
        goto phooey;
     }
-    else if ( (c = prog->regstclass) ) {
+    else if ( (c = progi->regstclass) ) {
        if (minlen) {
        if (minlen) {
-           const OPCODE op = OP(prog->regstclass);
+           const OPCODE op = OP(progi->regstclass);
            /* don't bother with what can't match */
            if (PL_regkind[op] != EXACT && op != CANY && PL_regkind[op] != TRIE)
                strend = HOPc(strend, -(minlen - 1));
            /* don't bother with what can't match */
            if (PL_regkind[op] != EXACT && op != CANY && PL_regkind[op] != TRIE)
                strend = HOPc(strend, -(minlen - 1));
@@ -1999,7 +2064,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
        /* We don't know much -- general case. */
        if (do_utf8) {
            for (;;) {
        /* We don't know much -- general case. */
        if (do_utf8) {
            for (;;) {
-               if (regtry(&reginfo, s))
+               if (regtry(&reginfo, &s))
                    goto got_it;
                if (s >= strend)
                    break;
                    goto got_it;
                if (s >= strend)
                    break;
@@ -2008,7 +2073,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
        }
        else {
            do {
        }
        else {
            do {
-               if (regtry(&reginfo, s))
+               if (regtry(&reginfo, &s))
                    goto got_it;
            } while (s++ < strend);
        }
                    goto got_it;
            } while (s++ < strend);
        }
@@ -2028,6 +2093,8 @@ got_it:
                                                  the same. */
        restore_pos(aTHX_ prog);
     }
                                                  the same. */
        restore_pos(aTHX_ prog);
     }
+    if (prog->paren_names) 
+        (void)hv_iterinit(prog->paren_names);
 
     /* make sure $`, $&, $', and $digit will work later */
     if ( !(flags & REXEC_NOT_FIRST) ) {
 
     /* make sure $`, $&, $', and $digit will work later */
     if ( !(flags & REXEC_NOT_FIRST) ) {
@@ -2067,6 +2134,10 @@ phooey:
                          PL_colors[4], PL_colors[5]));
     if (PL_reg_eval_set)
        restore_pos(aTHX_ prog);
                          PL_colors[4], PL_colors[5]));
     if (PL_reg_eval_set)
        restore_pos(aTHX_ prog);
+    if (swap_on_fail) 
+        /* we failed :-( roll it back */
+        swap_match_buff(prog);
+    
     return 0;
 }
 
     return 0;
 }
 
@@ -2075,16 +2146,18 @@ phooey:
  - regtry - try match at specific point
  */
 STATIC I32                     /* 0 failure, 1 success */
  - regtry - try match at specific point
  */
 STATIC I32                     /* 0 failure, 1 success */
-S_regtry(pTHX_ const regmatch_info *reginfo, char *startpos)
+S_regtry(pTHX_ regmatch_info *reginfo, char **startpos)
 {
     dVAR;
     register I32 *sp;
     register I32 *ep;
     CHECKPOINT lastcp;
     regexp *prog = reginfo->prog;
 {
     dVAR;
     register I32 *sp;
     register I32 *ep;
     CHECKPOINT lastcp;
     regexp *prog = reginfo->prog;
+    RXi_GET_DECL(prog,progi);
     GET_RE_DEBUG_FLAGS_DECL;
     GET_RE_DEBUG_FLAGS_DECL;
+    reginfo->cutpoint=NULL;
 
 
-    if ((prog->reganch & ROPT_EVAL_SEEN) && !PL_reg_eval_set) {
+    if ((prog->extflags & RXf_EVAL_SEEN) && !PL_reg_eval_set) {
        MAGIC *mg;
 
        PL_reg_eval_set = RS_init;
        MAGIC *mg;
 
        PL_reg_eval_set = RS_init;
@@ -2092,7 +2165,7 @@ S_regtry(pTHX_ const regmatch_info *reginfo, char *startpos)
            PerlIO_printf(Perl_debug_log, "  setting stack tmpbase at %"IVdf"\n",
                          (IV)(PL_stack_sp - PL_stack_base));
            ));
            PerlIO_printf(Perl_debug_log, "  setting stack tmpbase at %"IVdf"\n",
                          (IV)(PL_stack_sp - PL_stack_base));
            ));
-       SAVEI32(cxstack[cxstack_ix].blk_oldsp);
+       SAVESTACK_CXPOS();
        cxstack[cxstack_ix].blk_oldsp = PL_stack_sp - PL_stack_base;
        /* Otherwise OP_NEXTSTATE will free whatever on stack now.  */
        SAVETMPS;
        cxstack[cxstack_ix].blk_oldsp = PL_stack_sp - PL_stack_base;
        /* Otherwise OP_NEXTSTATE will free whatever on stack now.  */
        SAVETMPS;
@@ -2111,8 +2184,8 @@ S_regtry(pTHX_ const regmatch_info *reginfo, char *startpos)
                  && (mg = mg_find(reginfo->sv, PERL_MAGIC_regex_global)))) {
                /* prepare for quick setting of pos */
 #ifdef PERL_OLD_COPY_ON_WRITE
                  && (mg = mg_find(reginfo->sv, PERL_MAGIC_regex_global)))) {
                /* prepare for quick setting of pos */
 #ifdef PERL_OLD_COPY_ON_WRITE
-               if (SvIsCOW(sv))
-                   sv_force_normal_flags(sv, 0);
+               if (SvIsCOW(reginfo->sv))
+                   sv_force_normal_flags(reginfo->sv, 0);
 #endif
                mg = sv_magicext(reginfo->sv, NULL, PERL_MAGIC_regex_global,
                                 &PL_vtbl_mglob, NULL, 0);
 #endif
                mg = sv_magicext(reginfo->sv, NULL, PERL_MAGIC_regex_global,
                                 &PL_vtbl_mglob, NULL, 0);
@@ -2154,9 +2227,9 @@ S_regtry(pTHX_ const regmatch_info *reginfo, char *startpos)
        prog->subbeg = PL_bostr;
        prog->sublen = PL_regeol - PL_bostr; /* strend may have been modified */
     }
        prog->subbeg = PL_bostr;
        prog->sublen = PL_regeol - PL_bostr; /* strend may have been modified */
     }
-    DEBUG_EXECUTE_r(PL_reg_starttry = startpos);
-    prog->startp[0] = startpos - PL_bostr;
-    PL_reginput = startpos;
+    DEBUG_EXECUTE_r(PL_reg_starttry = *startpos);
+    prog->startp[0] = *startpos - PL_bostr;
+    PL_reginput = *startpos;
     PL_reglastparen = &prog->lastparen;
     PL_reglastcloseparen = &prog->lastcloseparen;
     prog->lastparen = 0;
     PL_reglastparen = &prog->lastparen;
     PL_reglastcloseparen = &prog->lastcloseparen;
     prog->lastparen = 0;
@@ -2187,8 +2260,8 @@ S_regtry(pTHX_ const regmatch_info *reginfo, char *startpos)
      * on those tests seems to be returning null fields from matches.
      * --jhi */
 #if 1
      * on those tests seems to be returning null fields from matches.
      * --jhi */
 #if 1
-    sp = prog->startp;
-    ep = prog->endp;
+    sp = PL_regstartp;
+    ep = PL_regendp;
     if (prog->nparens) {
        register I32 i;
        for (i = prog->nparens; i > (I32)*PL_reglastparen; i--) {
     if (prog->nparens) {
        register I32 i;
        for (i = prog->nparens; i > (I32)*PL_reglastparen; i--) {
@@ -2198,10 +2271,12 @@ S_regtry(pTHX_ const regmatch_info *reginfo, char *startpos)
     }
 #endif
     REGCP_SET(lastcp);
     }
 #endif
     REGCP_SET(lastcp);
-    if (regmatch(reginfo, prog->program + 1)) {
-       prog->endp[0] = PL_reginput - PL_bostr;
+    if (regmatch(reginfo, progi->program + 1)) {
+       PL_regendp[0] = PL_reginput - PL_bostr;
        return 1;
     }
        return 1;
     }
+    if (reginfo->cutpoint)
+        *startpos= reginfo->cutpoint;
     REGCP_UNWIND(lastcp);
     return 0;
 }
     REGCP_UNWIND(lastcp);
     return 0;
 }
@@ -2408,9 +2483,14 @@ regmatch(), slabs allocated since entry are freed.
     DEBUG_STATE_r({                                        \
        DUMP_EXEC_POS(locinput, scan, do_utf8);             \
        PerlIO_printf(Perl_debug_log,                       \
     DEBUG_STATE_r({                                        \
        DUMP_EXEC_POS(locinput, scan, do_utf8);             \
        PerlIO_printf(Perl_debug_log,                       \
-           "    %*s"pp" %s\n",                             \
+           "    %*s"pp" %s%s%s%s%s\n",                     \
            depth*2, "",                                    \
            depth*2, "",                                    \
-           reg_name[st->resume_state] );   \
+           PL_reg_name[st->resume_state],                     \
+           ((st==yes_state||st==mark_state) ? "[" : ""),   \
+           ((st==yes_state) ? "Y" : ""),                   \
+           ((st==mark_state) ? "M" : ""),                  \
+           ((st==yes_state||st==mark_state) ? "]" : "")    \
+       );                                                  \
     });
 
 
     });
 
 
@@ -2422,7 +2502,7 @@ STATIC void
 S_debug_start_match(pTHX_ const regexp *prog, const bool do_utf8, 
     const char *start, const char *end, const char *blurb)
 {
 S_debug_start_match(pTHX_ const regexp *prog, const bool do_utf8, 
     const char *start, const char *end, const char *blurb)
 {
-    const bool utf8_pat= prog->reganch & ROPT_UTF8 ? 1 : 0;
+    const bool utf8_pat= prog->extflags & RXf_UTF8 ? 1 : 0;
     if (!PL_colorset)   
             reginitcolors();    
     {
     if (!PL_colorset)   
             reginitcolors();    
     {
@@ -2506,8 +2586,33 @@ S_dump_exec_pos(pTHX_ const char *locinput,
 
 #endif
 
 
 #endif
 
+/* reg_check_named_buff_matched()
+ * Checks to see if a named buffer has matched. The data array of 
+ * buffer numbers corresponding to the buffer is expected to reside
+ * in the regexp->data->data array in the slot stored in the ARG() of
+ * node involved. Note that this routine doesn't actually care about the
+ * name, that information is not preserved from compilation to execution.
+ * Returns the index of the leftmost defined buffer with the given name
+ * or 0 if non of the buffers matched.
+ */
+STATIC I32
+S_reg_check_named_buff_matched(pTHX_ const regexp *rex, const regnode *scan) {
+    I32 n;
+    RXi_GET_DECL(rex,rexi);
+    SV *sv_dat=(SV*)rexi->data->data[ ARG( scan ) ];
+    I32 *nums=(I32*)SvPVX(sv_dat);
+    for ( n=0; n<SvIVX(sv_dat); n++ ) {
+        if ((I32)*PL_reglastparen >= nums[n] &&
+            PL_regendp[nums[n]] != -1)
+        {
+            return nums[n];
+        }
+    }
+    return 0;
+}
+
 STATIC I32                     /* 0 failure, 1 success */
 STATIC I32                     /* 0 failure, 1 success */
-S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
+S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog)
 {
 #if PERL_VERSION < 9
     dMY_CXT;
 {
 #if PERL_VERSION < 9
     dMY_CXT;
@@ -2517,7 +2622,8 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
     const U32 uniflags = UTF8_ALLOW_DEFAULT;
 
     regexp *rex = reginfo->prog;
     const U32 uniflags = UTF8_ALLOW_DEFAULT;
 
     regexp *rex = reginfo->prog;
-
+    RXi_GET_DECL(rex,rexi);
+    
     regmatch_slab  *orig_slab;
     regmatch_state *orig_state;
 
     regmatch_slab  *orig_slab;
     regmatch_state *orig_state;
 
@@ -2527,20 +2633,38 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
     /* cache heavy used fields of st in registers */
     register regnode *scan;
     register regnode *next;
     /* cache heavy used fields of st in registers */
     register regnode *scan;
     register regnode *next;
-    register I32 n = 0;        /* general value; init to avoid compiler warning */
+    register U32 n = 0;        /* general value; init to avoid compiler warning */
     register I32 ln = 0; /* len or last;  init to avoid compiler warning */
     register char *locinput = PL_reginput;
     register I32 nextchr;   /* is always set to UCHARAT(locinput) */
 
     bool result = 0;       /* return value of S_regmatch */
     int depth = 0;         /* depth of backtrack stack */
     register I32 ln = 0; /* len or last;  init to avoid compiler warning */
     register char *locinput = PL_reginput;
     register I32 nextchr;   /* is always set to UCHARAT(locinput) */
 
     bool result = 0;       /* return value of S_regmatch */
     int depth = 0;         /* depth of backtrack stack */
-    int nochange_depth = 0; /* depth of RECURSE recursion with nochange*/
+    U32 nochange_depth = 0; /* depth of GOSUB recursion with nochange */
+    const U32 max_nochange_depth =
+        (3 * rex->nparens > MAX_RECURSE_EVAL_NOCHANGE_DEPTH) ?
+        3 * rex->nparens : MAX_RECURSE_EVAL_NOCHANGE_DEPTH;
+            
     regmatch_state *yes_state = NULL; /* state to pop to on success of
                                                            subpattern */
     regmatch_state *yes_state = NULL; /* state to pop to on success of
                                                            subpattern */
+    /* mark_state piggy backs on the yes_state logic so that when we unwind 
+       the stack on success we can update the mark_state as we go */
+    regmatch_state *mark_state = NULL; /* last mark state we have seen */
+    
     regmatch_state *cur_eval = NULL; /* most recent EVAL_AB state */
     struct regmatch_state  *cur_curlyx = NULL; /* most recent curlyx */
     U32 state_num;
     regmatch_state *cur_eval = NULL; /* most recent EVAL_AB state */
     struct regmatch_state  *cur_curlyx = NULL; /* most recent curlyx */
     U32 state_num;
-
+    bool no_final = 0;      /* prevent failure from backtracking? */
+    bool do_cutgroup = 0;   /* no_final only until next branch/trie entry */
+    char *startpoint = PL_reginput;
+    SV *popmark = NULL;     /* are we looking for a mark? */
+    SV *sv_commit = NULL;   /* last mark name seen in failure */
+    SV *sv_yes_mark = NULL; /* last mark name we have seen 
+                               during a successfull match */
+    U32 lastopen = 0;       /* last open we saw */
+    bool has_cutgroup = RX_HAS_CUTGROUP(rex) ? 1 : 0;   
+               
+    
     /* these three flags are set by various ops to signal information to
      * the very next op. They have a useful lifetime of exactly one loop
      * iteration, and are not preserved or restored by state pushes/pops
     /* these three flags are set by various ops to signal information to
      * the very next op. They have a useful lifetime of exactly one loop
      * iteration, and are not preserved or restored by state pushes/pops
@@ -2560,6 +2684,9 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
     GET_RE_DEBUG_FLAGS_DECL;
 #endif
 
     GET_RE_DEBUG_FLAGS_DECL;
 #endif
 
+    DEBUG_OPTIMISE_r( DEBUG_EXECUTE_r({
+           PerlIO_printf(Perl_debug_log,"regmatch start\n");
+    }));
     /* on first ever call to regmatch, allocate first slab */
     if (!PL_regmatch_slab) {
        Newx(PL_regmatch_slab, 1, regmatch_slab);
     /* on first ever call to regmatch, allocate first slab */
     if (!PL_regmatch_slab) {
        Newx(PL_regmatch_slab, 1, regmatch_slab);
@@ -2591,10 +2718,10 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
             
            PerlIO_printf(Perl_debug_log,
                    "%3"IVdf":%*s%s(%"IVdf")\n",
             
            PerlIO_printf(Perl_debug_log,
                    "%3"IVdf":%*s%s(%"IVdf")\n",
-                   (IV)(scan - rex->program), depth*2, "",
+                   (IV)(scan - rexi->program), depth*2, "",
                    SvPVX_const(prop),
                    (PL_regkind[OP(scan)] == END || !rnext) ? 
                    SvPVX_const(prop),
                    (PL_regkind[OP(scan)] == END || !rnext) ? 
-                       0 : (IV)(rnext - rex->program));
+                       0 : (IV)(rnext - rexi->program));
        });
 
        next = scan + NEXT_OFF(scan);
        });
 
        next = scan + NEXT_OFF(scan);
@@ -2626,6 +2753,19 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
            if (locinput == reginfo->ganch)
                break;
            sayNO;
            if (locinput == reginfo->ganch)
                break;
            sayNO;
+
+       case KEEPS:
+           /* update the startpoint */
+           st->u.keeper.val = PL_regstartp[0];
+           PL_reginput = locinput;
+           PL_regstartp[0] = locinput - PL_bostr;
+           PUSH_STATE_GOTO(KEEPS_next, next);
+           /*NOT-REACHED*/
+       case KEEPS_next_fail:
+           /* rollback the start point change */
+           PL_regstartp[0] = st->u.keeper.val;
+           sayNO_SILENT;
+           /*NOT-REACHED*/
        case EOL:
                goto seol;
        case MEOL:
        case EOL:
                goto seol;
        case MEOL:
@@ -2701,7 +2841,8 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
 
                 /* what trie are we using right now */
                reg_trie_data * const trie
 
                 /* what trie are we using right now */
                reg_trie_data * const trie
-                   = (reg_trie_data*)rex->data->data[ ARG( scan ) ];
+                   = (reg_trie_data*)rexi->data->data[ ARG( scan ) ];
+               HV * widecharmap = (HV *)rexi->data->data[ ARG( scan ) + 1 ];
                 U32 state = trie->startstate;
 
                if (trie->bitmap && trie_type != trie_utf8_fold &&
                 U32 state = trie->startstate;
 
                if (trie->bitmap && trie_type != trie_utf8_fold &&
@@ -2737,13 +2878,7 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                ST.accepted = 0; /* how many accepting states we have seen */
                ST.B = next;
                ST.jump = trie->jump;
                ST.accepted = 0; /* how many accepting states we have seen */
                ST.B = next;
                ST.jump = trie->jump;
-               
-#ifdef DEBUGGING
                ST.me = scan;
                ST.me = scan;
-#endif
-                
-               
-
                /*
                   traverse the TRIE keeping track of all accepting states
                   we transition through until we get to a failing node.
                /*
                   traverse the TRIE keeping track of all accepting states
                   we transition through until we get to a failing node.
@@ -2802,8 +2937,9 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                    });
 
                    if ( base ) {
                    });
 
                    if ( base ) {
-                       REXEC_TRIE_READ_CHAR(trie_type, trie, uc, uscan, len,
-                           uvc, charid, foldlen, foldbuf, uniflags);
+                       REXEC_TRIE_READ_CHAR(trie_type, trie, widecharmap, uc,
+                                            uscan, len, uvc, charid, foldlen,
+                                            foldbuf, uniflags);
 
                        if (charid &&
                             (base + charid > trie->uniquecharcount )
 
                        if (charid &&
                             (base + charid > trie->uniquecharcount )
@@ -2840,47 +2976,79 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                        PL_colors[4], (IV)ST.accepted, PL_colors[5] );
                );
            }}
                        PL_colors[4], (IV)ST.accepted, PL_colors[5] );
                );
            }}
-
-           /* FALL THROUGH */
-
+            goto trie_first_try; /* jump into the fail handler */
+           /* NOTREACHED */
        case TRIE_next_fail: /* we failed - try next alterative */
        case TRIE_next_fail: /* we failed - try next alterative */
+            if ( ST.jump) {
+                REGCP_UNWIND(ST.cp);
+               for (n = *PL_reglastparen; n > ST.lastparen; n--)
+                   PL_regendp[n] = -1;
+               *PL_reglastparen = n;
+           }
+          trie_first_try:
+            if (do_cutgroup) {
+                do_cutgroup = 0;
+                no_final = 0;
+            }
 
 
+            if ( ST.jump) {
+                ST.lastparen = *PL_reglastparen;
+               REGCP_SET(ST.cp);
+            }          
            if ( ST.accepted == 1 ) {
                /* only one choice left - just continue */
                DEBUG_EXECUTE_r({
            if ( ST.accepted == 1 ) {
                /* only one choice left - just continue */
                DEBUG_EXECUTE_r({
-                   reg_trie_data * const trie
-                       = (reg_trie_data*)rex->data->data[ ARG(ST.me) ];
-                   SV ** const tmp = RX_DEBUG(reginfo->prog)
-                                   ? av_fetch( trie->words, ST.accept_buff[ 0 ].wordnum-1, 0 )
-                                   : NULL;
+                   AV *const trie_words
+                       = (AV *) rexi->data->data[ARG(ST.me)+TRIE_WORDS_OFFSET];
+                   SV ** const tmp = av_fetch( trie_words, 
+                       ST.accept_buff[ 0 ].wordnum-1, 0 );
+                   SV *sv= tmp ? sv_newmortal() : NULL;
+                   
                    PerlIO_printf( Perl_debug_log,
                        "%*s  %sonly one match left: #%d <%s>%s\n",
                        REPORT_CODE_OFF+depth*2, "", PL_colors[4],
                        ST.accept_buff[ 0 ].wordnum,
                    PerlIO_printf( Perl_debug_log,
                        "%*s  %sonly one match left: #%d <%s>%s\n",
                        REPORT_CODE_OFF+depth*2, "", PL_colors[4],
                        ST.accept_buff[ 0 ].wordnum,
-                       tmp ? SvPV_nolen_const( *tmp ) : "not compiled under -Dr",
+                       tmp ? pv_pretty(sv, SvPV_nolen_const(*tmp), SvCUR(*tmp), 0, 
+                               PL_colors[0], PL_colors[1],
+                               (SvUTF8(*tmp) ? PERL_PV_ESCAPE_UNI : 0)
+                            ) 
+                       : "not compiled under -Dr",
                        PL_colors[5] );
                });
                PL_reginput = (char *)ST.accept_buff[ 0 ].endpos;
                /* in this case we free tmps/leave before we call regmatch
                   as we wont be using accept_buff again. */
                        PL_colors[5] );
                });
                PL_reginput = (char *)ST.accept_buff[ 0 ].endpos;
                /* in this case we free tmps/leave before we call regmatch
                   as we wont be using accept_buff again. */
-               FREETMPS;
-               LEAVE;
+               
                locinput = PL_reginput;
                nextchr = UCHARAT(locinput);
                locinput = PL_reginput;
                nextchr = UCHARAT(locinput);
-               
-               if ( !ST.jump ) 
-                   scan = ST.B;
-               else
-                   scan = ST.B - ST.jump[ST.accept_buff[0].wordnum];
+               if ( !ST.jump || !ST.jump[ST.accept_buff[0].wordnum]) 
+                   scan = ST.B;
+               else
+                   scan = ST.me + ST.jump[ST.accept_buff[0].wordnum];
+               if (!has_cutgroup) {
+                   FREETMPS;
+                   LEAVE;
+                } else {
+                    ST.accepted--;
+                    PUSH_YES_STATE_GOTO(TRIE_next, scan);
+                }
                
                continue; /* execute rest of RE */
            }
                
                continue; /* execute rest of RE */
            }
-
-           if (!ST.accepted-- ) {
+           
+           if ( !ST.accepted-- ) {
+               DEBUG_EXECUTE_r({
+                   PerlIO_printf( Perl_debug_log,
+                       "%*s  %sTRIE failed...%s\n",
+                       REPORT_CODE_OFF+depth*2, "", 
+                       PL_colors[4],
+                       PL_colors[5] );
+               });
                FREETMPS;
                LEAVE;
                FREETMPS;
                LEAVE;
-               sayNO;
-           }
+               sayNO_SILENT;
+               /*NOTREACHED*/
+           } 
 
            /*
               There are at least two accepting states left.  Presumably
 
            /*
               There are at least two accepting states left.  Presumably
@@ -2912,19 +3080,23 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                }
 
                DEBUG_EXECUTE_r({
                }
 
                DEBUG_EXECUTE_r({
-                   reg_trie_data * const trie
-                       = (reg_trie_data*)rex->data->data[ ARG(ST.me) ];
-                   SV ** const tmp = RX_DEBUG(reginfo->prog)
-                               ? av_fetch( trie->words, ST.accept_buff[ best ].wordnum - 1, 0 )
-                               : NULL;
-                   regnode *nextop=!ST.jump ? 
+                   AV *const trie_words
+                       = (AV *) rexi->data->data[ARG(ST.me)+TRIE_WORDS_OFFSET];
+                   SV ** const tmp = av_fetch( trie_words, 
+                       ST.accept_buff[ best ].wordnum - 1, 0 );
+                   regnode *nextop=(!ST.jump || !ST.jump[ST.accept_buff[best].wordnum]) ? 
                                    ST.B : 
                                    ST.B : 
-                                   ST.B - ST.jump[ST.accept_buff[best].wordnum];    
+                                   ST.me + ST.jump[ST.accept_buff[best].wordnum];    
+                   SV *sv= tmp ? sv_newmortal() : NULL;
+                   
                    PerlIO_printf( Perl_debug_log, 
                        "%*s  %strying alternation #%d <%s> at node #%d %s\n",
                        REPORT_CODE_OFF+depth*2, "", PL_colors[4],
                        ST.accept_buff[best].wordnum,
                    PerlIO_printf( Perl_debug_log, 
                        "%*s  %strying alternation #%d <%s> at node #%d %s\n",
                        REPORT_CODE_OFF+depth*2, "", PL_colors[4],
                        ST.accept_buff[best].wordnum,
-                       tmp ? SvPV_nolen_const( *tmp ) : "not compiled under -Dr", 
+                       tmp ? pv_pretty(sv, SvPV_nolen_const(*tmp), SvCUR(*tmp), 0, 
+                               PL_colors[0], PL_colors[1],
+                               (SvUTF8(*tmp) ? PERL_PV_ESCAPE_UNI : 0)
+                            ) : "not compiled under -Dr", 
                            REG_NODE_NUM(nextop),
                        PL_colors[5] );
                });
                            REG_NODE_NUM(nextop),
                        PL_colors[5] );
                });
@@ -2936,17 +3108,27 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                    best = ST.accepted;
                }
                PL_reginput = (char *)ST.accept_buff[ best ].endpos;
                    best = ST.accepted;
                }
                PL_reginput = (char *)ST.accept_buff[ best ].endpos;
-               if ( !ST.jump ) {
-                   PUSH_STATE_GOTO(TRIE_next, ST.B);
+               if ( !ST.jump || !ST.jump[ST.accept_buff[best].wordnum]) {
+                   scan = ST.B;
                    /* NOTREACHED */
                } else {
                    /* NOTREACHED */
                } else {
-                   PUSH_STATE_GOTO(TRIE_next, ST.B - ST.jump[ST.accept_buff[best].wordnum]);
+                   scan = ST.me + ST.jump[ST.accept_buff[best].wordnum];
                    /* NOTREACHED */
                 }
                    /* NOTREACHED */
                 }
+                if (has_cutgroup) {
+                    PUSH_YES_STATE_GOTO(TRIE_next, scan);    
+                    /* NOTREACHED */
+                } else {
+                    PUSH_STATE_GOTO(TRIE_next, scan);
+                    /* NOTREACHED */
+                }
                 /* NOTREACHED */
            }
            /* NOTREACHED */
                 /* NOTREACHED */
            }
            /* NOTREACHED */
-
+        case TRIE_next:
+            FREETMPS;
+           LEAVE;
+           sayYES;
 #undef  ST
 
        case EXACT: {
 #undef  ST
 
        case EXACT: {
@@ -3288,22 +3470,42 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
               locinput++;
            nextchr = UCHARAT(locinput);
            break;
               locinput++;
            nextchr = UCHARAT(locinput);
            break;
+            
+       case NREFFL:
+       {
+           char *s;
+           char type;
+           PL_reg_flags |= RF_tainted;
+           /* FALL THROUGH */
+       case NREF:
+       case NREFF:
+           type = OP(scan);
+           n = reg_check_named_buff_matched(rex,scan);
+
+            if ( n ) {
+                type = REF + ( type - NREF );
+                goto do_ref;
+            } else {
+                sayNO;
+            }
+            /* unreached */
        case REFFL:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
         case REF:
        case REFFL:
            PL_reg_flags |= RF_tainted;
            /* FALL THROUGH */
         case REF:
-       case REFF: {
-           char *s;
+       case REFF: 
            n = ARG(scan);  /* which paren pair */
            n = ARG(scan);  /* which paren pair */
+           type = OP(scan);
+         do_ref:  
            ln = PL_regstartp[n];
            PL_reg_leftiter = PL_reg_maxiter;           /* Void cache */
            ln = PL_regstartp[n];
            PL_reg_leftiter = PL_reg_maxiter;           /* Void cache */
-           if ((I32)*PL_reglastparen < n || ln == -1)
+           if (*PL_reglastparen < n || ln == -1)
                sayNO;                  /* Do not match unless seen CLOSEn. */
            if (ln == PL_regendp[n])
                break;
 
            s = PL_bostr + ln;
                sayNO;                  /* Do not match unless seen CLOSEn. */
            if (ln == PL_regendp[n])
                break;
 
            s = PL_bostr + ln;
-           if (do_utf8 && OP(scan) != REF) {   /* REF can do byte comparison */
+           if (do_utf8 && type != REF) {       /* REF can do byte comparison */
                char *l = locinput;
                const char *e = PL_bostr + PL_regendp[n];
                /*
                char *l = locinput;
                const char *e = PL_bostr + PL_regendp[n];
                /*
@@ -3311,7 +3513,7 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                 * in the 8-bit case (no pun intended) because in Unicode we
                 * have to map both upper and title case to lower case.
                 */
                 * in the 8-bit case (no pun intended) because in Unicode we
                 * have to map both upper and title case to lower case.
                 */
-               if (OP(scan) == REFF) {
+               if (type == REFF) {
                    while (s < e) {
                        STRLEN ulen1, ulen2;
                        U8 tmpbuf1[UTF8_MAXBYTES_CASE+1];
                    while (s < e) {
                        STRLEN ulen1, ulen2;
                        U8 tmpbuf1[UTF8_MAXBYTES_CASE+1];
@@ -3334,24 +3536,23 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
 
            /* Inline the first character, for speed. */
            if (UCHARAT(s) != nextchr &&
 
            /* Inline the first character, for speed. */
            if (UCHARAT(s) != nextchr &&
-               (OP(scan) == REF ||
-                (UCHARAT(s) != ((OP(scan) == REFF
-                                 ? PL_fold : PL_fold_locale)[nextchr]))))
+               (type == REF ||
+                (UCHARAT(s) != (type == REFF
+                                 ? PL_fold : PL_fold_locale)[nextchr])))
                sayNO;
            ln = PL_regendp[n] - ln;
            if (locinput + ln > PL_regeol)
                sayNO;
                sayNO;
            ln = PL_regendp[n] - ln;
            if (locinput + ln > PL_regeol)
                sayNO;
-           if (ln > 1 && (OP(scan) == REF
+           if (ln > 1 && (type == REF
                           ? memNE(s, locinput, ln)
                           ? memNE(s, locinput, ln)
-                          : (OP(scan) == REFF
+                          : (type == REFF
                              ? ibcmp(s, locinput, ln)
                              : ibcmp_locale(s, locinput, ln))))
                sayNO;
            locinput += ln;
            nextchr = UCHARAT(locinput);
            break;
                              ? ibcmp(s, locinput, ln)
                              : ibcmp_locale(s, locinput, ln))))
                sayNO;
            locinput += ln;
            nextchr = UCHARAT(locinput);
            break;
-           }
-
+       }
        case NOTHING:
        case TAIL:
            break;
        case NOTHING:
        case TAIL:
            break;
@@ -3363,33 +3564,37 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
        {
            SV *ret;
             regexp *re;
        {
            SV *ret;
             regexp *re;
-            regnode *startpoint;           
-            
-        case SRECURSE:
-       case RECURSE: /*    /(...(?1))/      */
-            if (cur_eval && cur_eval->locinput==locinput) {
-                if (cur_eval->u.eval.close_paren == ARG(scan)) 
-                    Perl_croak(aTHX_ "Infinite recursion in RECURSE in regexp");
-                if ( ++nochange_depth > MAX_RECURSE_EVAL_NOCHANGE_DEPTH ) 
-                    Perl_croak(aTHX_ "RECURSE without pos change exceeded limit in regexp");
+            regexp_internal *rei;
+            regnode *startpoint;
+
+       case GOSTART:
+       case GOSUB: /*    /(...(?1))/   /(...(?&foo))/   */
+           if (cur_eval && cur_eval->locinput==locinput) {
+                if (cur_eval->u.eval.close_paren == (U32)ARG(scan)) 
+                    Perl_croak(aTHX_ "Infinite recursion in regex");
+                if ( ++nochange_depth > max_nochange_depth )
+                    Perl_croak(aTHX_ 
+                        "Pattern subroutine nesting without pos change"
+                        " exceeded limit in regex");
             } else {
                 nochange_depth = 0;
             } else {
                 nochange_depth = 0;
-            }    
+            }
             re = rex;
             re = rex;
+            rei = rexi;
             (void)ReREFCNT_inc(rex);
             (void)ReREFCNT_inc(rex);
-            if (OP(scan)==RECURSE) {
+            if (OP(scan)==GOSUB) {
                 startpoint = scan + ARG2L(scan);
                 ST.close_paren = ARG(scan);
             } else {
                 startpoint = scan + ARG2L(scan);
                 ST.close_paren = ARG(scan);
             } else {
-                startpoint = re->program+1;
+                startpoint = rei->program+1;
                 ST.close_paren = 0;
             }
             goto eval_recurse_doit;
             /* NOTREACHED */
         case EVAL:  /*   /(?{A})B/   /(??{A})B/  and /(?(?{A})X|Y)B/   */        
             if (cur_eval && cur_eval->locinput==locinput) {
                 ST.close_paren = 0;
             }
             goto eval_recurse_doit;
             /* NOTREACHED */
         case EVAL:  /*   /(?{A})B/   /(??{A})B/  and /(?(?{A})X|Y)B/   */        
             if (cur_eval && cur_eval->locinput==locinput) {
-                if ( ++nochange_depth > MAX_RECURSE_EVAL_NOCHANGE_DEPTH ) 
-                    Perl_croak(aTHX_ "EVAL without pos change exceeded limit in regexp");
+               if ( ++nochange_depth > max_nochange_depth )
+                    Perl_croak(aTHX_ "EVAL without pos change exceeded limit in regex");
             } else {
                 nochange_depth = 0;
             }    
             } else {
                 nochange_depth = 0;
             }    
@@ -3402,11 +3607,17 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                PAD *old_comppad;
            
                n = ARG(scan);
                PAD *old_comppad;
            
                n = ARG(scan);
-               PL_op = (OP_4tree*)rex->data->data[n];
-               DEBUG_EXECUTE_r( PerlIO_printf(Perl_debug_log, "  re_eval 0x%"UVxf"\n", PTR2UV(PL_op)) );
-               PAD_SAVE_LOCAL(old_comppad, (PAD*)rex->data->data[n + 2]);
+               PL_op = (OP_4tree*)rexi->data->data[n];
+               DEBUG_STATE_r( PerlIO_printf(Perl_debug_log, 
+                   "  re_eval 0x%"UVxf"\n", PTR2UV(PL_op)) );
+               PAD_SAVE_LOCAL(old_comppad, (PAD*)rexi->data->data[n + 2]);
                PL_regendp[0] = PL_reg_magic->mg_len = locinput - PL_bostr;
 
                PL_regendp[0] = PL_reg_magic->mg_len = locinput - PL_bostr;
 
+                if (sv_yes_mark) {
+                    SV *sv_mrk = get_sv("REGMARK", 1);
+                    sv_setsv(sv_mrk, sv_yes_mark);
+                }
+
                CALLRUNOPS(aTHX);                       /* Scalar context. */
                SPAGAIN;
                if (SP == before)
                CALLRUNOPS(aTHX);                       /* Scalar context. */
                SPAGAIN;
                if (SP == before)
@@ -3463,12 +3674,13 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                        PL_regsize = osize;
                    }
                }
                        PL_regsize = osize;
                    }
                }
+               rei = RXi_GET(re);
                 DEBUG_EXECUTE_r(
                     debug_start_match(re, do_utf8, locinput, PL_regeol, 
                         "Matching embedded");
                );              
                 DEBUG_EXECUTE_r(
                     debug_start_match(re, do_utf8, locinput, PL_regeol, 
                         "Matching embedded");
                );              
-               startpoint = re->program + 1;
-                       ST.close_paren = 0; /* only used for RECURSE */
+               startpoint = rei->program + 1;
+                       ST.close_paren = 0; /* only used for GOSUB */
                        /* borrowed from regtry */
                 if (PL_reg_start_tmpl <= re->nparens) {
                     PL_reg_start_tmpl = re->nparens*3/2 + 3;
                        /* borrowed from regtry */
                 if (PL_reg_start_tmpl <= re->nparens) {
                     PL_reg_start_tmpl = re->nparens*3/2 + 3;
@@ -3478,23 +3690,24 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                         Newx(PL_reg_start_tmp, PL_reg_start_tmpl, char*);
                 }                      
 
                         Newx(PL_reg_start_tmp, PL_reg_start_tmpl, char*);
                 }                      
 
-        eval_recurse_doit: /* Share code with RECURSE below this line */                               
+        eval_recurse_doit: /* Share code with GOSUB below this line */                         
                /* run the pattern returned from (??{...}) */
                ST.cp = regcppush(0);   /* Save *all* the positions. */
                REGCP_SET(ST.lastcp);
                
                /* run the pattern returned from (??{...}) */
                ST.cp = regcppush(0);   /* Save *all* the positions. */
                REGCP_SET(ST.lastcp);
                
-               PL_regstartp = re->startp; /* essentially NOOP on RECURSE */
-               PL_regendp = re->endp;     /* essentially NOOP on RECURSE */
+               PL_regstartp = re->startp; /* essentially NOOP on GOSUB */
+               PL_regendp = re->endp;     /* essentially NOOP on GOSUB */
                
                *PL_reglastparen = 0;
                *PL_reglastcloseparen = 0;
                PL_reginput = locinput;
                
                *PL_reglastparen = 0;
                *PL_reglastcloseparen = 0;
                PL_reginput = locinput;
+               PL_regsize = 0;
 
                /* XXXX This is too dramatic a measure... */
                PL_reg_maxiter = 0;
 
                ST.toggle_reg_flags = PL_reg_flags;
 
                /* XXXX This is too dramatic a measure... */
                PL_reg_maxiter = 0;
 
                ST.toggle_reg_flags = PL_reg_flags;
-               if (re->reganch & ROPT_UTF8)
+               if (re->extflags & RXf_UTF8)
                    PL_reg_flags |= RF_utf8;
                else
                    PL_reg_flags &= ~RF_utf8;
                    PL_reg_flags |= RF_utf8;
                else
                    PL_reg_flags &= ~RF_utf8;
@@ -3503,6 +3716,7 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
                ST.prev_rex = rex;
                ST.prev_curlyx = cur_curlyx;
                rex = re;
                ST.prev_rex = rex;
                ST.prev_curlyx = cur_curlyx;
                rex = re;
+               rexi = rei;
                cur_curlyx = NULL;
                ST.B = next;
                ST.prev_eval = cur_eval;
                cur_curlyx = NULL;
                ST.B = next;
                ST.prev_eval = cur_eval;
@@ -3522,11 +3736,14 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
            PL_reg_flags ^= ST.toggle_reg_flags; 
            ReREFCNT_dec(rex);
            rex = ST.prev_rex;
            PL_reg_flags ^= ST.toggle_reg_flags; 
            ReREFCNT_dec(rex);
            rex = ST.prev_rex;
+           rexi = RXi_GET(rex);
            regcpblow(ST.cp);
            cur_eval = ST.prev_eval;
            cur_curlyx = ST.prev_curlyx;
            /* XXXX This is too dramatic a measure... */
            PL_reg_maxiter = 0;
            regcpblow(ST.cp);
            cur_eval = ST.prev_eval;
            cur_curlyx = ST.prev_curlyx;
            /* XXXX This is too dramatic a measure... */
            PL_reg_maxiter = 0;
+            if ( nochange_depth )
+               nochange_depth--;
            sayYES;
 
 
            sayYES;
 
 
@@ -3535,6 +3752,7 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
            PL_reg_flags ^= ST.toggle_reg_flags; 
            ReREFCNT_dec(rex);
            rex = ST.prev_rex;
            PL_reg_flags ^= ST.toggle_reg_flags; 
            ReREFCNT_dec(rex);
            rex = ST.prev_rex;
+           rexi = RXi_GET(rex); 
            PL_reginput = locinput;
            REGCP_UNWIND(ST.lastcp);
            regcppop(rex);
            PL_reginput = locinput;
            REGCP_UNWIND(ST.lastcp);
            regcppop(rex);
@@ -3542,6 +3760,8 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
            cur_curlyx = ST.prev_curlyx;
            /* XXXX This is too dramatic a measure... */
            PL_reg_maxiter = 0;
            cur_curlyx = ST.prev_curlyx;
            /* XXXX This is too dramatic a measure... */
            PL_reg_maxiter = 0;
+           if ( nochange_depth )
+               nochange_depth--;
            sayNO_SILENT;
 #undef ST
 
            sayNO_SILENT;
 #undef ST
 
@@ -3550,22 +3770,62 @@ S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
            PL_reg_start_tmp[n] = locinput;
            if (n > PL_regsize)
                PL_regsize = n;
            PL_reg_start_tmp[n] = locinput;
            if (n > PL_regsize)
                PL_regsize = n;
+            lastopen = n;
            break;
        case CLOSE:
            n = ARG(scan);  /* which paren pair */
            PL_regstartp[n] = PL_reg_start_tmp[n] - PL_bostr;
            PL_regendp[n] = locinput - PL_bostr;
            break;
        case CLOSE:
            n = ARG(scan);  /* which paren pair */
            PL_regstartp[n] = PL_reg_start_tmp[n] - PL_bostr;
            PL_regendp[n] = locinput - PL_bostr;
-           if (n > (I32)*PL_reglastparen)
+           /*if (n > PL_regsize)
+               PL_regsize = n;*/
+           if (n > *PL_reglastparen)
                *PL_reglastparen = n;
            *PL_reglastcloseparen = n;
                *PL_reglastparen = n;
            *PL_reglastcloseparen = n;
-            if (cur_eval && cur_eval->u.eval.close_paren == (U32)n) {
+            if (cur_eval && cur_eval->u.eval.close_paren == n) {
                goto fake_end;
            }    
            break;
                goto fake_end;
            }    
            break;
+        case ACCEPT:
+            if (ARG(scan)){
+                regnode *cursor;
+                for (cursor=scan;
+                     cursor && OP(cursor)!=END; 
+                     cursor=regnext(cursor)) 
+                {
+                    if ( OP(cursor)==CLOSE ){
+                        n = ARG(cursor);
+                        if ( n <= lastopen ) {
+                            PL_regstartp[n] = PL_reg_start_tmp[n] - PL_bostr;
+                            PL_regendp[n] = locinput - PL_bostr;
+                            /*if (n > PL_regsize)
+                            PL_regsize = n;*/
+                            if (n > *PL_reglastparen)
+                                *PL_reglastparen = n;
+                            *PL_reglastcloseparen = n;
+                            if ( n == ARG(scan) || (cur_eval &&
+                                cur_eval->u.eval.close_paren == n))
+                                break;
+                        }
+                    }
+                }
+            }
+           goto fake_end;
+           /*NOTREACHED*/          
        case GROUPP:
            n = ARG(scan);  /* which paren pair */
        case GROUPP:
            n = ARG(scan);  /* which paren pair */
-           sw = (bool)((I32)*PL_reglastparen >= n && PL_regendp[n] != -1);
+           sw = (bool)(*PL_reglastparen >= n && PL_regendp[n] != -1);
+           break;
+       case NGROUPP:
+           /* reg_check_named_buff_matched returns 0 for no match */
+           sw = (bool)(0 < reg_check_named_buff_matched(rex,scan));
            break;
            break;
+        case INSUBP:
+            n = ARG(scan);
+            sw = (cur_eval && (!n || cur_eval->u.eval.close_paren == n));
+            break;
+        case DEFINEP:
+            sw = 0;
+            break;
        case IFTHEN:
            PL_reg_leftiter = PL_reg_maxiter;           /* Void cache */
            if (sw)
        case IFTHEN:
            PL_reg_leftiter = PL_reg_maxiter;           /* Void cache */
            if (sw)
@@ -3701,7 +3961,15 @@ NULL
        }
 
        case CURLYX_end: /* just finished matching all of A*B */
        }
 
        case CURLYX_end: /* just finished matching all of A*B */
-           regcpblow(ST.cp);
+           if (PL_reg_eval_set){
+               SV *pres= GvSV(PL_replgv);
+               SvREFCNT_inc(pres);
+               regcpblow(ST.cp);
+               sv_setsv(GvSV(PL_replgv), pres);
+               SvREFCNT_dec(pres);
+           } else {
+               regcpblow(ST.cp);
+           }
            cur_curlyx = ST.prev_curlyx;
            sayYES;
            /* NOTREACHED */
            cur_curlyx = ST.prev_curlyx;
            sayYES;
            /* NOTREACHED */
@@ -3719,7 +3987,6 @@ NULL
        case WHILEM:     /* just matched an A in /A*B/  (for complex A) */
        {
            /* see the discussion above about CURLYX/WHILEM */
        case WHILEM:     /* just matched an A in /A*B/  (for complex A) */
        {
            /* see the discussion above about CURLYX/WHILEM */
-
            I32 n;
            assert(cur_curlyx); /* keep Coverity happy */
            n = ++cur_curlyx->u.curlyx.count; /* how many A's matched */
            I32 n;
            assert(cur_curlyx); /* keep Coverity happy */
            n = ++cur_curlyx->u.curlyx.count; /* how many A's matched */
@@ -3923,27 +4190,62 @@ NULL
 
        case BRANCH:        /*  /(...|A|...)/ */
            scan = NEXTOPER(scan); /* scan now points to inner node */
 
        case BRANCH:        /*  /(...|A|...)/ */
            scan = NEXTOPER(scan); /* scan now points to inner node */
-           if (!next || (OP(next) != BRANCH && OP(next) != BRANCHJ))
+           if ((!next || (OP(next) != BRANCH && OP(next) != BRANCHJ)) 
+               && !has_cutgroup)
+           {
                /* last branch; skip state push and jump direct to node */
                continue;
                /* last branch; skip state push and jump direct to node */
                continue;
+            }
            ST.lastparen = *PL_reglastparen;
            ST.next_branch = next;
            REGCP_SET(ST.cp);
            PL_reginput = locinput;
 
            /* Now go into the branch */
            ST.lastparen = *PL_reglastparen;
            ST.next_branch = next;
            REGCP_SET(ST.cp);
            PL_reginput = locinput;
 
            /* Now go into the branch */
-           PUSH_STATE_GOTO(BRANCH_next, scan);
+           if (has_cutgroup) {
+               PUSH_YES_STATE_GOTO(BRANCH_next, scan);    
+           } else {
+               PUSH_STATE_GOTO(BRANCH_next, scan);
+           }
            /* NOTREACHED */
            /* NOTREACHED */
-
+        case CUTGROUP:
+            PL_reginput = locinput;
+            sv_yes_mark = st->u.mark.mark_name = scan->flags ? NULL :
+                (SV*)rexi->data->data[ ARG( scan ) ];
+            PUSH_STATE_GOTO(CUTGROUP_next,next);
+            /* NOTREACHED */
+        case CUTGROUP_next_fail:
+            do_cutgroup = 1;
+            no_final = 1;
+            if (st->u.mark.mark_name)
+                sv_commit = st->u.mark.mark_name;
+            sayNO;         
+            /* NOTREACHED */
+        case BRANCH_next:
+            sayYES;
+            /* NOTREACHED */
        case BRANCH_next_fail: /* that branch failed; try the next, if any */
        case BRANCH_next_fail: /* that branch failed; try the next, if any */
+           if (do_cutgroup) {
+               do_cutgroup = 0;
+               no_final = 0;
+           }
            REGCP_UNWIND(ST.cp);
            for (n = *PL_reglastparen; n > ST.lastparen; n--)
                PL_regendp[n] = -1;
            *PL_reglastparen = n;
            REGCP_UNWIND(ST.cp);
            for (n = *PL_reglastparen; n > ST.lastparen; n--)
                PL_regendp[n] = -1;
            *PL_reglastparen = n;
+           /*dmq: *PL_reglastcloseparen = n; */
            scan = ST.next_branch;
            /* no more branches? */
            scan = ST.next_branch;
            /* no more branches? */
-           if (!scan || (OP(scan) != BRANCH && OP(scan) != BRANCHJ))
-               sayNO;
+           if (!scan || (OP(scan) != BRANCH && OP(scan) != BRANCHJ)) {
+               DEBUG_EXECUTE_r({
+                   PerlIO_printf( Perl_debug_log,
+                       "%*s  %sBRANCH failed...%s\n",
+                       REPORT_CODE_OFF+depth*2, "", 
+                       PL_colors[4],
+                       PL_colors[5] );
+               });
+               sayNO_SILENT;
+            }
            continue; /* execute next BRANCH[J] op */
            /* NOTREACHED */
     
            continue; /* execute next BRANCH[J] op */
            /* NOTREACHED */
     
@@ -3967,10 +4269,10 @@ NULL
 
            /* if paren positive, emulate an OPEN/CLOSE around A */
            if (ST.me->flags) {
 
            /* if paren positive, emulate an OPEN/CLOSE around A */
            if (ST.me->flags) {
-               I32 paren = ST.me->flags;
+               U32 paren = ST.me->flags;
                if (paren > PL_regsize)
                    PL_regsize = paren;
                if (paren > PL_regsize)
                    PL_regsize = paren;
-               if (paren > (I32)*PL_reglastparen)
+               if (paren > *PL_reglastparen)
                    *PL_reglastparen = paren;
                scan += NEXT_OFF(scan); /* Skip former OPEN. */
            }
                    *PL_reglastparen = paren;
                scan += NEXT_OFF(scan); /* Skip former OPEN. */
            }
@@ -4019,13 +4321,21 @@ NULL
            );
 
            locinput = PL_reginput;
            );
 
            locinput = PL_reginput;
-           if (ST.count < (ST.minmod ? ARG1(ST.me) : ARG2(ST.me)))
+                       
+           if (cur_eval && cur_eval->u.eval.close_paren && 
+               cur_eval->u.eval.close_paren == (U32)ST.me->flags) 
+               goto fake_end;
+               
+           if ( ST.count < (ST.minmod ? ARG1(ST.me) : ARG2(ST.me)) )
                goto curlym_do_A; /* try to match another A */
            goto curlym_do_B; /* try to match B */
 
        case CURLYM_A_fail: /* just failed to match an A */
            REGCP_UNWIND(ST.cp);
                goto curlym_do_A; /* try to match another A */
            goto curlym_do_B; /* try to match B */
 
        case CURLYM_A_fail: /* just failed to match an A */
            REGCP_UNWIND(ST.cp);
-           if (ST.minmod || ST.count < ARG1(ST.me) /* min*/ )
+
+           if (ST.minmod || ST.count < ARG1(ST.me) /* min*/ 
+               || (cur_eval && cur_eval->u.eval.close_paren &&
+                   cur_eval->u.eval.close_paren == (U32)ST.me->flags))
                sayNO;
 
          curlym_do_B: /* execute the B in /A{m,n}B/  */
                sayNO;
 
          curlym_do_B: /* execute the B in /A{m,n}B/  */
@@ -4038,14 +4348,23 @@ NULL
                    regnode *text_node = ST.B;
                    if (! HAS_TEXT(text_node))
                        FIND_NEXT_IMPT(text_node);
                    regnode *text_node = ST.B;
                    if (! HAS_TEXT(text_node))
                        FIND_NEXT_IMPT(text_node);
-                   if (HAS_TEXT(text_node)
-                       && PL_regkind[OP(text_node)] != REF)
+                   /* this used to be 
+                       
+                       (HAS_TEXT(text_node) && PL_regkind[OP(text_node)] == EXACT)
+                       
+                       But the former is redundant in light of the latter.
+                       
+                       if this changes back then the macro for 
+                       IS_TEXT and friends need to change.
+                    */
+                   if (PL_regkind[OP(text_node)] == EXACT)
                    {
                    {
+                       
                        ST.c1 = (U8)*STRING(text_node);
                        ST.c2 =
                        ST.c1 = (U8)*STRING(text_node);
                        ST.c2 =
-                           (OP(text_node) == EXACTF || OP(text_node) == REFF)
+                           (IS_TEXTF(text_node))
                            ? PL_fold[ST.c1]
                            ? PL_fold[ST.c1]
-                           : (OP(text_node) == EXACTFL || OP(text_node) == REFFL)
+                           : (IS_TEXTFL(text_node))
                                ? PL_fold_locale[ST.c1]
                                : ST.c1;
                    }
                                ? PL_fold_locale[ST.c1]
                                : ST.c1;
                    }
@@ -4063,6 +4382,12 @@ NULL
                    && UCHARAT(PL_reginput) != ST.c2)
            {
                /* simulate B failing */
                    && UCHARAT(PL_reginput) != ST.c2)
            {
                /* simulate B failing */
+               DEBUG_OPTIMISE_r(
+                   PerlIO_printf(Perl_debug_log,
+                       "%*s  CURLYM Fast bail c1=%"IVdf" c2=%"IVdf"\n",
+                       (int)(REPORT_CODE_OFF+(depth*2)),"",
+                       (IV)ST.c1,(IV)ST.c2
+               ));
                state_num = CURLYM_B_fail;
                goto reenter_switch;
            }
                state_num = CURLYM_B_fail;
                goto reenter_switch;
            }
@@ -4074,10 +4399,20 @@ NULL
                    PL_regstartp[paren]
                        = HOPc(PL_reginput, -ST.alen) - PL_bostr;
                    PL_regendp[paren] = PL_reginput - PL_bostr;
                    PL_regstartp[paren]
                        = HOPc(PL_reginput, -ST.alen) - PL_bostr;
                    PL_regendp[paren] = PL_reginput - PL_bostr;
+                   /*dmq: *PL_reglastcloseparen = paren; */
                }
                else
                    PL_regendp[paren] = -1;
                }
                else
                    PL_regendp[paren] = -1;
+               if (cur_eval && cur_eval->u.eval.close_paren &&
+                   cur_eval->u.eval.close_paren == (U32)ST.me->flags) 
+               {
+                   if (ST.count) 
+                       goto fake_end;
+                   else
+                       sayNO;
+               }
            }
            }
+           
            PUSH_STATE_GOTO(CURLYM_B, ST.B); /* match B */
            /* NOTREACHED */
 
            PUSH_STATE_GOTO(CURLYM_B, ST.B); /* match B */
            /* NOTREACHED */
 
@@ -4103,6 +4438,7 @@ NULL
        if (success) { \
            PL_regstartp[paren] = HOPc(locinput, -1) - PL_bostr; \
            PL_regendp[paren] = locinput - PL_bostr; \
        if (success) { \
            PL_regstartp[paren] = HOPc(locinput, -1) - PL_bostr; \
            PL_regendp[paren] = locinput - PL_bostr; \
+           *PL_reglastcloseparen = paren; \
        } \
        else \
            PL_regendp[paren] = -1; \
        } \
        else \
            PL_regendp[paren] = -1; \
@@ -4124,10 +4460,15 @@ NULL
            ST.paren = scan->flags;     /* Which paren to set */
            if (ST.paren > PL_regsize)
                PL_regsize = ST.paren;
            ST.paren = scan->flags;     /* Which paren to set */
            if (ST.paren > PL_regsize)
                PL_regsize = ST.paren;
-           if (ST.paren > (I32)*PL_reglastparen)
+           if (ST.paren > *PL_reglastparen)
                *PL_reglastparen = ST.paren;
            ST.min = ARG1(scan);  /* min to match */
            ST.max = ARG2(scan);  /* max to match */
                *PL_reglastparen = ST.paren;
            ST.min = ARG1(scan);  /* min to match */
            ST.max = ARG2(scan);  /* max to match */
+           if (cur_eval && cur_eval->u.eval.close_paren &&
+               cur_eval->u.eval.close_paren == (U32)ST.paren) {
+               ST.min=1;
+               ST.max=1;
+           }
             scan = regnext(NEXTOPER(scan) + NODE_STEP_REGNODE);
            goto repeat;
        case CURLY:             /*  /A{m,n}B/ where A is width 1 */
             scan = regnext(NEXTOPER(scan) + NODE_STEP_REGNODE);
            goto repeat;
        case CURLY:             /*  /A{m,n}B/ where A is width 1 */
@@ -4157,22 +4498,28 @@ NULL
                if (! HAS_TEXT(text_node))
                    ST.c1 = ST.c2 = CHRTEST_VOID;
                else {
                if (! HAS_TEXT(text_node))
                    ST.c1 = ST.c2 = CHRTEST_VOID;
                else {
-                   if (PL_regkind[OP(text_node)] == REF) {
+                   if ( PL_regkind[OP(text_node)] != EXACT ) {
                        ST.c1 = ST.c2 = CHRTEST_VOID;
                        goto assume_ok_easy;
                    }
                    else
                        s = (U8*)STRING(text_node);
                        ST.c1 = ST.c2 = CHRTEST_VOID;
                        goto assume_ok_easy;
                    }
                    else
                        s = (U8*)STRING(text_node);
-
+                    
+                    /*  Currently we only get here when 
+                        
+                        PL_rekind[OP(text_node)] == EXACT
+                    
+                        if this changes back then the macro for IS_TEXT and 
+                        friends need to change. */
                    if (!UTF) {
                        ST.c2 = ST.c1 = *s;
                    if (!UTF) {
                        ST.c2 = ST.c1 = *s;
-                       if (OP(text_node) == EXACTF || OP(text_node) == REFF)
+                       if (IS_TEXTF(text_node))
                            ST.c2 = PL_fold[ST.c1];
                            ST.c2 = PL_fold[ST.c1];
-                       else if (OP(text_node) == EXACTFL || OP(text_node) == REFFL)
+                       else if (IS_TEXTFL(text_node))
                            ST.c2 = PL_fold_locale[ST.c1];
                    }
                    else { /* UTF */
                            ST.c2 = PL_fold_locale[ST.c1];
                    }
                    else { /* UTF */
-                       if (OP(text_node) == EXACTF || OP(text_node) == REFF) {
+                       if (IS_TEXTF(text_node)) {
                             STRLEN ulen1, ulen2;
                             U8 tmpbuf1[UTF8_MAXBYTES_CASE+1];
                             U8 tmpbuf2[UTF8_MAXBYTES_CASE+1];
                             STRLEN ulen1, ulen2;
                             U8 tmpbuf1[UTF8_MAXBYTES_CASE+1];
                             U8 tmpbuf2[UTF8_MAXBYTES_CASE+1];
@@ -4209,7 +4556,7 @@ NULL
            PL_reginput = locinput;
            if (minmod) {
                minmod = 0;
            PL_reginput = locinput;
            if (minmod) {
                minmod = 0;
-               if (ST.min && regrepeat(rex, ST.A, ST.min) < ST.min)
+               if (ST.min && regrepeat(rex, ST.A, ST.min, depth) < ST.min)
                    sayNO;
                ST.count = ST.min;
                locinput = PL_reginput;
                    sayNO;
                ST.count = ST.min;
                locinput = PL_reginput;
@@ -4242,7 +4589,7 @@ NULL
 
            }
            else {
 
            }
            else {
-               ST.count = regrepeat(rex, ST.A, ST.max);
+               ST.count = regrepeat(rex, ST.A, ST.max, depth);
                locinput = PL_reginput;
                if (ST.count < ST.min)
                    sayNO;
                locinput = PL_reginput;
                if (ST.count < ST.min)
                    sayNO;
@@ -4328,11 +4675,15 @@ NULL
                /* PL_reginput == oldloc now */
                if (n) {
                    ST.count += n;
                /* PL_reginput == oldloc now */
                if (n) {
                    ST.count += n;
-                   if (regrepeat(rex, ST.A, n) < n)
+                   if (regrepeat(rex, ST.A, n, depth) < n)
                        sayNO;
                }
                PL_reginput = locinput;
                CURLY_SETPAREN(ST.paren, ST.count);
                        sayNO;
                }
                PL_reginput = locinput;
                CURLY_SETPAREN(ST.paren, ST.count);
+               if (cur_eval && cur_eval->u.eval.close_paren && 
+                   cur_eval->u.eval.close_paren == (U32)ST.paren) {
+                   goto fake_end;
+               }
                PUSH_STATE_GOTO(CURLY_B_min_known, ST.B);
            }
            /* NOTREACHED */
                PUSH_STATE_GOTO(CURLY_B_min_known, ST.B);
            }
            /* NOTREACHED */
@@ -4346,7 +4697,7 @@ NULL
            REGCP_UNWIND(ST.cp);
            /* failed -- move forward one */
            PL_reginput = locinput;
            REGCP_UNWIND(ST.cp);
            /* failed -- move forward one */
            PL_reginput = locinput;
-           if (regrepeat(rex, ST.A, 1)) {
+           if (regrepeat(rex, ST.A, 1, depth)) {
                ST.count++;
                locinput = PL_reginput;
                if (ST.count <= ST.max || (ST.max == REG_INFTY &&
                ST.count++;
                locinput = PL_reginput;
                if (ST.count <= ST.max || (ST.max == REG_INFTY &&
@@ -4354,6 +4705,10 @@ NULL
                {
                  curly_try_B_min:
                    CURLY_SETPAREN(ST.paren, ST.count);
                {
                  curly_try_B_min:
                    CURLY_SETPAREN(ST.paren, ST.count);
+                   if (cur_eval && cur_eval->u.eval.close_paren &&
+                       cur_eval->u.eval.close_paren == (U32)ST.paren) {
+                        goto fake_end;
+                    }
                    PUSH_STATE_GOTO(CURLY_B_min, ST.B);
                }
            }
                    PUSH_STATE_GOTO(CURLY_B_min, ST.B);
                }
            }
@@ -4363,6 +4718,10 @@ NULL
 
        curly_try_B_max:
            /* a successful greedy match: now try to match B */
 
        curly_try_B_max:
            /* a successful greedy match: now try to match B */
+            if (cur_eval && cur_eval->u.eval.close_paren &&
+                cur_eval->u.eval.close_paren == (U32)ST.paren) {
+                goto fake_end;
+            }
            {
                UV c = 0;
                if (ST.c1 != CHRTEST_VOID)
            {
                UV c = 0;
                if (ST.c1 != CHRTEST_VOID)
@@ -4391,20 +4750,18 @@ NULL
 
 #undef ST
 
 
 #undef ST
 
-
        case END:
            fake_end:
            if (cur_eval) {
                /* we've just finished A in /(??{A})B/; now continue with B */
                I32 tmpix;
        case END:
            fake_end:
            if (cur_eval) {
                /* we've just finished A in /(??{A})B/; now continue with B */
                I32 tmpix;
-
-
                st->u.eval.toggle_reg_flags
                            = cur_eval->u.eval.toggle_reg_flags;
                PL_reg_flags ^= st->u.eval.toggle_reg_flags; 
 
                st->u.eval.prev_rex = rex;              /* inner */
                st->u.eval.toggle_reg_flags
                            = cur_eval->u.eval.toggle_reg_flags;
                PL_reg_flags ^= st->u.eval.toggle_reg_flags; 
 
                st->u.eval.prev_rex = rex;              /* inner */
-               rex    = cur_eval->u.eval.prev_rex;     /* outer */
+               rex  = cur_eval->u.eval.prev_rex;       /* outer */
+               rexi = RXi_GET(rex);
                cur_curlyx = cur_eval->u.eval.prev_curlyx;
                ReREFCNT_inc(rex);
                st->u.eval.cp = regcppush(0);   /* Save *all* the positions. */
                cur_curlyx = cur_eval->u.eval.prev_curlyx;
                ReREFCNT_inc(rex);
                st->u.eval.cp = regcppush(0);   /* Save *all* the positions. */
@@ -4421,9 +4778,12 @@ NULL
                st->u.eval.prev_eval = cur_eval;
                cur_eval = cur_eval->u.eval.prev_eval;
                DEBUG_EXECUTE_r(
                st->u.eval.prev_eval = cur_eval;
                cur_eval = cur_eval->u.eval.prev_eval;
                DEBUG_EXECUTE_r(
-                   PerlIO_printf(Perl_debug_log, "%*s  EVAL trying tail ... %x\n",
-                                     REPORT_CODE_OFF+depth*2, "",(int)cur_eval););
-               PUSH_YES_STATE_GOTO(EVAL_AB,
+                   PerlIO_printf(Perl_debug_log, "%*s  EVAL trying tail ... %"UVxf"\n",
+                                     REPORT_CODE_OFF+depth*2, "",PTR2UV(cur_eval)););
+                if ( nochange_depth )
+                   nochange_depth--;
+
+                PUSH_YES_STATE_GOTO(EVAL_AB,
                        st->u.eval.prev_eval->u.eval.B); /* match B */
            }
 
                        st->u.eval.prev_eval->u.eval.B); /* match B */
            }
 
@@ -4434,6 +4794,7 @@ NULL
                                      (long)(locinput - PL_reg_starttry),
                                      (long)(reginfo->till - PL_reg_starttry),
                                      PL_colors[5]));
                                      (long)(locinput - PL_reg_starttry),
                                      (long)(reginfo->till - PL_reg_starttry),
                                      PL_colors[5]));
+                                                     
                sayNO_SILENT;           /* Cannot match: too short. */
            }
            PL_reginput = locinput;     /* put where regtry can find it */
                sayNO_SILENT;           /* Cannot match: too short. */
            }
            PL_reginput = locinput;     /* put where regtry can find it */
@@ -4518,14 +4879,111 @@ NULL
            if (next == scan)
                next = NULL;
            break;
            if (next == scan)
                next = NULL;
            break;
+       case COMMIT:
+           reginfo->cutpoint = PL_regeol;
+           /* FALLTHROUGH */
+       case PRUNE:
+           PL_reginput = locinput;
+           if (!scan->flags)
+               sv_yes_mark = sv_commit = (SV*)rexi->data->data[ ARG( scan ) ];
+           PUSH_STATE_GOTO(COMMIT_next,next);
+           /* NOTREACHED */
+       case COMMIT_next_fail:
+           no_final = 1;    
+           /* FALLTHROUGH */       
+       case OPFAIL:
+           sayNO;
+           /* NOTREACHED */
+
+#define ST st->u.mark
+        case MARKPOINT:
+            ST.prev_mark = mark_state;
+            ST.mark_name = sv_commit = sv_yes_mark 
+                = (SV*)rexi->data->data[ ARG( scan ) ];
+            mark_state = st;
+            ST.mark_loc = PL_reginput = locinput;
+            PUSH_YES_STATE_GOTO(MARKPOINT_next,next);
+            /* NOTREACHED */
+        case MARKPOINT_next:
+            mark_state = ST.prev_mark;
+            sayYES;
+            /* NOTREACHED */
+        case MARKPOINT_next_fail:
+            if (popmark && sv_eq(ST.mark_name,popmark)) 
+            {
+                if (ST.mark_loc > startpoint)
+                   reginfo->cutpoint = HOPBACKc(ST.mark_loc, 1);
+                popmark = NULL; /* we found our mark */
+                sv_commit = ST.mark_name;
+
+                DEBUG_EXECUTE_r({
+                        PerlIO_printf(Perl_debug_log,
+                           "%*s  %ssetting cutpoint to mark:%"SVf"...%s\n",
+                           REPORT_CODE_OFF+depth*2, "", 
+                           PL_colors[4], SVfARG(sv_commit), PL_colors[5]);
+               });
+            }
+            mark_state = ST.prev_mark;
+            sv_yes_mark = mark_state ? 
+                mark_state->u.mark.mark_name : NULL;
+            sayNO;
+            /* NOTREACHED */
+        case SKIP:
+            PL_reginput = locinput;
+            if (scan->flags) {
+                /* (*SKIP) : if we fail we cut here*/
+                ST.mark_name = NULL;
+                ST.mark_loc = locinput;
+                PUSH_STATE_GOTO(SKIP_next,next);    
+            } else {
+                /* (*SKIP:NAME) : if there is a (*MARK:NAME) fail where it was, 
+                   otherwise do nothing.  Meaning we need to scan 
+                 */
+                regmatch_state *cur = mark_state;
+                SV *find = (SV*)rexi->data->data[ ARG( scan ) ];
+                
+                while (cur) {
+                    if ( sv_eq( cur->u.mark.mark_name, 
+                                find ) ) 
+                    {
+                        ST.mark_name = find;
+                        PUSH_STATE_GOTO( SKIP_next, next );
+                    }
+                    cur = cur->u.mark.prev_mark;
+                }
+            }    
+            /* Didn't find our (*MARK:NAME) so ignore this (*SKIP:NAME) */
+            break;    
+       case SKIP_next_fail:
+           if (ST.mark_name) {
+               /* (*CUT:NAME) - Set up to search for the name as we 
+                  collapse the stack*/
+               popmark = ST.mark_name;    
+           } else {
+               /* (*CUT) - No name, we cut here.*/
+               if (ST.mark_loc > startpoint)
+                   reginfo->cutpoint = HOPBACKc(ST.mark_loc, 1);
+               /* but we set sv_commit to latest mark_name if there
+                  is one so they can test to see how things lead to this
+                  cut */    
+                if (mark_state) 
+                    sv_commit=mark_state->u.mark.mark_name;                
+            } 
+            no_final = 1; 
+            sayNO;
+            /* NOTREACHED */
+#undef ST
+
        default:
            PerlIO_printf(Perl_error_log, "%"UVxf" %d\n",
                          PTR2UV(scan), OP(scan));
            Perl_croak(aTHX_ "regexp memory corruption");
        default:
            PerlIO_printf(Perl_error_log, "%"UVxf" %d\n",
                          PTR2UV(scan), OP(scan));
            Perl_croak(aTHX_ "regexp memory corruption");
-       }
+           
+       } /* end switch */ 
 
 
-       scan = next;
-       continue;
+        /* switch break jumps here */
+       scan = next; /* prepare to execute the next op and ... */
+       continue;    /* ... jump back to the top, reusing st */
        /* NOTREACHED */
 
       push_yes_state:
        /* NOTREACHED */
 
       push_yes_state:
@@ -4538,7 +4996,27 @@ NULL
        {
            regmatch_state *newst;
 
        {
            regmatch_state *newst;
 
-           DEBUG_STATE_pp("push");
+           DEBUG_STACK_r({
+               regmatch_state *cur = st;
+               regmatch_state *curyes = yes_state;
+               int curd = depth;
+               regmatch_slab *slab = PL_regmatch_slab;
+                for (;curd > -1;cur--,curd--) {
+                    if (cur < SLAB_FIRST(slab)) {
+                       slab = slab->prev;
+                       cur = SLAB_LAST(slab);
+                    }
+                    PerlIO_printf(Perl_error_log, "%*s#%-3d %-10s %s\n",
+                        REPORT_CODE_OFF + 2 + depth * 2,"",
+                        curd, PL_reg_name[cur->resume_state],
+                        (curyes == cur) ? "yes" : ""
+                    );
+                    if (curyes == cur)
+                       curyes = cur->u.yes.prev_yes_state;
+                }
+            } else 
+                DEBUG_STATE_pp("push")
+            );
            depth++;
            st->locinput = locinput;
            newst = st+1; 
            depth++;
            st->locinput = locinput;
            newst = st+1; 
@@ -4574,7 +5052,13 @@ yes:
                PL_regmatch_slab = PL_regmatch_slab->prev;
                st = SLAB_LAST(PL_regmatch_slab);
            }
                PL_regmatch_slab = PL_regmatch_slab->prev;
                st = SLAB_LAST(PL_regmatch_slab);
            }
-           DEBUG_STATE_pp("pop (yes)");
+           DEBUG_STATE_r({
+               if (no_final) {
+                   DEBUG_STATE_pp("pop (no final)");        
+               } else {
+                   DEBUG_STATE_pp("pop (yes)");
+               }
+           });
            depth--;
        }
 #else
            depth--;
        }
 #else
@@ -4591,8 +5075,12 @@ yes:
        st = yes_state;
        yes_state = st->u.yes.prev_yes_state;
        PL_regmatch_state = st;
        st = yes_state;
        yes_state = st->u.yes.prev_yes_state;
        PL_regmatch_state = st;
-
-       state_num = st->resume_state;
+        
+        if (no_final) {
+            locinput= st->locinput;
+            nextchr = UCHARAT(locinput);
+        }
+       state_num = st->resume_state + no_final;
        goto reenter_switch;
     }
 
        goto reenter_switch;
     }
 
@@ -4611,6 +5099,13 @@ no:
        );
 
 no_silent:
        );
 
 no_silent:
+    if (no_final) {
+        if (yes_state) {
+            goto yes;
+        } else {
+            goto final_exit;
+        }
+    }    
     if (depth) {
        /* there's a previous state to backtrack to */
        st--;
     if (depth) {
        /* there's a previous state to backtrack to */
        st--;
@@ -4633,7 +5128,21 @@ no_silent:
     result = 0;
 
   final_exit:
     result = 0;
 
   final_exit:
-
+    if (rex->intflags & PREGf_VERBARG_SEEN) {
+        SV *sv_err = get_sv("REGERROR", 1);
+        SV *sv_mrk = get_sv("REGMARK", 1);
+        if (result) {
+            sv_commit = &PL_sv_no;
+            if (!sv_yes_mark) 
+                sv_yes_mark = &PL_sv_yes;
+        } else {
+            if (!sv_commit) 
+                sv_commit = &PL_sv_yes;
+            sv_yes_mark = &PL_sv_no;
+        }
+        sv_setsv(sv_err, sv_commit);
+        sv_setsv(sv_mrk, sv_yes_mark);
+    }
     /* restore original high-water mark */
     PL_regmatch_slab  = orig_slab;
     PL_regmatch_state = orig_state;
     /* restore original high-water mark */
     PL_regmatch_slab  = orig_slab;
     PL_regmatch_state = orig_state;
@@ -4661,7 +5170,7 @@ no_silent:
  * rather than incrementing count on every character.  [Er, except utf8.]]
  */
 STATIC I32
  * rather than incrementing count on every character.  [Er, except utf8.]]
  */
 STATIC I32
-S_regrepeat(pTHX_ const regexp *prog, const regnode *p, I32 max)
+S_regrepeat(pTHX_ const regexp *prog, const regnode *p, I32 max, int depth)
 {
     dVAR;
     register char *scan;
 {
     dVAR;
     register char *scan;
@@ -4669,6 +5178,9 @@ S_regrepeat(pTHX_ const regexp *prog, const regnode *p, I32 max)
     register char *loceol = PL_regeol;
     register I32 hardcount = 0;
     register bool do_utf8 = PL_reg_match_utf8;
     register char *loceol = PL_regeol;
     register I32 hardcount = 0;
     register bool do_utf8 = PL_reg_match_utf8;
+#ifndef DEBUGGING
+    PERL_UNUSED_ARG(depth);
+#endif
 
     scan = PL_reginput;
     if (max == REG_INFTY)
 
     scan = PL_reginput;
     if (max == REG_INFTY)
@@ -4892,7 +5404,7 @@ S_regrepeat(pTHX_ const regexp *prog, const regnode *p, I32 max)
            regprop(prog, prop, p);
            PerlIO_printf(Perl_debug_log,
                        "%*s  %s can match %"IVdf" times out of %"IVdf"...\n",
            regprop(prog, prop, p);
            PerlIO_printf(Perl_debug_log,
                        "%*s  %s can match %"IVdf" times out of %"IVdf"...\n",
-                       REPORT_CODE_OFF+1, "", SvPVX_const(prop),(IV)c,(IV)max);
+                       REPORT_CODE_OFF + depth*2, "", SvPVX_const(prop),(IV)c,(IV)max);
        });
     });
 
        });
     });
 
@@ -4912,7 +5424,8 @@ Perl_regclass_swash(pTHX_ const regexp *prog, register const regnode* node, bool
     SV *sw  = NULL;
     SV *si  = NULL;
     SV *alt = NULL;
     SV *sw  = NULL;
     SV *si  = NULL;
     SV *alt = NULL;
-    const struct reg_data * const data = prog ? prog->data : NULL;
+    RXi_GET_DECL(prog,progi);
+    const struct reg_data * const data = prog ? progi->data : NULL;
 
     if (data && data->count) {
        const U32 n = ARG(node);
 
     if (data && data->count) {
        const U32 n = ARG(node);
@@ -5185,56 +5698,60 @@ restore_pos(pTHX_ void *arg)
 STATIC void
 S_to_utf8_substr(pTHX_ register regexp *prog)
 {
 STATIC void
 S_to_utf8_substr(pTHX_ register regexp *prog)
 {
-    if (prog->float_substr && !prog->float_utf8) {
-       SV* const sv = newSVsv(prog->float_substr);
-       prog->float_utf8 = sv;
-       sv_utf8_upgrade(sv);
-       if (SvTAIL(prog->float_substr))
-           SvTAIL_on(sv);
-       if (prog->float_substr == prog->check_substr)
-           prog->check_utf8 = sv;
-    }
-    if (prog->anchored_substr && !prog->anchored_utf8) {
-       SV* const sv = newSVsv(prog->anchored_substr);
-       prog->anchored_utf8 = sv;
-       sv_utf8_upgrade(sv);
-       if (SvTAIL(prog->anchored_substr))
-           SvTAIL_on(sv);
-       if (prog->anchored_substr == prog->check_substr)
-           prog->check_utf8 = sv;
-    }
+    int i = 1;
+    do {
+       if (prog->substrs->data[i].substr
+           && !prog->substrs->data[i].utf8_substr) {
+           SV* const sv = newSVsv(prog->substrs->data[i].substr);
+           prog->substrs->data[i].utf8_substr = sv;
+           sv_utf8_upgrade(sv);
+           if (SvVALID(prog->substrs->data[i].substr)) {
+               const U8 flags = BmFLAGS(prog->substrs->data[i].substr);
+               if (flags & FBMcf_TAIL) {
+                   /* Trim the trailing \n that fbm_compile added last
+                      time.  */
+                   SvCUR_set(sv, SvCUR(sv) - 1);
+                   /* Whilst this makes the SV technically "invalid" (as its
+                      buffer is no longer followed by "\0") when fbm_compile()
+                      adds the "\n" back, a "\0" is restored.  */
+               }
+               fbm_compile(sv, flags);
+           }
+           if (prog->substrs->data[i].substr == prog->check_substr)
+               prog->check_utf8 = sv;
+       }
+    } while (i--);
 }
 
 STATIC void
 S_to_byte_substr(pTHX_ register regexp *prog)
 {
     dVAR;
 }
 
 STATIC void
 S_to_byte_substr(pTHX_ register regexp *prog)
 {
     dVAR;
-    if (prog->float_utf8 && !prog->float_substr) {
-       SV* sv = newSVsv(prog->float_utf8);
-       prog->float_substr = sv;
-       if (sv_utf8_downgrade(sv, TRUE)) {
-           if (SvTAIL(prog->float_utf8))
-               SvTAIL_on(sv);
-       } else {
-           SvREFCNT_dec(sv);
-           prog->float_substr = sv = &PL_sv_undef;
-       }
-       if (prog->float_utf8 == prog->check_utf8)
-           prog->check_substr = sv;
-    }
-    if (prog->anchored_utf8 && !prog->anchored_substr) {
-       SV* sv = newSVsv(prog->anchored_utf8);
-       prog->anchored_substr = sv;
-       if (sv_utf8_downgrade(sv, TRUE)) {
-           if (SvTAIL(prog->anchored_utf8))
-               SvTAIL_on(sv);
-       } else {
-           SvREFCNT_dec(sv);
-           prog->anchored_substr = sv = &PL_sv_undef;
+    int i = 1;
+    do {
+       if (prog->substrs->data[i].utf8_substr
+           && !prog->substrs->data[i].substr) {
+           SV* sv = newSVsv(prog->substrs->data[i].utf8_substr);
+           if (sv_utf8_downgrade(sv, TRUE)) {
+               if (SvVALID(prog->substrs->data[i].utf8_substr)) {
+                   const U8 flags
+                       = BmFLAGS(prog->substrs->data[i].utf8_substr);
+                   if (flags & FBMcf_TAIL) {
+                       /* Trim the trailing \n that fbm_compile added last
+                          time.  */
+                       SvCUR_set(sv, SvCUR(sv) - 1);
+                   }
+                   fbm_compile(sv, flags);
+               }           
+           } else {
+               SvREFCNT_dec(sv);
+               sv = &PL_sv_undef;
+           }
+           prog->substrs->data[i].substr = sv;
+           if (prog->substrs->data[i].utf8_substr == prog->check_utf8)
+               prog->check_substr = sv;
        }
        }
-       if (prog->anchored_utf8 == prog->check_utf8)
-           prog->check_substr = sv;
-    }
+    } while (i--);
 }
 
 /*
 }
 
 /*