This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Anohter ptags improvement
[perl5.git] / regexec.c
index 7a0e84a..77b9f2d 100644 (file)
--- a/regexec.c
+++ b/regexec.c
 
 #define RF_tainted     1               /* tainted information used? */
 #define RF_warned      2               /* warned about big count? */
-#define RF_evaled      4               /* Did an EVAL? */
+#define RF_evaled      4               /* Did an EVAL with setting? */
+
+#define RS_init                1               /* eval environment created */
+#define RS_set         2               /* replsv value is set */
 
 #ifndef STATIC
 #define        STATIC  static
@@ -74,10 +77,12 @@ static I32 regmatch _((regnode *prog));
 static I32 regrepeat _((regnode *p, I32 max));
 static I32 regrepeat_hard _((regnode *p, I32 max, I32 *lp));
 static I32 regtry _((regexp *prog, char *startpos));
+
 static bool reginclass _((char *p, I32 c));
 static CHECKPOINT regcppush _((I32 parenfloor));
 static char * regcppop _((void));
 #endif
+#define REGINCLASS(p,c)  (*(p) ? reginclass(p,c) : ANYOF_TEST(p,c))
 
 STATIC CHECKPOINT
 regcppush(I32 parenfloor)
@@ -192,6 +197,7 @@ regexec_flags(register regexp *prog, char *stringarg, register char *strend, cha
     I32 end_shift = 0;                 /* Same for the end. */
     I32 scream_pos = -1;               /* Internal iterator of scream. */
     char *scream_olds;
+    SV* oreplsv = GvSV(replgv);
 
     cc.cur = 0;
     cc.oldcc = 0;
@@ -252,7 +258,7 @@ regexec_flags(register regexp *prog, char *stringarg, register char *strend, cha
        else
            s = fbm_instr((unsigned char*)s + start_shift,
                          (unsigned char*)strend - end_shift,
-               prog->check_substr);
+               prog->check_substr, 0);
        if (!s) {
            ++BmUSEFUL(prog->check_substr);     /* hooray */
            goto phooey;        /* not present */
@@ -353,7 +359,7 @@ regexec_flags(register regexp *prog, char *stringarg, register char *strend, cha
                 ? (s = screaminstr(screamer, must, s + back_min - strbeg,
                                    end_shift, &scream_pos, 0))
                 : (s = fbm_instr((unsigned char*)s + back_min,
-                                 (unsigned char*)strend, must))) ) {
+                                 (unsigned char*)strend, must, 0))) ) {
            if (s - back_max > last1) {
                last1 = s - back_min;
                s = s - back_max;
@@ -383,7 +389,7 @@ regexec_flags(register regexp *prog, char *stringarg, register char *strend, cha
        case ANYOF:
            Class = (char *) OPERAND(c);
            while (s < strend) {
-               if (reginclass(Class, *s)) {
+               if (REGINCLASS(Class, *s)) {
                    if (tmp && regtry(prog, s))
                        goto got_it;
                    else
@@ -604,7 +610,7 @@ got_it:
     strend += dontbother;      /* uncheat */
     prog->subbeg = strbeg;
     prog->subend = strend;
-    RX_MATCH_TAINTED_SET(prog, reg_flags & RF_tainted);
+    RX_MATCH_TAINTED_set(prog, reg_flags & RF_tainted);
 
     /* make sure $`, $&, $', and $digit will work later */
     if (strbeg != prog->subbase) {     /* second+ //g match.  */
@@ -630,6 +636,12 @@ got_it:
            }
        }
     }
+    /* Preserve the current value of $^R */
+    if (oreplsv != GvSV(replgv)) {
+       sv_setsv(oreplsv, GvSV(replgv));/* So that when GvSV(replgv) is
+                                          restored, the value remains
+                                          the same. */
+    }
     return 1;
 
 phooey:
@@ -648,6 +660,19 @@ regtry(regexp *prog, char *startpos)
     register char **ep;
     CHECKPOINT lastcp;
 
+    if ((prog->reganch & ROPT_EVAL_SEEN) && !reg_eval_set) {
+       reg_eval_set = RS_init;
+       DEBUG_r(DEBUG_s(
+           PerlIO_printf(Perl_debug_log, "  setting stack tmpbase at %i\n", stack_sp - stack_base);
+           ));
+       SAVEINT(cxstack[cxstack_ix].blk_oldsp);
+       cxstack[cxstack_ix].blk_oldsp = stack_sp - stack_base;
+       /* Otherwise OP_NEXTSTATE will free whatever on stack now.  */
+       SAVETMPS;
+       /* Apparently this is not needed, judging by wantarray. */
+       /* SAVEINT(cxstack[cxstack_ix].blk_gimme);
+          cxstack[cxstack_ix].blk_gimme = G_SCALAR; */
+    }
     reginput = startpos;
     regstartp = prog->startp;
     regendp = prog->endp;
@@ -672,7 +697,7 @@ regtry(regexp *prog, char *startpos)
        }
     }
     REGCP_SET;
-    if (regmatch(prog->program + 1) && reginput >= regtill) {
+    if (regmatch(prog->program + 1)) {
        prog->startp[0] = startpos;
        prog->endp[0] = reginput;
        return 1;
@@ -751,17 +776,13 @@ regmatch(regnode *prog)
                          SvPVX(prop));
        } );
 
-#ifdef REGALIGN
        next = scan + NEXT_OFF(scan);
        if (next == scan)
            next = NULL;
-#else
-       next = regnext(scan);
-#endif
 
        switch (OP(scan)) {
        case BOL:
-           if (locinput == regbol
+           if (locinput == bostr
                ? regprev == '\n'
                : (multiline && 
                   (nextchr || locinput < regeol) && locinput[-1] == '\n') )
@@ -771,7 +792,7 @@ regmatch(regnode *prog)
            }
            sayNO;
        case MBOL:
-           if (locinput == regbol
+           if (locinput == bostr
                ? regprev == '\n'
                : ((nextchr || locinput < regeol) && locinput[-1] == '\n') )
            {
@@ -803,6 +824,10 @@ regmatch(regnode *prog)
            if (regeol - locinput > 1)
                sayNO;
            break;
+       case EOS:
+           if (regeol != locinput)
+               sayNO;
+           break;
        case SANY:
            if (!nextchr && locinput >= regeol)
                sayNO;
@@ -850,7 +875,7 @@ regmatch(regnode *prog)
            s = (char *) OPERAND(scan);
            if (nextchr < 0)
                nextchr = UCHARAT(locinput);
-           if (!reginclass(s, nextchr))
+           if (!REGINCLASS(s, nextchr))
                sayNO;
            if (!nextchr && locinput >= regeol)
                sayNO;
@@ -978,22 +1003,6 @@ regmatch(regnode *prog)
            op = (OP_4tree*)regdata->data[n];
            DEBUG_r( PerlIO_printf(Perl_debug_log, "  re_eval 0x%x\n", op) );
            curpad = AvARRAY((AV*)regdata->data[n + 1]);
-           if (!reg_eval_set) {
-               /* Preserve whatever is on stack now, otherwise
-                  OP_NEXTSTATE will overwrite it. */
-               SAVEINT(reg_eval_set);  /* Protect against unwinding. */
-               reg_eval_set = 1;
-               DEBUG_r(DEBUG_s(
-                   PerlIO_printf(Perl_debug_log, "  setting stack tmpbase at %i\n", stack_sp - stack_base);
-                   ));
-               SAVEINT(cxstack[cxstack_ix].blk_oldsp);
-               cxstack[cxstack_ix].blk_oldsp = stack_sp - stack_base;
-               /* Otherwise OP_NEXTSTATE will free whatever on stack now.  */
-               SAVETMPS;
-               /* Apparently this is not needed, judging by wantarray. */
-               /* SAVEINT(cxstack[cxstack_ix].blk_gimme);
-                  cxstack[cxstack_ix].blk_gimme = G_SCALAR; */
-           }
 
            CALLRUNOPS();                       /* Scalar context. */
            SPAGAIN;
@@ -1003,7 +1012,8 @@ regmatch(regnode *prog)
            if (logical) {
                logical = 0;
                sw = SvTRUE(ret);
-           }
+           } else
+               sv_setsv(save_scalar(replgv), ret);
            op = oop;
            curpad = ocurpad;
            curcop = ocurcop;
@@ -1232,15 +1242,11 @@ regmatch(regnode *prog)
                            regendp[n] = 0;
                        *reglastparen = n;
                        scan = next;
-#ifdef REGALIGN
                        /*SUPPRESS 560*/
                        if (n = (c1 == BRANCH ? NEXT_OFF(next) : ARG(next)))
                            next += n;
                        else
                            next = NULL;
-#else
-                       next = regnext(next);
-#endif
                        inner = NEXTOPER(scan);
                        if (c1 == BRANCHJ) {
                            inner = NEXTOPER(inner);
@@ -1256,7 +1262,7 @@ regmatch(regnode *prog)
            break;
        case CURLYM:
        {
-           I32 l;
+           I32 l = 0;
            CHECKPOINT lastcp;
            
            /* We suppose that the next guy does not need
@@ -1264,7 +1270,6 @@ regmatch(regnode *prog)
               and has no parenths to influence future backrefs. */
            ln = ARG1(scan);  /* min to match */
            n  = ARG2(scan);  /* max to match */
-#ifdef REGALIGN_STRUCT
            paren = scan->flags;
            if (paren) {
                if (paren > regsize)
@@ -1272,8 +1277,7 @@ regmatch(regnode *prog)
                if (paren > *reglastparen)
                    *reglastparen = paren;
            }
-#endif 
-           scan = NEXTOPER(scan) + 4/sizeof(regnode);
+           scan = NEXTOPER(scan) + NODE_STEP_REGNODE;
            if (paren)
                scan += NEXT_OFF(scan); /* Skip former OPEN. */
            reginput = locinput;
@@ -1281,7 +1285,7 @@ regmatch(regnode *prog)
                minmod = 0;
                if (ln && regrepeat_hard(scan, ln, &l) < ln)
                    sayNO;
-               if (l == 0 && n >= ln
+               if (ln && l == 0 && n >= ln
                    /* In fact, this is tricky.  If paren, then the
                       fact that we did/didnot match may influence
                       future execution. */
@@ -1299,6 +1303,7 @@ regmatch(regnode *prog)
                } else
                    c1 = c2 = -1000;
                REGCP_SET;
+               /* This may be improved if l == 0.  */
                while (n >= ln || (n == REG_INFTY && ln > 0 && l)) { /* ln overflow ? */
                    /* If it could work, try it. */
                    if (c1 == -1000 ||
@@ -1387,13 +1392,13 @@ regmatch(regnode *prog)
                *reglastparen = paren;
            ln = ARG1(scan);  /* min to match */
            n  = ARG2(scan);  /* max to match */
-            scan = regnext(NEXTOPER(scan) + 4/sizeof(regnode));
+            scan = regnext(NEXTOPER(scan) + NODE_STEP_REGNODE);
            goto repeat;
        case CURLY:
            paren = 0;
            ln = ARG1(scan);  /* min to match */
            n  = ARG2(scan);  /* max to match */
-           scan = NEXTOPER(scan) + 4/sizeof(regnode);
+           scan = NEXTOPER(scan) + NODE_STEP_REGNODE;
            goto repeat;
        case STAR:
            ln = 0;
@@ -1503,8 +1508,11 @@ regmatch(regnode *prog)
            }
            sayNO;
            break;
-       case SUCCEED:
        case END:
+           if (locinput < regtill)
+               sayNO;                  /* Cannot match: too short. */
+           /* Fall through */
+       case SUCCEED:
            reginput = locinput;        /* put where regtry can find it */
            sayYES;                     /* Success! */
        case SUSPEND:
@@ -1623,7 +1631,7 @@ regrepeat(regnode *p, I32 max)
            scan++;
        break;
     case ANYOF:
-       while (scan < loceol && reginclass(opnd, *scan))
+       while (scan < loceol && REGINCLASS(opnd, *scan))
            scan++;
        break;
     case ALNUM:
@@ -1734,7 +1742,7 @@ reginclass(register char *p, register I32 c)
     bool match = FALSE;
 
     c &= 0xFF;
-    if (p[1 + (c >> 3)] & (1 << (c & 7)))
+    if (ANYOF_TEST(p, c))
        match = TRUE;
     else if (flags & ANYOF_FOLD) {
        I32 cf;
@@ -1744,7 +1752,7 @@ reginclass(register char *p, register I32 c)
        }
        else
            cf = fold[c];
-       if (p[1 + (cf >> 3)] & (1 << (cf & 7)))
+       if (ANYOF_TEST(p, cf))
            match = TRUE;
     }
 
@@ -1760,7 +1768,7 @@ reginclass(register char *p, register I32 c)
        }
     }
 
-    return match ^ ((flags & ANYOF_INVERT) != 0);
+    return (flags & ANYOF_INVERT) ? !match : match;
 }