This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Regexp tests and UTF8
[perl5.git] / regcomp.c
index 02b65d6..2f39b27 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -38,7 +38,8 @@
 /* *These* symbols are masked to allow static link. */
 #  define Perl_pregfree my_regfree
 #  define Perl_regnext my_regnext
-#  define save_re_context my_save_re_context
+#  define Perl_save_re_context my_save_re_context
+#  define Perl_reginitcolors my_reginitcolors 
 #endif 
 
 /*SUPPRESS 112*/
@@ -259,7 +260,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
     while (scan && OP(scan) != END && scan < last) {
        /* Peephole optimizer: */
 
-       if (regkind[(U8)OP(scan)] == EXACT) {
+       if (PL_regkind[(U8)OP(scan)] == EXACT) {
            regnode *n = regnext(scan);
            U32 stringok = 1;
 #ifdef DEBUGGING
@@ -269,13 +270,13 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
            next = scan + (*OPERAND(scan) + 2 - 1)/sizeof(regnode) + 2;
            /* Skip NOTHING, merge EXACT*. */
            while (n &&
-                  ( regkind[(U8)OP(n)] == NOTHING || 
+                  ( PL_regkind[(U8)OP(n)] == NOTHING || 
                     (stringok && (OP(n) == OP(scan))))
                   && NEXT_OFF(n)
                   && NEXT_OFF(scan) + NEXT_OFF(n) < I16_MAX) {
                if (OP(n) == TAIL || n > next)
                    stringok = 0;
-               if (regkind[(U8)OP(n)] == NOTHING) {
+               if (PL_regkind[(U8)OP(n)] == NOTHING) {
                    NEXT_OFF(scan) += NEXT_OFF(n);
                    next = n + NODE_STEP_REGNODE;
 #ifdef DEBUGGING
@@ -311,7 +312,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                 * don't initialize the OP() slot of a node when that node
                 * is occupied by just the trailing null of the string in
                 * an EXACT node */
-               if (regkind[(U8)OP(n)] != NOTHING || OP(n) == NOTHING) {
+               if (PL_regkind[(U8)OP(n)] != NOTHING || OP(n) == NOTHING) {
                    OP(n) = OPTIMIZED;
                    NEXT_OFF(n) = 0;
                }
@@ -331,7 +332,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
            
            /* Skip NOTHING and LONGJMP. */
            while ((n = regnext(n))
-                  && ((regkind[(U8)OP(n)] == NOTHING && (noff = NEXT_OFF(n)))
+                  && ((PL_regkind[(U8)OP(n)] == NOTHING && (noff = NEXT_OFF(n)))
                       || ((OP(n) == LONGJMP) && (noff = ARG(n))))
                   && off + noff < max)
                off += noff;
@@ -420,7 +421,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                data->flags &= ~SF_BEFORE_EOL;
            }
        }
-       else if (regkind[(U8)OP(scan)] == EXACT) {
+       else if (PL_regkind[(U8)OP(scan)] == EXACT) {
            I32 l = *OPERAND(scan);
            if (flags & SCF_DO_SUBSTR) 
                scan_commit(data);
@@ -438,11 +439,11 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
            if (data && (flags & SCF_DO_SUBSTR))
                data->pos_min += l;
        }
-       else if (strchr(varies,OP(scan))) {
+       else if (strchr(PL_varies,OP(scan))) {
            I32 mincount, maxcount, minnext, deltanext, pos_before, fl;
            regnode *oscan = scan;
            
-           switch (regkind[(U8)OP(scan)]) {
+           switch (PL_regkind[(U8)OP(scan)]) {
            case WHILEM:
                scan = NEXTOPER(scan);
                goto finish;
@@ -493,7 +494,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                    scan = next;
                if (ckWARN(WARN_UNSAFE) && (minnext + deltanext == 0) 
                    && !(data->flags & (SF_HAS_PAR|SF_IN_PAR))
-                   && maxcount <= 10000) /* Complement check for big count */
+                   && maxcount <= REG_INFTY/3) /* Complement check for big count */
                    warner(WARN_UNSAFE, "Strange *+?{} on zero-length expression");
                min += minnext * mincount;
                is_inf_internal |= (maxcount == REG_INFTY 
@@ -513,8 +514,8 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
 
                    /* Skip open. */
                    nxt = regnext(nxt);
-                   if (!strchr(simple,OP(nxt))
-                       && !(regkind[(U8)OP(nxt)] == EXACT
+                   if (!strchr(PL_simple,OP(nxt))
+                       && !(PL_regkind[(U8)OP(nxt)] == EXACT
                             && *OPERAND(nxt) == 1)) 
                        goto nogo;
                    nxt2 = nxt;
@@ -646,7 +647,7 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                    data->flags |= SF_HAS_EVAL;
              optimize_curly_tail:
                if (OP(oscan) != CURLYX) {
-                   while (regkind[(U8)OP(next = regnext(oscan))] == NOTHING
+                   while (PL_regkind[(U8)OP(next = regnext(oscan))] == NOTHING
                           && NEXT_OFF(next))
                        NEXT_OFF(oscan) += NEXT_OFF(next);
                }
@@ -660,19 +661,19 @@ study_chunk(regnode **scanp, I32 *deltap, regnode *last, scan_data_t *data, U32
                break;
            }
        }
-       else if (strchr(simple,OP(scan)) || regkind[(U8)OP(scan)] == ANYUTF8) {
+       else if (strchr(PL_simple,OP(scan)) || PL_regkind[(U8)OP(scan)] == ANYUTF8) {
            if (flags & SCF_DO_SUBSTR) {
                scan_commit(data);
                data->pos_min++;
            }
            min++;
        }
-       else if (regkind[(U8)OP(scan)] == EOL && flags & SCF_DO_SUBSTR) {
+       else if (PL_regkind[(U8)OP(scan)] == EOL && flags & SCF_DO_SUBSTR) {
            data->flags |= (OP(scan) == MEOL
                            ? SF_BEFORE_MEOL
                            : SF_BEFORE_SEOL);
        }
-       else if (regkind[(U8)OP(scan)] == BRANCHJ
+       else if (PL_regkind[(U8)OP(scan)] == BRANCHJ
                   && (scan->flags || data)
                   && (OP(scan) == IFMATCH || OP(scan) == UNLESSM)) {
            I32 deltanext, minnext;
@@ -759,6 +760,31 @@ add_data(I32 n, char *s)
     return PL_regcomp_rx->data->count - n;
 }
 
+void
+reginitcolors(void)
+{
+    dTHR;
+    int i = 0;
+    char *s = PerlEnv_getenv("PERL_RE_COLORS");
+           
+    if (s) {
+       PL_colors[0] = s = savepv(s);
+       while (++i < 6) {
+           s = strchr(s, '\t');
+           if (s) {
+               *s = '\0';
+               PL_colors[i] = ++s;
+           }
+           else
+               PL_colors[i] = "";
+       }
+    } else {
+       while (i < 6) 
+           PL_colors[i++] = "";
+    }
+    PL_colorset = 1;
+}
+
 /*
  - pregcomp - compile a regular expression into internal code
  *
@@ -792,38 +818,16 @@ pregcomp(char *exp, char *xend, PMOP *pm)
     if (exp == NULL)
        FAIL("NULL regexp argument");
 
-    if (PL_curcop == &compiling ? (PL_hints & HINT_UTF8) : IN_UTF8)
+    if (PL_curcop == &PL_compiling ? (PL_hints & HINT_UTF8) : IN_UTF8)
        PL_reg_flags |= RF_utf8;
     else
        PL_reg_flags = 0;
 
     PL_regprecomp = savepvn(exp, xend - exp);
-    DEBUG_r(
-       if (!PL_colorset) {
-           int i = 0;
-           char *s = PerlEnv_getenv("PERL_RE_COLORS");
-           
-           if (s) {
-               PL_colors[0] = s = savepv(s);
-               while (++i < 6) {
-                   s = strchr(s, '\t');
-                   if (s) {
-                       *s = '\0';
-                       PL_colors[i] = ++s;
-                   }
-                   else
-                       PL_colors[i] = "";
-               }
-           } else {
-               while (i < 6) 
-                   PL_colors[i++] = "";
-           }
-           PL_colorset = 1;
-       }
-       );
+    DEBUG_r(if (!PL_colorset) reginitcolors());
     DEBUG_r(PerlIO_printf(Perl_debug_log, "%sCompiling%s RE `%s%*s%s'\n",
-                         PL_colors[4],PL_colors[5],PL_colors[0],
-                         xend - exp, PL_regprecomp, PL_colors[1]));
+                     PL_colors[4],PL_colors[5],PL_colors[0],
+                     xend - exp, PL_regprecomp, PL_colors[1]));
     PL_regflags = pm->op_pmflags;
     PL_regsawback = 0;
 
@@ -839,7 +843,7 @@ pregcomp(char *exp, char *xend, PMOP *pm)
     PL_regnpar = 1;
     PL_regsize = 0L;
     PL_regcode = &PL_regdummy;
-    regc((U8)MAGIC, (char*)PL_regcode);
+    regc((U8)REG_MAGIC, (char*)PL_regcode);
     if (reg(0, &flags) == NULL) {
        Safefree(PL_regprecomp);
        PL_regprecomp = Nullch;
@@ -874,7 +878,7 @@ pregcomp(char *exp, char *xend, PMOP *pm)
     PL_regcode = r->program;
     /* Store the count of eval-groups for security checks: */
     PL_regcode->next_off = ((PL_seen_evals > U16_MAX) ? U16_MAX : PL_seen_evals);
-    regc((U8)MAGIC, (char*) PL_regcode++);
+    regc((U8)REG_MAGIC, (char*) PL_regcode++);
     r->data = 0;
     if (reg(0, &flags) == NULL)
        return(NULL);
@@ -905,7 +909,7 @@ pregcomp(char *exp, char *xend, PMOP *pm)
            (OP(first) == BRANCH && OP(regnext(first)) != BRANCH) ||
            (OP(first) == PLUS) ||
            (OP(first) == MINMOD) ||
-           (regkind[(U8)OP(first)] == CURLY && ARG1(first) > 0) ) {
+           (PL_regkind[(U8)OP(first)] == CURLY && ARG1(first) > 0) ) {
                if (OP(first) == PLUS)
                    sawplus = 1;
                else
@@ -916,12 +920,12 @@ pregcomp(char *exp, char *xend, PMOP *pm)
        /* Starting-point info. */
       again:
        if (OP(first) == EXACT);        /* Empty, get anchored substr later. */
-       else if (strchr(simple+4,OP(first)))
+       else if (strchr(PL_simple+4,OP(first)))
            r->regstclass = first;
-       else if (regkind[(U8)OP(first)] == BOUND ||
-                regkind[(U8)OP(first)] == NBOUND)
+       else if (PL_regkind[(U8)OP(first)] == BOUND ||
+                PL_regkind[(U8)OP(first)] == NBOUND)
            r->regstclass = first;
-       else if (regkind[(U8)OP(first)] == BOL) {
+       else if (PL_regkind[(U8)OP(first)] == BOL) {
            r->reganch |= (OP(first) == MBOL ? ROPT_ANCH_MBOL: ROPT_ANCH_BOL);
            first = NEXTOPER(first);
            goto again;
@@ -932,7 +936,7 @@ pregcomp(char *exp, char *xend, PMOP *pm)
            goto again;
        }
        else if ((OP(first) == STAR &&
-           regkind[(U8)OP(NEXTOPER(first))] == ANY) &&
+           PL_regkind[(U8)OP(NEXTOPER(first))] == REG_ANY) &&
            !(r->reganch & ROPT_ANCH) )
        {
            /* turn .* into ^.* with an implied $*=1 */
@@ -1160,8 +1164,9 @@ reg(I32 paren, I32 *flagp)
                    PL_regcomp_rx->data->data[n+2] = (void*)sop;
                    SvREFCNT_dec(sv);
                }
-               else {          /* First pass */
-                   if (PL_reginterp_cnt < ++PL_seen_evals && PL_curcop != &compiling)
+               else {                                          /* First pass */
+                   if (PL_reginterp_cnt < ++PL_seen_evals
+                       && PL_curcop != &PL_compiling)
                        /* No compiled RE interpolated, has runtime
                           components ===> unsafe.  */
                        FAIL("Eval-group not allowed at runtime, use re 'eval'");
@@ -1210,10 +1215,14 @@ reg(I32 paren, I32 *flagp)
                    else
                        regtail(br, reganode(LONGJMP, 0));
                    c = *nextchar();
+                   if (flags&HASWIDTH)
+                       *flagp |= HASWIDTH;
                    if (c == '|') {
                        lastbr = reganode(IFTHEN, 0); /* Fake one for optimizer. */
                        regbranch(&flags, 1);
                        regtail(ret, lastbr);
+                       if (flags&HASWIDTH)
+                           *flagp |= HASWIDTH;
                        c = *nextchar();
                    }
                    else
@@ -1582,7 +1591,7 @@ regpiece(I32 *flagp)
        goto do_curly;
     }
   nest_check:
-    if (ckWARN(WARN_UNSAFE) && !SIZE_ONLY && !(flags&HASWIDTH) && max > 10000) {
+    if (ckWARN(WARN_UNSAFE) && !SIZE_ONLY && !(flags&HASWIDTH) && max > REG_INFTY/3) {
        warner(WARN_UNSAFE, "%.*s matches null string many times",
            PL_regcomp_parse - origparse, origparse);
     }
@@ -1653,7 +1662,7 @@ tryagain:
            if (PL_regflags & PMf_SINGLELINE)
                ret = reg_node(SANY);
            else
-               ret = reg_node(ANY);
+               ret = reg_node(REG_ANY);
            *flagp |= HASWIDTH|SIMPLE;
        }
        PL_regnaughty++;
@@ -2084,6 +2093,44 @@ regwhite(char *p, char *e)
     return p;
 }
 
+/* parse POSIX character classes like [[:foo:]] */
+STATIC char*
+regpposixcc(I32 value)
+{
+    char *posixcc = 0;
+
+    if (value == '[' && PL_regcomp_parse + 1 < PL_regxend &&
+       /* I smell either [: or [= or [. -- POSIX has been here, right? */
+       (*PL_regcomp_parse == ':' ||
+        *PL_regcomp_parse == '=' ||
+        *PL_regcomp_parse == '.')) {
+       char  c = *PL_regcomp_parse;
+       char* s = PL_regcomp_parse++;
+           
+       while (PL_regcomp_parse < PL_regxend && *PL_regcomp_parse != c)
+           PL_regcomp_parse++;
+       if (PL_regcomp_parse == PL_regxend)
+           /* Grandfather lone [:, [=, [. */
+           PL_regcomp_parse = s;
+       else {
+           PL_regcomp_parse++; /* skip over the c */
+           if (*PL_regcomp_parse == ']') {
+               /* Not Implemented Yet.
+                * (POSIX Extended Character Classes, that is)
+                * The text between e.g. [: and :] would start
+                * at s + 1 and stop at regcomp_parse - 2. */
+               if (ckWARN(WARN_UNSAFE) && !SIZE_ONLY)
+                   warner(WARN_UNSAFE,
+                          "Character class syntax [%c %c] is reserved for future extensions", c, c);
+               PL_regcomp_parse++; /* skip over the ending ] */
+               posixcc = s + 1;
+           }
+       }
+    }
+
+    return posixcc;
+}
+
 STATIC regnode *
 regclass(void)
 {
@@ -2121,32 +2168,9 @@ regclass(void)
     while (PL_regcomp_parse < PL_regxend && *PL_regcomp_parse != ']') {
        skipcond:
        value = UCHARAT(PL_regcomp_parse++);
-       if (value == '[' && PL_regcomp_parse + 1 < PL_regxend &&
-           /* I smell either [: or [= or [. -- POSIX has been here, right? */
-           (*PL_regcomp_parse == ':' || *PL_regcomp_parse == '=' || *PL_regcomp_parse == '.')) {
-           char  posixccc = *PL_regcomp_parse;
-           char* posixccs = PL_regcomp_parse++;
-           
-           while (PL_regcomp_parse < PL_regxend && *PL_regcomp_parse != posixccc)
-               PL_regcomp_parse++;
-           if (PL_regcomp_parse == PL_regxend)
-               /* Grandfather lone [:, [=, [. */
-               PL_regcomp_parse = posixccs;
-           else {
-               PL_regcomp_parse++; /* skip over the posixccc */
-               if (*PL_regcomp_parse == ']') {
-                   /* Not Implemented Yet.
-                    * (POSIX Extended Character Classes, that is)
-                    * The text between e.g. [: and :] would start
-                    * at posixccs + 1 and stop at regcomp_parse - 2. */
-                   if (ckWARN(WARN_UNSAFE) && !SIZE_ONLY)
-                       warner(WARN_UNSAFE,
-                           "Character class syntax [%c %c] is reserved for future extensions", posixccc, posixccc);
-                   PL_regcomp_parse++; /* skip over the ending ] */
-               }
-           }
-       }
-       if (value == '\\') {
+       if (value == '[')
+           (void)regpposixcc(value); /* ignore the return value for now */
+       else if (value == '\\') {
            value = UCHARAT(PL_regcomp_parse++);
            switch (value) {
            case 'w':
@@ -2266,7 +2290,9 @@ regclass(void)
        if (!SIZE_ONLY) {
 #ifndef ASCIIish
            if ((isLOWER(lastvalue) && isLOWER(value)) ||
-               (isUPPER(lastvalue) && isUPPER(value))) {
+               (isUPPER(lastvalue) && isUPPER(value)))
+           {
+               I32 i;
                if (isLOWER(lastvalue)) {
                    for (i = lastvalue; i <= value; i++)
                        if (isLOWER(i))
@@ -2288,7 +2314,7 @@ regclass(void)
     if (!SIZE_ONLY && (*opnd & (0xFF ^ ANYOF_INVERT)) == ANYOF_FOLD) {
        for (value = 0; value < 256; ++value) {
            if (ANYOF_TEST(opnd, value)) {
-               I32 cf = fold[value];
+               I32 cf = PL_fold[value];
                ANYOF_SET(opnd, cf);
            }
        }
@@ -2339,33 +2365,9 @@ regclassutf8(void)
        value = utf8_to_uv((U8*)PL_regcomp_parse, &numlen);
        PL_regcomp_parse += numlen;
 
-       if (value == '[' && PL_regcomp_parse + 1 < PL_regxend &&
-           /* I smell either [: or [= or [. -- POSIX has been here, right? */
-           (*PL_regcomp_parse == ':' || *PL_regcomp_parse == '=' || *PL_regcomp_parse == '.')) {
-           char  posixccc = *PL_regcomp_parse;
-           char* posixccs = PL_regcomp_parse++;
-           
-           while (PL_regcomp_parse < PL_regxend && *PL_regcomp_parse != posixccc)
-               PL_regcomp_parse++;
-           if (PL_regcomp_parse == PL_regxend)
-               /* Grandfather lone [:, [=, [. */
-               PL_regcomp_parse = posixccs;
-           else {
-               PL_regcomp_parse++; /* skip over the posixccc */
-               if (*PL_regcomp_parse == ']') {
-                   /* Not Implemented Yet.
-                    * (POSIX Extended Character Classes, that is)
-                    * The text between e.g. [: and :] would start
-                    * at posixccs + 1 and stop at regcomp_parse - 2. */
-                   if (ckWARN(WARN_UNSAFE) && !SIZE_ONLY)
-                       warner(WARN_UNSAFE,
-                           "Character class syntax [%c %c] is reserved for future extensions", posixccc, posixccc);
-                   PL_regcomp_parse++; /* skip over the ending ] */
-               }
-           }
-       }
-
-       if (value == '\\') {
+       if (value == '[')
+           (void)regpposixcc(value); /* ignore the return value for now */
+       else if (value == '\\') {
            value = utf8_to_uv((U8*)PL_regcomp_parse, &numlen);
            PL_regcomp_parse += numlen;
            switch (value) {
@@ -2647,7 +2649,7 @@ reginsert(U8 op, regnode *opnd)
     register regnode *place;
     register int offset = regarglen[(U8)op];
     
-/* (regkind[(U8)op] == CURLY ? EXTRA_STEP_2ARGS : 0); */
+/* (PL_regkind[(U8)op] == CURLY ? EXTRA_STEP_2ARGS : 0); */
 
     if (SIZE_ONLY) {
        PL_regsize += NODE_STEP_REGNODE + offset;
@@ -2707,10 +2709,10 @@ regoptail(regnode *p, regnode *val)
     /* "Operandless" and "op != BRANCH" are synonymous in practice. */
     if (p == NULL || SIZE_ONLY)
        return;
-    if (regkind[(U8)OP(p)] == BRANCH) {
+    if (PL_regkind[(U8)OP(p)] == BRANCH) {
        regtail(NEXTOPER(p), val);
     }
-    else if ( regkind[(U8)OP(p)] == BRANCHJ) {
+    else if ( PL_regkind[(U8)OP(p)] == BRANCHJ) {
        regtail(NEXTOPER(NEXTOPER(p)), val);
     }
     else
@@ -2766,7 +2768,7 @@ dumpuntil(regnode *start, regnode *node, regnode *last, SV* sv, I32 l)
            PerlIO_printf(Perl_debug_log, "(%d)", next - start);
        (void)PerlIO_putc(Perl_debug_log, '\n');
       after_print:
-       if (regkind[(U8)op] == BRANCHJ) {
+       if (PL_regkind[(U8)op] == BRANCHJ) {
            register regnode *nnode = (OP(next) == LONGJMP 
                                       ? regnext(next) 
                                       : next);
@@ -2774,14 +2776,14 @@ dumpuntil(regnode *start, regnode *node, regnode *last, SV* sv, I32 l)
                nnode = last;
            node = dumpuntil(start, NEXTOPER(NEXTOPER(node)), nnode, sv, l + 1);
        }
-       else if (regkind[(U8)op] == BRANCH) {
+       else if (PL_regkind[(U8)op] == BRANCH) {
            node = dumpuntil(start, NEXTOPER(node), next, sv, l + 1);
        }
        else if ( op == CURLY) {   /* `next' might be very big: optimizer */
            node = dumpuntil(start, NEXTOPER(node) + EXTRA_STEP_2ARGS,
                             NEXTOPER(node) + EXTRA_STEP_2ARGS + 1, sv, l + 1);
        }
-       else if (regkind[(U8)op] == CURLY && op != CURLYX) {
+       else if (PL_regkind[(U8)op] == CURLY && op != CURLYX) {
            node = dumpuntil(start, NEXTOPER(node) + EXTRA_STEP_2ARGS,
                             next, sv, l + 1);
        }
@@ -2792,7 +2794,7 @@ dumpuntil(regnode *start, regnode *node, regnode *last, SV* sv, I32 l)
            node = NEXTOPER(node);
            node += ANY_SKIP;
        }
-       else if (regkind[(U8)op] == EXACT) {
+       else if (PL_regkind[(U8)op] == EXACT) {
             /* Literal string, where present. */
            node += ((*OPERAND(node)) + 2 + sizeof(regnode) - 1) / sizeof(regnode);
            node = NEXTOPER(node);
@@ -2908,7 +2910,7 @@ regprop(SV *sv, regnode *o)
     case SEOL:
        p = "SEOL";
        break;
-    case ANY:
+    case REG_ANY:
        p = "ANY";
        break;
     case SANY:
@@ -3209,4 +3211,15 @@ save_re_context(void)
     SAVESPTR(PL_regcode);              /* Code-emit pointer; &regdummy = don't */
     SAVEPPTR(PL_regxend);              /* End of input for compile */
     SAVEPPTR(PL_regcomp_parse);                /* Input-scan pointer. */
+    SAVESPTR(PL_reg_call_cc);          /* from regexec.c */
+    SAVESPTR(PL_reg_re);               /* from regexec.c */
+    SAVEPPTR(PL_reg_ganch);            /* from regexec.c */
+    SAVESPTR(PL_reg_sv);               /* from regexec.c */
+    SAVESPTR(PL_reg_magic);            /* from regexec.c */
+    SAVEI32(PL_reg_oldpos);                    /* from regexec.c */
+    SAVESPTR(PL_reg_oldcurpm);         /* from regexec.c */
+    SAVESPTR(PL_reg_curpm);            /* from regexec.c */
+#ifdef DEBUGGING
+    SAVEPPTR(PL_reg_starttry);         /* from regexec.c */    
+#endif
 }