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 71eab5b..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.
@@ -839,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;
@@ -932,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, const 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;
@@ -954,9 +956,9 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                 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;
@@ -970,12 +972,12 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                 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;
@@ -988,7 +990,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            break;
        case CANY:
            while (s < strend) {
-               if (tmp && (norun || regtry(prog, s)))
+               if (tmp && (!reginfo || regtry(reginfo, s)))
                    goto got_it;
                else
                    tmp = doevery;
@@ -1033,7 +1035,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
          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
@@ -1062,7 +1064,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                             && (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];
@@ -1075,7 +1077,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                                                  (char **)0, foldlen, do_utf8,
                                                  m,
                                                  (char **)0, ln, (bool)UTF))
-                                 && (norun || regtry(prog, s)) )
+                                 && (!reginfo || regtry(reginfo, s)) )
                                  goto got_it;
                        }
                        s += len;
@@ -1101,7 +1103,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                             && (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];
@@ -1114,7 +1116,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                                                  (char **)0, foldlen, do_utf8,
                                                  m,
                                                  (char **)0, ln, (bool)UTF))
-                                 && (norun || regtry(prog, s)) )
+                                 && (!reginfo || regtry(reginfo, s)) )
                                  goto got_it;
                        }
                        s += len;
@@ -1128,7 +1130,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                             && (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++;
                    }
@@ -1138,7 +1140,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                             && (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++;
                    }
@@ -1164,7 +1166,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                                 isALNUM_LC_utf8((U8*)s)))
                    {
                        tmp = !tmp;
-                       if ((norun || regtry(prog, s)))
+                       if ((!reginfo || regtry(reginfo, s)))
                            goto got_it;
                    }
                    s += uskip;
@@ -1177,13 +1179,13 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                    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:
@@ -1205,7 +1207,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                                 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;
                }
@@ -1218,12 +1220,12 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                    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:
@@ -1231,7 +1233,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                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;
@@ -1244,7 +1246,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1260,7 +1262,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1273,7 +1275,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1289,7 +1291,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                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;
@@ -1302,7 +1304,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1318,7 +1320,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1331,7 +1333,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1347,7 +1349,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                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;
@@ -1360,7 +1362,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1376,7 +1378,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1389,7 +1391,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1405,7 +1407,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                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;
@@ -1418,7 +1420,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1434,7 +1436,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1447,7 +1449,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1463,7 +1465,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                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;
@@ -1476,7 +1478,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1492,7 +1494,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1505,7 +1507,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1521,7 +1523,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
                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;
@@ -1534,7 +1536,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1550,7 +1552,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1563,7 +1565,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, const char *stren
            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;
@@ -1606,11 +1608,12 @@ 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;
 
@@ -1622,9 +1625,12 @@ Perl_regexec_flags(pTHX_ register regexp *prog, char *stringarg, register char *
        return 0;
     }
 
-    PL_reg_re = prog;
+    multiline = prog->reganch & PMf_MULTILINE;
+    reginfo.prog = prog;
+
 #ifdef DEBUGGING
-    PL_regnarrate = DEBUG_r_TEST;
+    dsv0 = PERL_DEBUG_PAD_ZERO(0);
+    dsv1 = PERL_DEBUG_PAD_ZERO(1);
 #endif
 
     RX_MATCH_UTF8_set(prog, do_utf8);
@@ -1649,37 +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;
+    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)) {
@@ -1721,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? */
@@ -1736,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)
@@ -1754,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;
                    }
                }               
@@ -1762,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;
     }
@@ -1783,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);
@@ -1795,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++;
@@ -1873,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++;
                }
@@ -1912,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) :
@@ -1926,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"));
     }
@@ -1984,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;
@@ -1993,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);
        }
@@ -2059,12 +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 *sp;
     register I32 *ep;
     CHECKPOINT lastcp;
+    regexp *prog = reginfo->prog;
     GET_RE_DEBUG_FLAGS_DECL;
 
 #ifdef DEBUGGING
@@ -2086,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;
            }
@@ -2184,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;
     }
@@ -2211,6 +2218,7 @@ typedef struct {
     regnode *next;
     char *locinput;
     I32 nextchr;
+    int minmod;
 #ifdef DEBUGGING
     int regindent;
 #endif
@@ -2449,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;
 
@@ -2536,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 ?
@@ -2583,7 +2593,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
        case BOL:
            if (locinput == PL_bostr)
            {
-               /* regtill = regbol; */
+               /* reginfo->till = reginfo->bol; */
                break;
            }
            sayNO;
@@ -2599,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:
@@ -2678,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;
 
@@ -2843,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],
@@ -2985,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;
@@ -2996,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;
@@ -3298,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. */
@@ -3318,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);
@@ -3389,9 +3397,7 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                            ((re->reganch & ROPT_UTF8) != 0);
                if (st->u.eval.toggleutf) PL_reg_flags ^= RF_utf8;
                st->u.eval.prev_rex = rex;
-               assert(rex == PL_reg_re); /* XXX */
                rex = re;
-               PL_reg_re = rex; /* XXX */
 
                st->u.eval.prev_eval = cur_eval;
                st->u.eval.prev_slab = PL_regmatch_slab;
@@ -3522,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... */
@@ -3778,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;
@@ -3795,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
@@ -4078,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);
@@ -4150,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 */
@@ -4194,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;
                    }
@@ -4203,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 ||
@@ -4267,7 +4274,6 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
                    PL_reg_flags ^= RF_utf8;
                ReREFCNT_dec(rex);
                rex = st->u.eval.prev_rex;
-               PL_reg_re = rex; /* XXX */
                /* XXXX This is too dramatic a measure... */
                PL_reg_maxiter = 0;
 
@@ -4287,12 +4293,12 @@ S_regmatch(pTHX_ regexp *rex, regnode *prog)
 
            }
 
-           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. */
            }
@@ -4503,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 */
@@ -4557,7 +4564,6 @@ do_no:
                PL_reg_flags ^= RF_utf8;
            ReREFCNT_dec(rex);
            rex = st->u.eval.prev_rex;
-           PL_reg_re = rex; /* XXX */
            cur_eval = st->u.eval.prev_eval;
 
            /* XXXX This is too dramatic a measure... */
@@ -4635,7 +4641,7 @@ final_exit:
  * 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;
@@ -4698,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;
@@ -4864,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);
@@ -4880,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 ? PL_reg_re->data : NULL;
+    const struct reg_data *data = prog ? prog->data : NULL;
 
     if (data && data->count) {
        const U32 n = ARG(node);
@@ -4934,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);
@@ -4963,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))