#define sayNO goto no
#define sayNO_ANYOF goto no_anyof
#define sayYES_FINAL goto yes_final
-#define sayYES_LOUD goto yes_loud
#define sayNO_FINAL goto no_final
#define sayNO_SILENT goto do_no
#define saySAME(x) if (x) goto yes; else goto no
#define POSCACHE_SUCCESS 0 /* caching success rather than failure */
#define POSCACHE_SEEN 1 /* we know what we're caching */
#define POSCACHE_START 2 /* the real cache: this bit maps to pos 0 */
+
#define CACHEsayYES STMT_START { \
if (st->u.whilem.cache_offset | st->u.whilem.cache_bit) { \
- if (!(PL_reg_poscache[0] & (1<<POSCACHE_SEEN))) \
- PL_reg_poscache[0] |= (1<<POSCACHE_SUCCESS) || (1<<POSCACHE_SEEN); \
- else if (!(PL_reg_poscache[0] & (1<<POSCACHE_SUCCESS))) { \
+ if (!(PL_reg_poscache[0] & (1<<POSCACHE_SEEN))) { \
+ PL_reg_poscache[0] |= (1<<POSCACHE_SUCCESS) | (1<<POSCACHE_SEEN); \
+ PL_reg_poscache[st->u.whilem.cache_offset] |= (1<<st->u.whilem.cache_bit); \
+ } \
+ else if (PL_reg_poscache[0] & (1<<POSCACHE_SUCCESS)) { \
+ PL_reg_poscache[st->u.whilem.cache_offset] |= (1<<st->u.whilem.cache_bit); \
+ } \
+ else { \
/* cache records failure, but this is success */ \
DEBUG_r( \
PerlIO_printf(Perl_debug_log, \
} \
sayYES; \
} STMT_END
+
#define CACHEsayNO STMT_START { \
if (st->u.whilem.cache_offset | st->u.whilem.cache_bit) { \
- if (!(PL_reg_poscache[0] & (1<<POSCACHE_SEEN))) \
+ if (!(PL_reg_poscache[0] & (1<<POSCACHE_SEEN))) { \
PL_reg_poscache[0] |= (1<<POSCACHE_SEEN); \
- else if ((PL_reg_poscache[0] & (1<<POSCACHE_SUCCESS))) { \
+ PL_reg_poscache[st->u.whilem.cache_offset] |= (1<<st->u.whilem.cache_bit); \
+ } \
+ else if (!(PL_reg_poscache[0] & (1<<POSCACHE_SUCCESS))) { \
+ PL_reg_poscache[st->u.whilem.cache_offset] |= (1<<st->u.whilem.cache_bit); \
+ } \
+ else { \
/* cache records success, but this is failure */ \
DEBUG_r( \
PerlIO_printf(Perl_debug_log, \
/* No need to save/restore up to this paren */
I32 parenfloor = scan->flags;
+ /* Dave says:
+
+ CURLYX and WHILEM are always paired: they're the moral
+ equivalent of pp_enteriter anbd pp_iter.
+
+ The only time next could be null is if the node tree is
+ corrupt. This was mentioned on p5p a few days ago.
+
+ See http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2006-04/msg00556.html
+ So we'll assert that this is true:
+ */
+ assert(next);
if (OP(PREVOPER(next)) == NOTHING) /* LONGJMP */
next += ARG(next);
/* XXXX Probably it is better to teach regpush to support
* that we can try again after backing off.
*/
+ /* Dave says:
+
+ st->cc gets initialised by CURLYX ready for use by WHILEM.
+ So again, unless somethings been corrupted, st->cc cannot
+ be null at that point in WHILEM.
+
+ See http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2006-04/msg00556.html
+ So we'll assert that this is true:
+ */
+ assert(st->cc);
st->u.whilem.lastloc = st->cc->u.curlyx.lastloc; /* Detection of 0-len. */
st->u.whilem.cache_offset = 0;
st->u.whilem.cache_bit = 0;
/* cache records failure */
sayNO_SILENT;
}
- PL_reg_poscache[st->u.whilem.cache_offset] |= (1<<st->u.whilem.cache_bit);
}
}
st->u.curlym.maxwanted = st->minmod ? st->ln : n;
if (st->u.curlym.maxwanted) {
while (PL_reginput < PL_regeol && st->u.curlym.matches < st->u.curlym.maxwanted) {
+ /* resume to current state on success */
+ st->u.yes.prev_yes_state = yes_state;
+ yes_state = st;
REGMATCH(scan, CURLYM1);
+ yes_state = st->u.yes.prev_yes_state;
/*** all unsaved local vars undefined at this point */
if (!result)
break;
else
PL_regendp[st->u.curlym.paren] = -1;
}
+ /* resume to current state on success */
+ st->u.yes.prev_yes_state = yes_state;
+ yes_state = st;
REGMATCH(next, CURLYM2);
+ yes_state = st->u.yes.prev_yes_state;
/*** all unsaved local vars undefined at this point */
if (result)
- sayYES;
+ /* XXX tmp sayYES; */
+ sayYES_FINAL;
REGCP_UNWIND(st->u.curlym.lastcp);
}
/* Couldn't or didn't -- move forward. */
PL_reginput = locinput;
+ /* resume to current state on success */
+ st->u.yes.prev_yes_state = yes_state;
+ yes_state = st;
REGMATCH(scan, CURLYM3);
+ yes_state = st->u.yes.prev_yes_state;
/*** all unsaved local vars undefined at this point */
if (result) {
st->ln++;
else
PL_regendp[st->u.curlym.paren] = -1;
}
+ /* resume to current state on success */
+ st->u.yes.prev_yes_state = yes_state;
+ yes_state = st;
REGMATCH(next, CURLYM4);
+ yes_state = st->u.yes.prev_yes_state;
/*** all unsaved local vars undefined at this point */
if (result)
- sayYES;
+ /* XXX tmp sayYES; */
+ sayYES_FINAL;
REGCP_UNWIND(st->u.curlym.lastcp);
}
/* Couldn't or didn't -- back up. */
}
PL_reginput = locinput; /* put where regtry can find it */
sayYES_FINAL; /* Success! */
- case SUCCEED:
+
+ case SUCCEED: /* successful SUSPEND/UNLESSM/IFMATCH/CURLYM */
+ DEBUG_EXECUTE_r(
+ PerlIO_printf(Perl_debug_log,
+ "%*s %ssubpattern success...%s\n",
+ REPORT_CODE_OFF+PL_regindent*2, "", PL_colors[4], PL_colors[5]));
PL_reginput = locinput; /* put where regtry can find it */
- sayYES_LOUD; /* Success! */
- case SUSPEND:
- n = 1;
+ sayYES_FINAL; /* Success! */
+
+ case SUSPEND: /* (?>FOO) */
+ st->u.ifmatch.wanted = 1;
PL_reginput = locinput;
goto do_ifmatch;
- case UNLESSM:
- n = 0;
- if (scan->flags) {
- char * const s = HOPBACKc(locinput, scan->flags);
- if (!s)
- goto say_yes;
- PL_reginput = s;
- }
- else
- PL_reginput = locinput;
- goto do_ifmatch;
- case IFMATCH:
- n = 1;
+
+ case UNLESSM: /* -ve lookaround: (?!FOO), or with flags, (?<!foo) */
+ st->u.ifmatch.wanted = 0;
+ goto ifmatch_trivial_fail_test;
+
+ case IFMATCH: /* +ve lookaround: (?=FOO), or with flags, (?<=foo) */
+ st->u.ifmatch.wanted = 1;
+ ifmatch_trivial_fail_test:
if (scan->flags) {
char * const s = HOPBACKc(locinput, scan->flags);
- if (!s)
- goto say_no;
+ if (!s) {
+ /* trivial fail */
+ if (st->logical) {
+ st->logical = 0;
+ st->sw = 1 - st->u.ifmatch.wanted;
+ }
+ else if (st->u.ifmatch.wanted)
+ sayNO;
+ next = scan + ARG(scan);
+ if (next == scan)
+ next = NULL;
+ break;
+ }
PL_reginput = s;
}
else
PL_reginput = locinput;
do_ifmatch:
- REGMATCH(NEXTOPER(NEXTOPER(scan)), IFMATCH);
- /*** all unsaved local vars undefined at this point */
- if (result != n) {
- say_no:
- if (st->logical) {
- st->logical = 0;
- st->sw = 0;
- goto do_longjump;
- }
- else
- sayNO;
- }
- say_yes:
- if (st->logical) {
- st->logical = 0;
- st->sw = 1;
- }
- if (OP(scan) == SUSPEND) {
- locinput = PL_reginput;
- nextchr = UCHARAT(locinput);
- }
- /* FALL THROUGH. */
+ /* resume to current state on success */
+ st->u.yes.prev_yes_state = yes_state;
+ yes_state = st;
+ PUSH_STATE(newst, resume_IFMATCH);
+ st = newst;
+ next = NEXTOPER(NEXTOPER(scan));
+ break;
+
case LONGJMP:
- do_longjump:
next = scan + ARG(scan);
if (next == scan)
next = NULL;
/*NOTREACHED*/
sayNO;
-yes_loud:
- DEBUG_EXECUTE_r(
- PerlIO_printf(Perl_debug_log,
- "%*s %scould match...%s\n",
- REPORT_CODE_OFF+PL_regindent*2, "", PL_colors[4], PL_colors[5])
- );
- goto yes;
yes_final:
if (yes_state) {
/* we have successfully completed a subexpression, but we must now
* pop to the state marked by yes_state and continue from there */
+ /*XXX tmp for CURLYM*/
+ regmatch_slab *oslab = PL_regmatch_slab;
+ regmatch_state *ost = st, *oys=yes_state;
+ int odepth = depth;
+
assert(st != yes_state);
while (yes_state < SLAB_FIRST(PL_regmatch_slab)
|| yes_state > SLAB_LAST(PL_regmatch_slab))
st = SLAB_LAST(PL_regmatch_slab);
}
depth -= (st - yes_state);
- DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log, "POP STATE TO (%d)\n", depth)); \
+ DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log, "POP STATE TO (%d)\n", depth));
st = yes_state;
yes_state = st->u.yes.prev_yes_state;
PL_regmatch_state = st;
next = st->next;
goto reenter;
+ case resume_IFMATCH:
+ if (st->logical) {
+ st->logical = 0;
+ st->sw = st->u.ifmatch.wanted;
+ }
+ else if (!st->u.ifmatch.wanted)
+ sayNO;
+
+ if (OP(st->scan) == SUSPEND)
+ locinput = PL_reginput;
+ else {
+ locinput = PL_reginput = st->locinput;
+ nextchr = UCHARAT(locinput);
+ }
+ next = st->scan + ARG(st->scan);
+ if (next == st->scan)
+ next = NULL;
+ goto reenter;
+
+ /* XXX tmp don't handle yes_state yet */
+ case resume_CURLYM1:
+ case resume_CURLYM2:
+ case resume_CURLYM3:
+ case resume_CURLYM4:
+ PL_regmatch_slab =oslab;
+ st = ost;
+ PL_regmatch_state = st;
+ depth = odepth;
+ yes_state = oys;
+ DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log, "XXX revering a CURLYM\n"));
+ goto yes;
+
default:
Perl_croak(aTHX_ "unexpected yes reume state");
}
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:
case resume_PLUS4:
goto resume_point_PLUS4;
+ case resume_IFMATCH:
case resume_EVAL:
default:
Perl_croak(aTHX_ "regexp resume memory corruption");
case resume_CURLYM4:
goto resume_point_CURLYM4;
case resume_IFMATCH:
- goto resume_point_IFMATCH;
+ yes_state = st->u.yes.prev_yes_state;
+ if (st->logical) {
+ st->logical = 0;
+ st->sw = !st->u.ifmatch.wanted;
+ }
+ else if (st->u.ifmatch.wanted)
+ sayNO;
+
+ assert(OP(scan) != SUSPEND); /* XXX DAPM tmp */
+ locinput = PL_reginput = st->locinput;
+ nextchr = UCHARAT(locinput);
+ next = scan + ARG(scan);
+ if (next == scan)
+ next = NULL;
+ goto reenter;
+
case resume_PLUS1:
goto resume_point_PLUS1;
case resume_PLUS2: