This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
(Hopefully) fix coredumps in ByteLoader, which were a side effect of
[perl5.git] / regexec.c
index 663af09..34fd1ac 100644 (file)
--- a/regexec.c
+++ b/regexec.c
 #define        STATIC  static
 #endif
 
-#define REGINCLASS(p,c)  (ANYOF_FLAGS(p) ? reginclass(p,c,0,0) : ANYOF_BITMAP_TEST(p,*(c)))
+#define REGINCLASS(prog,p,c)  (ANYOF_FLAGS(p) ? reginclass(prog,p,c,0,0) : ANYOF_BITMAP_TEST(p,*(c)))
 
 /*
  * Forwards.
@@ -213,11 +213,10 @@ S_regcppush(pTHX_ I32 parenfloor)
                                (IV)(cp), (IV)PL_savestack_ix) : 0); regcpblow(cp)
 
 STATIC char *
-S_regcppop(pTHX_ regexp *rex)
+S_regcppop(pTHX_ const regexp *rex)
 {
     dVAR;
     I32 i;
-    U32 paren = 0;
     char *input;
 
     GET_RE_DEBUG_FLAGS_DECL;
@@ -235,7 +234,7 @@ S_regcppop(pTHX_ regexp *rex)
     for (i -= (REGCP_OTHER_ELEMS - REGCP_FRAME_ELEMS);
         i > 0; i -= REGCP_PAREN_ELEMS) {
        I32 tmps;
-       paren = (U32)SSPOPINT;
+       U32 paren = (U32)SSPOPINT;
        PL_reg_start_tmp[paren] = (char *) SSPOPPTR;
        PL_regstartp[paren] = SSPOPINT;
        tmps = SSPOPINT;
@@ -268,10 +267,10 @@ S_regcppop(pTHX_ regexp *rex)
      * building DynaLoader will fail:
      * "Error: '*' not in typemap in DynaLoader.xs, line 164"
      * --jhi */
-    for (paren = *PL_reglastparen + 1; (I32)paren <= rex->nparens; paren++) {
-       if ((I32)paren > PL_regsize)
-           PL_regstartp[paren] = -1;
-       PL_regendp[paren] = -1;
+    for (i = *PL_reglastparen + 1; i <= rex->nparens; i++) {
+       if (i > PL_regsize)
+           PL_regstartp[i] = -1;
+       PL_regendp[i] = -1;
     }
 #endif
     return input;
@@ -840,8 +839,7 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
                   : strend);
 
        t = s;
-       PL_reg_re = prog;
-        s = find_byclass(prog, prog->regstclass, s, endpos, 1);
+        s = find_byclass(prog, prog->regstclass, s, endpos, NULL);
        if (!s) {
 #ifdef DEBUGGING
            const char *what = NULL;
@@ -933,8 +931,11 @@ Perl_re_intuit_start(pTHX_ regexp *prog, SV *sv, char *strpos,
 }
 
 /* We know what class REx starts with.  Try to find this position... */
+/* if reginfo is NULL, its a dryrun */
+
 STATIC char *
-S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32 norun)
+S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char
+*strend, const regmatch_info *reginfo)
 {
        dVAR;
        const I32 doevery = (prog->reganch & ROPT_SKIP) == 0;
@@ -955,9 +956,9 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                 while (s + (uskip = UTF8SKIP(s)) <= strend) {
                      if ((ANYOF_FLAGS(c) & ANYOF_UNICODE) ||
                          !UTF8_IS_INVARIANT((U8)s[0]) ?
-                         reginclass(c, (U8*)s, 0, do_utf8) :
-                         REGINCLASS(c, (U8*)s)) {
-                          if (tmp && (norun || regtry(prog, s)))
+                         reginclass(prog, c, (U8*)s, 0, do_utf8) :
+                         REGINCLASS(prog, c, (U8*)s)) {
+                          if (tmp && (!reginfo || regtry(reginfo, s)))
                                goto got_it;
                           else
                                tmp = doevery;
@@ -971,12 +972,12 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                 while (s < strend) {
                      STRLEN skip = 1;
 
-                     if (REGINCLASS(c, (U8*)s) ||
+                     if (REGINCLASS(prog, c, (U8*)s) ||
                          (ANYOF_FOLD_SHARP_S(c, s, strend) &&
                           /* The assignment of 2 is intentional:
                            * for the folded sharp s, the skip is 2. */
                           (skip = SHARP_S_SKIP))) {
-                          if (tmp && (norun || regtry(prog, s)))
+                          if (tmp && (!reginfo || regtry(reginfo, s)))
                                goto got_it;
                           else
                                tmp = doevery;
@@ -989,7 +990,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            break;
        case CANY:
            while (s < strend) {
-               if (tmp && (norun || regtry(prog, s)))
+               if (tmp && (!reginfo || regtry(reginfo, s)))
                    goto got_it;
                else
                    tmp = doevery;
@@ -1034,7 +1035,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
          do_exactf:
            e = HOP3c(strend, -((I32)lnc), s);
 
-           if (norun && e < s)
+           if (!reginfo && e < s)
                e = s;                  /* Due to minlen logic of intuit() */
 
            /* The idea in the EXACTF* cases is to first find the
@@ -1063,7 +1064,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                             && (ln == len ||
                                 ibcmp_utf8(s, (char **)0, 0,  do_utf8,
                                            m, (char **)0, ln, (bool)UTF))
-                            && (norun || regtry(prog, s)) )
+                            && (!reginfo || regtry(reginfo, s)) )
                            goto got_it;
                        else {
                             U8 foldbuf[UTF8_MAXBYTES_CASE+1];
@@ -1076,7 +1077,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                                                  (char **)0, foldlen, do_utf8,
                                                  m,
                                                  (char **)0, ln, (bool)UTF))
-                                 && (norun || regtry(prog, s)) )
+                                 && (!reginfo || regtry(reginfo, s)) )
                                  goto got_it;
                        }
                        s += len;
@@ -1102,7 +1103,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                             && (ln == len ||
                                 ibcmp_utf8(s, (char **)0, 0,  do_utf8,
                                            m, (char **)0, ln, (bool)UTF))
-                            && (norun || regtry(prog, s)) )
+                            && (!reginfo || regtry(reginfo, s)) )
                            goto got_it;
                        else {
                             U8 foldbuf[UTF8_MAXBYTES_CASE+1];
@@ -1115,7 +1116,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                                                  (char **)0, foldlen, do_utf8,
                                                  m,
                                                  (char **)0, ln, (bool)UTF))
-                                 && (norun || regtry(prog, s)) )
+                                 && (!reginfo || regtry(reginfo, s)) )
                                  goto got_it;
                        }
                        s += len;
@@ -1129,7 +1130,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                             && (ln == 1 || !(OP(c) == EXACTF
                                              ? ibcmp(s, m, ln)
                                              : ibcmp_locale(s, m, ln)))
-                            && (norun || regtry(prog, s)) )
+                            && (!reginfo || regtry(reginfo, s)) )
                            goto got_it;
                        s++;
                    }
@@ -1139,7 +1140,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                             && (ln == 1 || !(OP(c) == EXACTF
                                              ? ibcmp(s, m, ln)
                                              : ibcmp_locale(s, m, ln)))
-                            && (norun || regtry(prog, s)) )
+                            && (!reginfo || regtry(reginfo, s)) )
                            goto got_it;
                        s++;
                    }
@@ -1165,7 +1166,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                                 isALNUM_LC_utf8((U8*)s)))
                    {
                        tmp = !tmp;
-                       if ((norun || regtry(prog, s)))
+                       if ((!reginfo || regtry(reginfo, s)))
                            goto got_it;
                    }
                    s += uskip;
@@ -1178,13 +1179,13 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                    if (tmp ==
                        !(OP(c) == BOUND ? isALNUM(*s) : isALNUM_LC(*s))) {
                        tmp = !tmp;
-                       if ((norun || regtry(prog, s)))
+                       if ((!reginfo || regtry(reginfo, s)))
                            goto got_it;
                    }
                    s++;
                }
            }
-           if ((!prog->minlen && tmp) && (norun || regtry(prog, s)))
+           if ((!prog->minlen && tmp) && (!reginfo || regtry(reginfo, s)))
                goto got_it;
            break;
        case NBOUNDL:
@@ -1206,7 +1207,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                                 swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8) :
                                 isALNUM_LC_utf8((U8*)s)))
                        tmp = !tmp;
-                   else if ((norun || regtry(prog, s)))
+                   else if ((!reginfo || regtry(reginfo, s)))
                        goto got_it;
                    s += uskip;
                }
@@ -1219,12 +1220,12 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                    if (tmp ==
                        !(OP(c) == NBOUND ? isALNUM(*s) : isALNUM_LC(*s)))
                        tmp = !tmp;
-                   else if ((norun || regtry(prog, s)))
+                   else if ((!reginfo || regtry(reginfo, s)))
                        goto got_it;
                    s++;
                }
            }
-           if ((!prog->minlen && !tmp) && (norun || regtry(prog, s)))
+           if ((!prog->minlen && !tmp) && (!reginfo || regtry(reginfo, s)))
                goto got_it;
            break;
        case ALNUM:
@@ -1232,7 +1233,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                LOAD_UTF8_CHARCLASS_ALNUM();
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1245,7 +1246,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (isALNUM(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1261,7 +1262,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            if (do_utf8) {
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (isALNUM_LC_utf8((U8*)s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1274,7 +1275,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (isALNUM_LC(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1290,7 +1291,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                LOAD_UTF8_CHARCLASS_ALNUM();
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (!swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1303,7 +1304,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (!isALNUM(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1319,7 +1320,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            if (do_utf8) {
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (!isALNUM_LC_utf8((U8*)s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1332,7 +1333,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (!isALNUM_LC(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1348,7 +1349,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                LOAD_UTF8_CHARCLASS_SPACE();
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s, do_utf8)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1361,7 +1362,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (isSPACE(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1377,7 +1378,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            if (do_utf8) {
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (*s == ' ' || isSPACE_LC_utf8((U8*)s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1390,7 +1391,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (isSPACE_LC(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1406,7 +1407,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                LOAD_UTF8_CHARCLASS_SPACE();
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (!(*s == ' ' || swash_fetch(PL_utf8_space,(U8*)s, do_utf8))) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1419,7 +1420,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (!isSPACE(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1435,7 +1436,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            if (do_utf8) {
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (!(*s == ' ' || isSPACE_LC_utf8((U8*)s))) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1448,7 +1449,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (!isSPACE_LC(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1464,7 +1465,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                LOAD_UTF8_CHARCLASS_DIGIT();
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (swash_fetch(PL_utf8_digit,(U8*)s, do_utf8)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1477,7 +1478,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (isDIGIT(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1493,7 +1494,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            if (do_utf8) {
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (isDIGIT_LC_utf8((U8*)s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1506,7 +1507,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (isDIGIT_LC(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1522,7 +1523,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
                LOAD_UTF8_CHARCLASS_DIGIT();
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (!swash_fetch(PL_utf8_digit,(U8*)s, do_utf8)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1535,7 +1536,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (!isDIGIT(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1551,7 +1552,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            if (do_utf8) {
                while (s + (uskip = UTF8SKIP(s)) <= strend) {
                    if (!isDIGIT_LC_utf8((U8*)s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1564,7 +1565,7 @@ S_find_byclass(pTHX_ regexp * prog, regnode *c, char *s, const char *strend, I32
            else {
                while (s < strend) {
                    if (!isDIGIT_LC(*s)) {
-                       if (tmp && (norun || regtry(prog, s)))
+                       if (tmp && (!reginfo || regtry(reginfo, s)))
                            goto got_it;
                        else
                            tmp = doevery;
@@ -1607,21 +1608,16 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
     char *scream_olds = NULL;
     SV* oreplsv = GvSV(PL_replgv);
     const bool do_utf8 = DO_UTF8(sv);
-    const I32 multiline = prog->reganch & PMf_MULTILINE;
+    I32 multiline;
 #ifdef DEBUGGING
-    SV * const dsv0 = PERL_DEBUG_PAD_ZERO(0);
-    SV * const dsv1 = PERL_DEBUG_PAD_ZERO(1);
+    SV* dsv0;
+    SV* dsv1;
 #endif
+    regmatch_info reginfo;  /* create some info to pass to regtry etc */
 
     GET_RE_DEBUG_FLAGS_DECL;
 
     PERL_UNUSED_ARG(data);
-    RX_MATCH_UTF8_set(prog,do_utf8);
-
-    PL_reg_re = prog;
-#ifdef DEBUGGING
-    PL_regnarrate = DEBUG_r_TEST;
-#endif
 
     /* Be paranoid... */
     if (prog == NULL || startpos == NULL) {
@@ -1629,6 +1625,16 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
        return 0;
     }
 
+    multiline = prog->reganch & PMf_MULTILINE;
+    reginfo.prog = prog;
+
+#ifdef DEBUGGING
+    dsv0 = PERL_DEBUG_PAD_ZERO(0);
+    dsv1 = PERL_DEBUG_PAD_ZERO(1);
+#endif
+
+    RX_MATCH_UTF8_set(prog, do_utf8);
+
     minlen = prog->minlen;
     if (strend - startpos < minlen) {
         DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log,
@@ -1649,40 +1655,37 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
        PL_reg_flags |= RF_utf8;
 
     /* Mark beginning of line for ^ and lookbehind. */
-    PL_regbol = startpos;
+    reginfo.bol = startpos; /* XXX not used ??? */
     PL_bostr  = strbeg;
-    PL_reg_sv = sv;
+    reginfo.sv = sv;
 
     /* Mark end of line for $ (and such) */
     PL_regeol = strend;
 
     /* see how far we have to get to not match where we matched before */
-    PL_regtill = startpos+minend;
-
-    /* We start without call_cc context.  */
-    PL_reg_call_cc = 0;
+    reginfo.till = startpos+minend;
 
     /* If there is a "must appear" string, look for it. */
     s = startpos;
 
-    if (prog->reganch & ROPT_GPOS_SEEN) { /* Need to have PL_reg_ganch */
+    if (prog->reganch & ROPT_GPOS_SEEN) { /* Need to set reginfo->ganch */
        MAGIC *mg;
 
        if (flags & REXEC_IGNOREPOS)    /* Means: check only at start */
-           PL_reg_ganch = startpos;
+           reginfo.ganch = startpos;
        else if (sv && SvTYPE(sv) >= SVt_PVMG
                  && SvMAGIC(sv)
                  && (mg = mg_find(sv, PERL_MAGIC_regex_global))
                  && mg->mg_len >= 0) {
-           PL_reg_ganch = strbeg + mg->mg_len; /* Defined pos() */
+           reginfo.ganch = strbeg + mg->mg_len;        /* Defined pos() */
            if (prog->reganch & ROPT_ANCH_GPOS) {
-               if (s > PL_reg_ganch)
+               if (s > reginfo.ganch)
                    goto phooey;
-               s = PL_reg_ganch;
+               s = reginfo.ganch;
            }
        }
        else                            /* pos() not defined */
-           PL_reg_ganch = strbeg;
+           reginfo.ganch = strbeg;
     }
 
     if (!(flags & REXEC_CHECKED) && (prog->check_substr != NULL || prog->check_utf8 != NULL)) {
@@ -1724,7 +1727,7 @@ 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] */
     if (prog->reganch & (ROPT_ANCH & ~ROPT_ANCH_GPOS)) {
-       if (s == startpos && regtry(prog, startpos))
+       if (s == startpos && regtry(&reginfo, startpos))
            goto got_it;
        else if (multiline || (prog->reganch & ROPT_IMPLICIT)
                 || (prog->reganch & ROPT_ANCH_MBOL)) /* XXXX SBOL? */
@@ -1739,7 +1742,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
                if (s == startpos)
                    goto after_try;
                while (1) {
-                   if (regtry(prog, s))
+                   if (regtry(&reginfo, s))
                        goto got_it;
                  after_try:
                    if (s >= end)
@@ -1757,7 +1760,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
                    s--;
                while (s < end) {
                    if (*s++ == '\n') { /* don't need PL_utf8skip here */
-                       if (regtry(prog, s))
+                       if (regtry(&reginfo, s))
                            goto got_it;
                    }
                }               
@@ -1765,7 +1768,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
        }
        goto phooey;
     } else if (prog->reganch & ROPT_ANCH_GPOS) {
-       if (regtry(prog, PL_reg_ganch))
+       if (regtry(&reginfo, reginfo.ganch))
            goto got_it;
        goto phooey;
     }
@@ -1786,7 +1789,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
            while (s < strend) {
                if (*s == ch) {
                    DEBUG_EXECUTE_r( did_match = 1 );
-                   if (regtry(prog, s)) goto got_it;
+                   if (regtry(&reginfo, s)) goto got_it;
                    s += UTF8SKIP(s);
                    while (s < strend && *s == ch)
                        s += UTF8SKIP(s);
@@ -1798,7 +1801,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
            while (s < strend) {
                if (*s == ch) {
                    DEBUG_EXECUTE_r( did_match = 1 );
-                   if (regtry(prog, s)) goto got_it;
+                   if (regtry(&reginfo, s)) goto got_it;
                    s++;
                    while (s < strend && *s == ch)
                        s++;
@@ -1876,14 +1879,14 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
            }
            if (do_utf8) {
                while (s <= last1) {
-                   if (regtry(prog, s))
+                   if (regtry(&reginfo, s))
                        goto got_it;
                    s += UTF8SKIP(s);
                }
            }
            else {
                while (s <= last1) {
-                   if (regtry(prog, s))
+                   if (regtry(&reginfo, s))
                        goto got_it;
                    s++;
                }
@@ -1915,7 +1918,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
            int len0;
            int len1;
 
-           regprop(prop, c);
+           regprop(prog, prop, c);
            s0 = UTF ?
              pv_uni_display(dsv0, (U8*)SvPVX_const(prop), SvCUR(prop), 60,
                             UNI_DISPLAY_REGEX) :
@@ -1929,7 +1932,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
                          len0, len0, s0,
                          len1, len1, s1);
        });
-        if (find_byclass(prog, c, s, strend, 0))
+        if (find_byclass(prog, c, s, strend, &reginfo))
            goto got_it;
        DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log, "Contradicts stclass...\n"));
     }
@@ -1987,7 +1990,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
        /* We don't know much -- general case. */
        if (do_utf8) {
            for (;;) {
-               if (regtry(prog, s))
+               if (regtry(&reginfo, s))
                    goto got_it;
                if (s >= strend)
                    break;
@@ -1996,7 +1999,7 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
        }
        else {
            do {
-               if (regtry(prog, s))
+               if (regtry(&reginfo, s))
                    goto got_it;
            } while (s++ < strend);
        }
@@ -2062,13 +2065,13 @@ phooey:
  - regtry - try match at specific point
  */
 STATIC I32                     /* 0 failure, 1 success */
-S_regtry(pTHX_ regexp *prog, char *startpos)
+S_regtry(pTHX_ const regmatch_info *reginfo, char *startpos)
 {
     dVAR;
-    register I32 i;
     register I32 *sp;
     register I32 *ep;
     CHECKPOINT lastcp;
+    regexp *prog = reginfo->prog;
     GET_RE_DEBUG_FLAGS_DECL;
 
 #ifdef DEBUGGING
@@ -2090,21 +2093,21 @@ S_regtry(pTHX_ regexp *prog, char *startpos)
        /* SAVEI8(cxstack[cxstack_ix].blk_gimme);
           cxstack[cxstack_ix].blk_gimme = G_SCALAR; */
 
-       if (PL_reg_sv) {
+       if (reginfo->sv) {
            /* Make $_ available to executed code. */
-           if (PL_reg_sv != DEFSV) {
+           if (reginfo->sv != DEFSV) {
                SAVE_DEFSV;
-               DEFSV = PL_reg_sv;
+               DEFSV = reginfo->sv;
            }
        
-           if (!(SvTYPE(PL_reg_sv) >= SVt_PVMG && SvMAGIC(PL_reg_sv)
-                 && (mg = mg_find(PL_reg_sv, PERL_MAGIC_regex_global)))) {
+           if (!(SvTYPE(reginfo->sv) >= SVt_PVMG && SvMAGIC(reginfo->sv)
+                 && (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);
 #endif
-               mg = sv_magicext(PL_reg_sv, (SV*)0, PERL_MAGIC_regex_global,
+               mg = sv_magicext(reginfo->sv, (SV*)0, PERL_MAGIC_regex_global,
                                 &PL_vtbl_mglob, NULL, 0);
                mg->mg_len = -1;
            }
@@ -2180,6 +2183,7 @@ S_regtry(pTHX_ regexp *prog, char *startpos)
     sp = prog->startp;
     ep = prog->endp;
     if (prog->nparens) {
+       register I32 i;
        for (i = prog->nparens; i > (I32)*PL_reglastparen; i--) {
            *++sp = -1;
            *++ep = -1;
@@ -2187,7 +2191,7 @@ S_regtry(pTHX_ regexp *prog, char *startpos)
     }
 #endif
     REGCP_SET(lastcp);
-    if (regmatch(prog, prog->program + 1)) {
+    if (regmatch(reginfo, prog->program + 1)) {
        prog->endp[0] = PL_reginput - PL_bostr;
        return 1;
     }
@@ -2214,6 +2218,7 @@ typedef struct {
     regnode *next;
     char *locinput;
     I32 nextchr;
+    int minmod;
 #ifdef DEBUGGING
     int regindent;
 #endif
@@ -2307,6 +2312,44 @@ S_push_slab(pTHX)
     goto start_recurse; \
     resume_point_##where:
 
+
+/* push a new regex state. Set newst to point to it */
+
+#define PUSH_STATE(newst, resume) \
+    depth++;   \
+    DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log, "PUSH STATE(%d)\n", depth)); \
+    st->scan = scan;   \
+    st->next = next;   \
+    st->n = n; \
+    st->locinput = locinput;   \
+    st->resume_state = resume; \
+    newst = st+1;   \
+    if (newst >  &(PL_regmatch_slab->states[PERL_REGMATCH_SLAB_SLOTS-1])) \
+       newst = S_push_slab(aTHX);  \
+    PL_regmatch_state = newst; \
+    newst->cc = 0;  \
+    newst->minmod = 0; \
+    newst->sw = 0;  \
+    newst->logical = 0;        \
+    newst->unwind = 0; \
+    locinput = PL_reginput; \
+    nextchr = UCHARAT(locinput);    
+
+#define POP_STATE \
+    DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log, "POP STATE(%d)\n", depth)); \
+    depth--; \
+    st--; \
+    if (st < &PL_regmatch_slab->states[0]) { \
+       PL_regmatch_slab = PL_regmatch_slab->prev; \
+       st = &PL_regmatch_slab->states[PERL_REGMATCH_SLAB_SLOTS-1]; \
+    } \
+    PL_regmatch_state = st; \
+    scan       = st->scan; \
+    next       = st->next; \
+    n          = st->n; \
+    locinput   = st->locinput; \
+    nextchr = UCHARAT(locinput);
+
 /*
  - regmatch - main matching routine
  *
@@ -2414,12 +2457,14 @@ S_push_slab(pTHX)
  
 
 STATIC I32                     /* 0 failure, 1 success */
-S_regmatch(pTHX_ regexp *rex, regnode *prog)
+S_regmatch(pTHX_ const regmatch_info *reginfo, regnode *prog)
 {
     dVAR;
     register const bool do_utf8 = PL_reg_match_utf8;
     const U32 uniflags = UTF8_ALLOW_DEFAULT;
 
+    regexp *rex = reginfo->prog;
+
     regmatch_slab  *orig_slab;
     regmatch_state *orig_state;
 
@@ -2437,6 +2482,8 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
     bool result;           /* return value of S_regmatch */
     regnode *inner;        /* Next node in internal branch. */
     int depth = 0;         /* depth of recursion */
+    regmatch_state *newst;  /* when pushing a state, this is the new one */
+    regmatch_state *cur_eval = NULL;  /* most recent (??{}) state */
     
 #ifdef DEBUGGING
     SV *re_debug_flags = NULL;
@@ -2499,7 +2546,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                pref0_len = 0;
            if (pref0_len > pref_len)
                pref0_len = pref_len;
-           regprop(prop, scan);
+           regprop(rex, prop, scan);
            {
              const char * const s0 =
                do_utf8 && OP(scan) != CANY ?
@@ -2546,7 +2593,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
        case BOL:
            if (locinput == PL_bostr)
            {
-               /* regtill = regbol; */
+               /* reginfo->till = reginfo->bol; */
                break;
            }
            sayNO;
@@ -2562,7 +2609,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                break;
            sayNO;
        case GPOS:
-           if (locinput == PL_reg_ganch)
+           if (locinput == reginfo->ganch)
                break;
            sayNO;
        case EOL:
@@ -2641,7 +2688,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
 
                /* what trie are we using right now */
                reg_trie_data *trie
-                   = (reg_trie_data*)PL_reg_re->data->data[ ARG( scan ) ];
+                   = (reg_trie_data*)rex->data->data[ ARG( scan ) ];
                st->u.trie.accepted = 0; /* how many accepting states we have seen */
                result = 0;
 
@@ -2767,7 +2814,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
 
                if ( st->u.trie.accepted == 1 ) {
                    DEBUG_EXECUTE_r({
-                        SV **tmp = av_fetch( trie->words, st->u.trie.accept_buff[ 0 ].wordnum-1, 0 );
+                        SV ** const tmp = av_fetch( trie->words, st->u.trie.accept_buff[ 0 ].wordnum-1, 0 );
                                PerlIO_printf( Perl_debug_log,
                            "%*s  %sonly one match : #%d <%s>%s\n",
                            REPORT_CODE_OFF+PL_regindent*2, "", PL_colors[4],
@@ -2806,7 +2853,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                        }
                        DEBUG_EXECUTE_r({
                            reg_trie_data * const trie = (reg_trie_data*)
-                                           PL_reg_re->data->data[ARG(scan)];
+                                           rex->data->data[ARG(scan)];
                            SV ** const tmp = av_fetch( trie->words, st->u.trie.accept_buff[ best ].wordnum - 1, 0 );
                            PerlIO_printf( Perl_debug_log, "%*s  %strying alternation #%d <%s> at 0x%p%s\n",
                                REPORT_CODE_OFF+PL_regindent*2, "", PL_colors[4],
@@ -2948,7 +2995,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
            if (do_utf8) {
                STRLEN inclasslen = PL_regeol - locinput;
 
-               if (!reginclass(scan, (U8*)locinput, &inclasslen, do_utf8))
+               if (!reginclass(rex, scan, (U8*)locinput, &inclasslen, do_utf8))
                    sayNO_ANYOF;
                if (locinput >= PL_regeol)
                    sayNO;
@@ -2959,7 +3006,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
            else {
                if (nextchr < 0)
                    nextchr = UCHARAT(locinput);
-               if (!REGINCLASS(scan, (U8*)locinput))
+               if (!REGINCLASS(rex, scan, (U8*)locinput))
                    sayNO_ANYOF;
                if (!nextchr && locinput >= PL_regeol)
                    sayNO;
@@ -3261,12 +3308,11 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                OP_4tree * const oop = PL_op;
                COP * const ocurcop = PL_curcop;
                PAD *old_comppad;
-               struct regexp * const oreg = PL_reg_re;
            
                n = ARG(scan);
-               PL_op = (OP_4tree*)PL_reg_re->data->data[n];
+               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*)PL_reg_re->data->data[n + 2]);
+               PAD_SAVE_LOCAL(old_comppad, (PAD*)rex->data->data[n + 2]);
                PL_regendp[0] = PL_reg_magic->mg_len = locinput - PL_bostr;
 
                CALLRUNOPS(aTHX);                       /* Scalar context. */
@@ -3281,7 +3327,6 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                PL_op = oop;
                PAD_RESTORE_LOCAL(old_comppad);
                PL_curcop = ocurcop;
-               PL_reg_re = oreg;
                if (!st->logical) {
                    /* /(?{...})/ */
                    sv_setsv(save_scalar(PL_replgv), ret);
@@ -3290,9 +3335,6 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
            }
            if (st->logical == 2) { /* Postponed subexpression: /(??{...})/ */
                regexp *re;
-               re_cc_state state;
-               int toggleutf;
-
                {
                    /* extract RE object from returned value; compiling if
                     * necessary */
@@ -3329,6 +3371,9 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                        PL_regsize = osize;
                    }
                }
+
+               /* run the pattern returned from (??{...}) */
+
                DEBUG_EXECUTE_r(
                    PerlIO_printf(Perl_debug_log,
                                  "Entering embedded \"%s%.60s%s%s\"\n",
@@ -3337,62 +3382,33 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                                  PL_colors[1],
                                  (strlen(re->precomp) > 60 ? "..." : ""))
                    );
-               state.node = next;
-               state.prev = PL_reg_call_cc;
-               state.cc = st->cc;
-               state.re = PL_reg_re;
 
-               st->cc = 0;
-           
                st->u.eval.cp = regcppush(0);   /* Save *all* the positions. */
                REGCP_SET(st->u.eval.lastcp);
-               PL_reg_re = re;
-               state.ss = PL_savestack_ix;
                *PL_reglastparen = 0;
                *PL_reglastcloseparen = 0;
-               PL_reg_call_cc = &state;
                PL_reginput = locinput;
-               toggleutf = ((PL_reg_flags & RF_utf8) != 0) ^
-                           ((re->reganch & ROPT_UTF8) != 0);
-               if (toggleutf) PL_reg_flags ^= RF_utf8;
-
-               /* XXXX This is too dramatic a measure... */
-               PL_reg_maxiter = 0;
-
-               /* XXX the only recursion left in regmatch() */
-               if (regmatch(re, re->program + 1)) {
-                   /* Even though we succeeded, we need to restore
-                      global variables, since we may be wrapped inside
-                      SUSPEND, thus the match may be not finished yet. */
-
-                   /* XXXX Do this only if SUSPENDed? */
-                   PL_reg_call_cc = state.prev;
-                   st->cc = state.cc;
-                   PL_reg_re = state.re;
-
-                   if (toggleutf) PL_reg_flags ^= RF_utf8;
-
-                   /* XXXX This is too dramatic a measure... */
-                   PL_reg_maxiter = 0;
-
-                   /* These are needed even if not SUSPEND. */
-                   ReREFCNT_dec(re);
-                   regcpblow(st->u.eval.cp);
-                   sayYES;
-               }
-               ReREFCNT_dec(re);
-               REGCP_UNWIND(st->u.eval.lastcp);
-               regcppop(rex);
-               PL_reg_call_cc = state.prev;
-               st->cc = state.cc;
-               PL_reg_re = state.re;
-               if (toggleutf) PL_reg_flags ^= RF_utf8;
 
                /* XXXX This is too dramatic a measure... */
                PL_reg_maxiter = 0;
 
                st->logical = 0;
-               sayNO;
+               st->u.eval.toggleutf = ((PL_reg_flags & RF_utf8) != 0) ^
+                           ((re->reganch & ROPT_UTF8) != 0);
+               if (st->u.eval.toggleutf) PL_reg_flags ^= RF_utf8;
+               st->u.eval.prev_rex = rex;
+               rex = re;
+
+               st->u.eval.prev_eval = cur_eval;
+               st->u.eval.prev_slab = PL_regmatch_slab;
+               st->u.eval.depth = depth;
+               cur_eval = st;
+               PUSH_STATE(newst, resume_EVAL);
+               st = newst;
+
+               /* now continue  from first node in postoned RE */
+               next = re->program + 1;
+               break;
                /* NOTREACHED */
            }
            /* /(?(?{...})X|Y)/ */
@@ -3512,7 +3528,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                /* No need to save/restore up to this paren */
                I32 parenfloor = scan->flags;
 
-               if (OP(PREVOPER(next)) == NOTHING) /* LONGJMP */
+               if (next && (OP(PREVOPER(next)) == NOTHING)) /* LONGJMP */
                    next += ARG(next);
                /* XXXX Probably it is better to teach regpush to support
                   parenfloor > PL_regsize... */
@@ -3768,7 +3784,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
            {
                I32 type;
                type = OP(scan);
-               if (OP(next) != type)   /* No choice. */
+               if (!next || OP(next) != type)  /* No choice. */
                    next = inner;       /* Avoid recursion. */
                else {
                    const I32 lastparen = *PL_reglastparen;
@@ -3785,6 +3801,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                    uw->next = next;
                    uw->locinput = locinput;
                    uw->nextchr = nextchr;
+                   uw->minmod = st->minmod;
 #ifdef DEBUGGING
                    uw->regindent = ++PL_regindent;
 #endif
@@ -4068,7 +4085,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
            PL_reginput = locinput;
            if (st->minmod) {
                st->minmod = 0;
-               if (st->ln && regrepeat(scan, st->ln) < st->ln)
+               if (st->ln && regrepeat(rex, scan, st->ln) < st->ln)
                    sayNO;
                locinput = PL_reginput;
                REGCP_SET(st->u.plus.lastcp);
@@ -4140,7 +4157,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                        /* PL_reginput == old now */
                        if (locinput != st->u.plus.old) {
                            st->ln = 1; /* Did some */
-                           if (regrepeat(scan, st->u.plus.count) < st->u.plus.count)
+                           if (regrepeat(rex, scan, st->u.plus.count) < st->u.plus.count)
                                sayNO;
                        }
                        /* PL_reginput == locinput now */
@@ -4184,7 +4201,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                    }
                    /* Couldn't or didn't -- move forward. */
                    PL_reginput = locinput;
-                   if (regrepeat(scan, 1)) {
+                   if (regrepeat(rex, scan, 1)) {
                        st->ln++;
                        locinput = PL_reginput;
                    }
@@ -4193,7 +4210,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                }
            }
            else {
-               n = regrepeat(scan, n);
+               n = regrepeat(rex, scan, n);
                locinput = PL_reginput;
                if (st->ln < n && PL_regkind[(U8)OP(next)] == EOL &&
                    (OP(next) != MEOL ||
@@ -4234,55 +4251,54 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
            sayNO;
            break;
        case END:
-           if (PL_reg_call_cc) {
-               st->u.end.cur_call_cc = PL_reg_call_cc;
-               st->u.end.end_re = PL_reg_re;
+           if (cur_eval) {
+               /* we have successfully completed the execution of a
+                * postponed re. Pop all states back to the last EVAL
+                * then continue with the node following the (??{...})
+                */
+
+               /* this simulates a POP_STATE, except that it pops several
+                * levels, and doesn't restore locinput */
 
-               /* Save *all* the positions. */
-               st->u.end.cp = regcppush(0);
-               REGCP_SET(st->u.end.lastcp);
+               st = cur_eval;
+               PL_regmatch_slab = st->u.eval.prev_slab;
+               cur_eval = st->u.eval.prev_eval;
+               depth = st->u.eval.depth;
 
-               /* Restore parens of the caller. */
+               PL_regmatch_state = st;
+               scan    = st->scan;
+               next    = st->next;
+               n               = st->n;
+
+               if (st->u.eval.toggleutf)
+                   PL_reg_flags ^= RF_utf8;
+               ReREFCNT_dec(rex);
+               rex = st->u.eval.prev_rex;
+               /* XXXX This is too dramatic a measure... */
+               PL_reg_maxiter = 0;
+
+               /* Restore parens of the caller without popping the
+                * savestack */
                {
                    I32 tmp = PL_savestack_ix;
-                   PL_savestack_ix = PL_reg_call_cc->ss;
+                   PL_savestack_ix = st->u.eval.lastcp;
                    regcppop(rex);
                    PL_savestack_ix = tmp;
                }
 
-               /* Make position available to the callcc. */
-               PL_reginput = locinput;
 
-               PL_reg_re = PL_reg_call_cc->re;
-               st->u.end.savecc = st->cc;
-               st->cc = PL_reg_call_cc->cc;
-               PL_reg_call_cc = PL_reg_call_cc->prev;
-               REGMATCH(st->u.end.cur_call_cc->node, END);
-               /*** all unsaved local vars undefined at this point */
-               if (result) {
-                   PL_reg_call_cc = st->u.end.cur_call_cc;
-                   regcpblow(st->u.end.cp);
-                   sayYES;
-               }
-               REGCP_UNWIND(st->u.end.lastcp);
-               regcppop(rex);
-               PL_reg_call_cc = st->u.end.cur_call_cc;
-               st->cc = st->u.end.savecc;
-               PL_reg_re = st->u.end.end_re;
+               PL_reginput = locinput;
+               /* resume at node following the (??{...}) */
+               break;
 
-               DEBUG_EXECUTE_r(
-                   PerlIO_printf(Perl_debug_log,
-                                 "%*s  continuation failed...\n",
-                                 REPORT_CODE_OFF+PL_regindent*2, "")
-                   );
-               sayNO_SILENT;
            }
-           if (locinput < PL_regtill) {
+
+           if (locinput < reginfo->till) {
                DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log,
                                      "%sMatch possible, but length=%ld is smaller than requested=%ld, failing!%s\n",
                                      PL_colors[4],
                                      (long)(locinput - PL_reg_starttry),
-                                     (long)(PL_regtill - PL_reg_starttry),
+                                     (long)(reginfo->till - PL_reg_starttry),
                                      PL_colors[5]));
                sayNO_FINAL;            /* Cannot match: too short. */
            }
@@ -4378,7 +4394,6 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
            oldst->next = next;
            oldst->n = n;
            oldst->locinput = locinput;
-           oldst->reg_call_cc = PL_reg_call_cc;
 
            st->cc = oldst->cc;
            locinput = PL_reginput;
@@ -4393,6 +4408,8 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
        }
     }
 
+
+
     /*
     * We get here only if there's trouble -- normally "case END" is
     * the terminating point.
@@ -4417,7 +4434,56 @@ yes:
 #endif
 
     result = 1;
-    goto exit_level;
+    /* XXX this is duplicate(ish) code to that in the do_no section.
+     * eventually a yes should just pop the whole stack */
+    if (depth) {
+       /* restore previous state and re-enter */
+       POP_STATE;
+
+       switch (st->resume_state) {
+       case resume_TRIE1:
+           goto resume_point_TRIE1;
+       case resume_TRIE2:
+           goto resume_point_TRIE2;
+       case resume_EVAL:
+           break;
+       case resume_CURLYX:
+           goto resume_point_CURLYX;
+       case resume_WHILEM1:
+           goto resume_point_WHILEM1;
+       case resume_WHILEM2:
+           goto resume_point_WHILEM2;
+       case resume_WHILEM3:
+           goto resume_point_WHILEM3;
+       case resume_WHILEM4:
+           goto resume_point_WHILEM4;
+       case resume_WHILEM5:
+           goto resume_point_WHILEM5;
+       case resume_WHILEM6:
+           goto resume_point_WHILEM6;
+       case resume_CURLYM1:
+           goto resume_point_CURLYM1;
+       case resume_CURLYM2:
+           goto resume_point_CURLYM2;
+       case resume_CURLYM3:
+           goto resume_point_CURLYM3;
+       case resume_CURLYM4:
+           goto resume_point_CURLYM4;
+       case resume_IFMATCH:
+           goto resume_point_IFMATCH;
+       case resume_PLUS1:
+           goto resume_point_PLUS1;
+       case resume_PLUS2:
+           goto resume_point_PLUS2;
+       case resume_PLUS3:
+           goto resume_point_PLUS3;
+       case resume_PLUS4:
+           goto resume_point_PLUS4;
+       default:
+           Perl_croak(aTHX_ "regexp resume memory corruption");
+       }
+    }
+    goto final_exit;
 
 no:
     DEBUG_EXECUTE_r(
@@ -4443,6 +4509,7 @@ do_no:
                PL_regendp[n] = -1;
            *PL_reglastparen = n;
            scan = next = uwb->next;
+           st->minmod = uwb->minmod;
            if ( !scan ||
                 OP(scan) != (uwb->type == RE_UNWIND_BRANCH
                              ? BRANCH : BRANCHJ) ) {           /* Failure */
@@ -4476,33 +4543,37 @@ do_no:
        }
        /* NOTREACHED */
     }
+
 #ifdef DEBUGGING
     PL_regindent--;
 #endif
     result = 0;
-exit_level:
-
-    if (depth--) {
-       /* restore previous state and re-enter */
-       st--;
-       if (st < &PL_regmatch_slab->states[0]) {
-           PL_regmatch_slab = PL_regmatch_slab->prev;
-           st = &PL_regmatch_slab->states[PERL_REGMATCH_SLAB_SLOTS-1];
-       }
-       PL_regmatch_state = st;
-
-       PL_reg_call_cc  = st->reg_call_cc;
-       scan            = st->scan;
-       next            = st->next;
-       n               = st->n;
-       locinput        = st->locinput;
-       nextchr = UCHARAT(locinput);
 
+    if (depth) {
+       /* there's a previous state to backtrack to */
+       POP_STATE;
        switch (st->resume_state) {
        case resume_TRIE1:
            goto resume_point_TRIE1;
        case resume_TRIE2:
            goto resume_point_TRIE2;
+       case resume_EVAL:
+           /* we have failed an (??{...}). Restore state to the outer re
+            * then re-throw the failure */
+           if (st->u.eval.toggleutf)
+               PL_reg_flags ^= RF_utf8;
+           ReREFCNT_dec(rex);
+           rex = st->u.eval.prev_rex;
+           cur_eval = st->u.eval.prev_eval;
+
+           /* XXXX This is too dramatic a measure... */
+           PL_reg_maxiter = 0;
+
+           PL_reginput = locinput;
+           REGCP_UNWIND(st->u.eval.lastcp);
+           regcppop(rex);
+           goto do_no;
+
        case resume_CURLYX:
            goto resume_point_CURLYX;
        case resume_WHILEM1:
@@ -4535,13 +4606,13 @@ exit_level:
            goto resume_point_PLUS3;
        case resume_PLUS4:
            goto resume_point_PLUS4;
-       case resume_END:
-           goto resume_point_END;
        default:
            Perl_croak(aTHX_ "regexp resume memory corruption");
        }
-       /* NOTREACHED */
     }
+
+final_exit:
+
     /* restore original high-water mark */
     PL_regmatch_slab  = orig_slab;
     PL_regmatch_state = orig_state;
@@ -4570,7 +4641,7 @@ exit_level:
  * rather than incrementing count on every character.  [Er, except utf8.]]
  */
 STATIC I32
-S_regrepeat(pTHX_ const regnode *p, I32 max)
+S_regrepeat(pTHX_ const regexp *prog, const regnode *p, I32 max)
 {
     dVAR;
     register char *scan;
@@ -4633,12 +4704,12 @@ S_regrepeat(pTHX_ const regnode *p, I32 max)
        if (do_utf8) {
            loceol = PL_regeol;
            while (hardcount < max && scan < loceol &&
-                  reginclass(p, (U8*)scan, 0, do_utf8)) {
+                  reginclass(prog, p, (U8*)scan, 0, do_utf8)) {
                scan += UTF8SKIP(scan);
                hardcount++;
            }
        } else {
-           while (scan < loceol && REGINCLASS(p, (U8*)scan))
+           while (scan < loceol && REGINCLASS(prog, p, (U8*)scan))
                scan++;
        }
        break;
@@ -4799,7 +4870,7 @@ S_regrepeat(pTHX_ const regnode *p, I32 max)
                SV * const prop = sv_newmortal();
                 GET_RE_DEBUG_FLAGS;
                 DEBUG_EXECUTE_r({
-               regprop(prop, p);
+               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);
@@ -4815,13 +4886,13 @@ S_regrepeat(pTHX_ const regnode *p, I32 max)
 */
 
 SV *
-Perl_regclass_swash(pTHX_ register const regnode* node, bool doinit, SV** listsvp, SV **altsvp)
+Perl_regclass_swash(pTHX_ const regexp *prog, register const regnode* node, bool doinit, SV** listsvp, SV **altsvp)
 {
     dVAR;
     SV *sw  = NULL;
     SV *si  = NULL;
     SV *alt = NULL;
-    const struct reg_data *data = PL_reg_re->data;
+    const struct reg_data *data = prog ? prog->data : NULL;
 
     if (data && data->count) {
        const U32 n = ARG(node);
@@ -4869,7 +4940,7 @@ Perl_regclass_swash(pTHX_ register const regnode* node, bool doinit, SV** listsv
  */
 
 STATIC bool
-S_reginclass(pTHX_ register const regnode *n, register const U8* p, STRLEN* lenp, register bool do_utf8)
+S_reginclass(pTHX_ const regexp *prog, register const regnode *n, register const U8* p, STRLEN* lenp, register bool do_utf8)
 {
     dVAR;
     const char flags = ANYOF_FLAGS(n);
@@ -4898,7 +4969,7 @@ S_reginclass(pTHX_ register const regnode *n, register const U8* p, STRLEN* lenp
            match = TRUE;
        if (!match) {
            AV *av;
-           SV * const sw = regclass_swash(n, TRUE, 0, (SV**)&av);
+           SV * const sw = regclass_swash(prog, n, TRUE, 0, (SV**)&av);
        
            if (sw) {
                if (swash_fetch(sw, p, do_utf8))
@@ -5051,7 +5122,7 @@ static void
 restore_pos(pTHX_ void *arg)
 {
     dVAR;
-    regexp *rex = (regexp *)arg;
+    regexp * const rex = (regexp *)arg;
     if (PL_reg_eval_set) {
        if (PL_reg_oldsaved) {
            rex->subbeg = PL_reg_oldsaved;
@@ -5071,8 +5142,8 @@ STATIC void
 S_to_utf8_substr(pTHX_ register regexp *prog)
 {
     if (prog->float_substr && !prog->float_utf8) {
-       SV* sv;
-       prog->float_utf8 = sv = newSVsv(prog->float_substr);
+       SV* const sv = newSVsv(prog->float_substr);
+       prog->float_utf8 = sv;
        sv_utf8_upgrade(sv);
        if (SvTAIL(prog->float_substr))
            SvTAIL_on(sv);
@@ -5080,8 +5151,8 @@ S_to_utf8_substr(pTHX_ register regexp *prog)
            prog->check_utf8 = sv;
     }
     if (prog->anchored_substr && !prog->anchored_utf8) {
-       SV* sv;
-       prog->anchored_utf8 = sv = newSVsv(prog->anchored_substr);
+       SV* const sv = newSVsv(prog->anchored_substr);
+       prog->anchored_utf8 = sv;
        sv_utf8_upgrade(sv);
        if (SvTAIL(prog->anchored_substr))
            SvTAIL_on(sv);
@@ -5095,8 +5166,8 @@ S_to_byte_substr(pTHX_ register regexp *prog)
 {
     dVAR;
     if (prog->float_utf8 && !prog->float_substr) {
-       SV* sv;
-       prog->float_substr = sv = newSVsv(prog->float_utf8);
+       SV* sv = newSVsv(prog->float_utf8);
+       prog->float_substr = sv;
        if (sv_utf8_downgrade(sv, TRUE)) {
            if (SvTAIL(prog->float_utf8))
                SvTAIL_on(sv);
@@ -5108,8 +5179,8 @@ S_to_byte_substr(pTHX_ register regexp *prog)
            prog->check_substr = sv;
     }
     if (prog->anchored_utf8 && !prog->anchored_substr) {
-       SV* sv;
-       prog->anchored_substr = sv = newSVsv(prog->anchored_utf8);
+       SV* sv = newSVsv(prog->anchored_utf8);
+       prog->anchored_substr = sv;
        if (sv_utf8_downgrade(sv, TRUE)) {
            if (SvTAIL(prog->anchored_utf8))
                SvTAIL_on(sv);