/* push a new state then goto it */
-#define PUSH_STATE_GOTO(state, node, input) \
+#define PUSH_STATE_GOTO(state, node, input, eol) \
pushinput = input; \
+ pusheol = eol; \
scan = node; \
st->resume_state = state; \
goto push_state;
/* push a new state with success backtracking, then goto it */
-#define PUSH_YES_STATE_GOTO(state, node, input) \
+#define PUSH_YES_STATE_GOTO(state, node, input, eol) \
pushinput = input; \
+ pusheol = eol; \
scan = node; \
st->resume_state = state; \
goto push_yes_state;
want to claim it, populate any ST.foo fields in it with values you wish to
save, then do one of
- PUSH_STATE_GOTO(resume_state, node, newinput);
- PUSH_YES_STATE_GOTO(resume_state, node, newinput);
+ PUSH_STATE_GOTO(resume_state, node, newinput, new_eol);
+ PUSH_YES_STATE_GOTO(resume_state, node, newinput, new_eol);
which sets that backtrack state's resume value to 'resume_state', pushes a
new free entry to the top of the backtrack stack, then goes to 'node'.
char *locinput = startpos;
char *loceol = reginfo->strend;
char *pushinput; /* where to continue after a PUSH */
+ char *pusheol; /* where to stop matching (loceol) after a PUSH */
I32 nextchr; /* is always set to UCHARAT(locinput), or -1 at EOS */
bool result = 0; /* return value of S_regmatch */
/* update the startpoint */
st->u.keeper.val = rex->offs[0].start;
rex->offs[0].start = locinput - reginfo->strbeg;
- PUSH_STATE_GOTO(KEEPS_next, next, locinput);
+ PUSH_STATE_GOTO(KEEPS_next, next, locinput, loceol);
NOT_REACHED; /* NOTREACHED */
case KEEPS_next_fail:
});
if ( ST.accepted > 1 || has_cutgroup || ST.jump ) {
- PUSH_STATE_GOTO(TRIE_next, scan, (char*)uc);
+ PUSH_STATE_GOTO(TRIE_next, scan, (char*)uc, loceol);
NOT_REACHED; /* NOTREACHED */
}
/* only one choice left - just continue */
PL_curpm = PL_reg_curpm;
if (logical != 2) {
- PUSH_STATE_GOTO(EVAL_B, next, locinput);
+ PUSH_STATE_GOTO(EVAL_B, next, locinput, loceol);
/* NOTREACHED */
}
}
ST.prev_eval = cur_eval;
cur_eval = st;
/* now continue from first node in postoned RE */
- PUSH_YES_STATE_GOTO(EVAL_postponed_AB, startpoint, locinput);
+ PUSH_YES_STATE_GOTO(EVAL_postponed_AB, startpoint, locinput, loceol);
NOT_REACHED; /* NOTREACHED */
}
ST.count = -1; /* this will be updated by WHILEM */
ST.lastloc = NULL; /* this will be updated by WHILEM */
- PUSH_YES_STATE_GOTO(CURLYX_end, PREVOPER(next), locinput);
+ PUSH_YES_STATE_GOTO(CURLYX_end, PREVOPER(next), locinput, loceol);
NOT_REACHED; /* NOTREACHED */
}
cur_curlyx->u.curlyx.lastloc = locinput;
REGCP_SET(ST.lastcp);
- PUSH_STATE_GOTO(WHILEM_A_pre, A, locinput);
+ PUSH_STATE_GOTO(WHILEM_A_pre, A, locinput, loceol);
NOT_REACHED; /* NOTREACHED */
}
ST.save_curlyx = cur_curlyx;
cur_curlyx = cur_curlyx->u.curlyx.prev_curlyx;
PUSH_YES_STATE_GOTO(WHILEM_B_min, ST.save_curlyx->u.curlyx.B,
- locinput);
+ locinput, loceol);
NOT_REACHED; /* NOTREACHED */
}
maxopenparen);
cur_curlyx->u.curlyx.lastloc = locinput;
REGCP_SET(ST.lastcp);
- PUSH_STATE_GOTO(WHILEM_A_max, A, locinput);
+ PUSH_STATE_GOTO(WHILEM_A_max, A, locinput, loceol);
NOT_REACHED; /* NOTREACHED */
}
goto do_whilem_B_max;
ST.save_curlyx = cur_curlyx;
cur_curlyx = cur_curlyx->u.curlyx.prev_curlyx;
PUSH_YES_STATE_GOTO(WHILEM_B_max, ST.save_curlyx->u.curlyx.B,
- locinput);
+ locinput, loceol);
NOT_REACHED; /* NOTREACHED */
case WHILEM_B_min_fail: /* just failed to match B in a minimal match */
REGCP_SET(ST.lastcp);
PUSH_STATE_GOTO(WHILEM_A_min,
/*A*/ NEXTOPER(ST.save_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS,
- locinput);
+ locinput, loceol);
NOT_REACHED; /* NOTREACHED */
#undef ST
/* Now go into the branch */
if (has_cutgroup) {
- PUSH_YES_STATE_GOTO(BRANCH_next, scan, locinput);
+ PUSH_YES_STATE_GOTO(BRANCH_next, scan, locinput, loceol);
} else {
- PUSH_STATE_GOTO(BRANCH_next, scan, locinput);
+ PUSH_STATE_GOTO(BRANCH_next, scan, locinput, loceol);
}
NOT_REACHED; /* NOTREACHED */
sv_yes_mark = st->u.mark.mark_name = scan->flags
? MUTABLE_SV(rexi->data->data[ ARG( scan ) ])
: NULL;
- PUSH_STATE_GOTO(CUTGROUP_next, next, locinput);
+ PUSH_STATE_GOTO(CUTGROUP_next, next, locinput, loceol);
NOT_REACHED; /* NOTREACHED */
case CUTGROUP_next_fail:
goto curlym_do_B;
curlym_do_A: /* execute the A in /A{m,n}B/ */
- PUSH_YES_STATE_GOTO(CURLYM_A, ST.A, locinput); /* match A */
+ PUSH_YES_STATE_GOTO(CURLYM_A, ST.A, locinput, loceol); /* match A */
NOT_REACHED; /* NOTREACHED */
case CURLYM_A: /* we've just matched an A */
}
}
- PUSH_STATE_GOTO(CURLYM_B, ST.B, locinput); /* match B */
+ PUSH_STATE_GOTO(CURLYM_B, ST.B, locinput, loceol); /* match B */
NOT_REACHED; /* NOTREACHED */
case CURLYM_B_fail: /* just failed to match a B */
curly_try_B_min:
CURLY_SETPAREN(ST.paren, ST.count);
- PUSH_STATE_GOTO(CURLY_B_min, ST.B, locinput);
+ PUSH_STATE_GOTO(CURLY_B_min, ST.B, locinput, loceol);
NOT_REACHED; /* NOTREACHED */
}
if (ST.c1 == CHRTEST_VOID || could_match) {
CURLY_SETPAREN(ST.paren, ST.count);
- PUSH_STATE_GOTO(CURLY_B_max, ST.B, locinput);
+ PUSH_STATE_GOTO(CURLY_B_max, ST.B, locinput, loceol);
NOT_REACHED; /* NOTREACHED */
}
}
SET_RECURSE_LOCINPUT("FAKE-END[after]", cur_eval->locinput);
PUSH_YES_STATE_GOTO(EVAL_postponed_AB, st->u.eval.prev_eval->u.eval.B,
- locinput); /* match B */
+ locinput, loceol); /* match B */
}
if (locinput < reginfo->till) {
logical = 0; /* XXX: reset state of logical once it has been saved into ST */
/* execute body of (?...A) */
- PUSH_YES_STATE_GOTO(IFMATCH_A, NEXTOPER(NEXTOPER(scan)), newstart);
+ PUSH_YES_STATE_GOTO(IFMATCH_A, NEXTOPER(NEXTOPER(scan)), newstart, loceol);
NOT_REACHED; /* NOTREACHED */
}
if (OP(ST.me) != SUSPEND) {
/* restore old position except for (?>...) */
locinput = st->locinput;
+ loceol = st->loceol;
}
scan = ST.me + ARG(ST.me);
if (scan == ST.me)
case PRUNE: /* (*PRUNE) */
if (scan->flags)
sv_yes_mark = sv_commit = MUTABLE_SV(rexi->data->data[ ARG( scan ) ]);
- PUSH_STATE_GOTO(COMMIT_next, next, locinput);
+ PUSH_STATE_GOTO(COMMIT_next, next, locinput, loceol);
NOT_REACHED; /* NOTREACHED */
case COMMIT_next_fail:
= MUTABLE_SV(rexi->data->data[ ARG( scan ) ]);
mark_state = st;
ST.mark_loc = locinput;
- PUSH_YES_STATE_GOTO(MARKPOINT_next, next, locinput);
+ PUSH_YES_STATE_GOTO(MARKPOINT_next, next, locinput, loceol);
NOT_REACHED; /* NOTREACHED */
case MARKPOINT_next:
/* (*SKIP) : if we fail we cut here*/
ST.mark_name = NULL;
ST.mark_loc = locinput;
- PUSH_STATE_GOTO(SKIP_next,next, locinput);
+ PUSH_STATE_GOTO(SKIP_next,next, locinput, loceol);
} else {
/* (*SKIP:NAME) : if there is a (*MARK:NAME) fail where it was,
otherwise do nothing. Meaning we need to scan
find ) )
{
ST.mark_name = find;
- PUSH_STATE_GOTO( SKIP_next, next, locinput);
+ PUSH_STATE_GOTO( SKIP_next, next, locinput, loceol);
}
cur = cur->u.mark.prev_mark;
}
);
depth++;
st->locinput = locinput;
+ st->loceol = loceol;
newst = st+1;
if (newst > SLAB_LAST(PL_regmatch_slab))
newst = S_push_slab(aTHX);
PL_regmatch_state = newst;
locinput = pushinput;
+ loceol = pusheol;
st = newst;
continue;
/* NOTREACHED */
yes_state = st->u.yes.prev_yes_state;
PL_regmatch_state = st;
- if (no_final)
+ if (no_final) {
locinput= st->locinput;
+ loceol= st->loceol;
+ }
state_num = st->resume_state + no_final;
goto reenter_switch;
}
}
PL_regmatch_state = st;
locinput= st->locinput;
+ loceol= st->loceol;
DEBUG_STATE_pp("pop");
depth--;