**** Alterations to Henry's code are...
****
**** Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- **** 2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
+ **** 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by Larry Wall and others
****
**** You may distribute under the terms of either the GNU General Public
**** License or the Artistic License, as specified in the README file.
OP(rn) == OPEN || OP(rn) == CLOSE || OP(rn) == EVAL || \
OP(rn) == SUSPEND || OP(rn) == IFMATCH || \
OP(rn) == PLUS || OP(rn) == MINMOD || \
+ OP(rn) == KEEPS || (PL_regkind[OP(rn)] == VERB) || \
(PL_regkind[OP(rn)] == CURLY && ARG1(rn) > 0) \
)
+#define IS_EXACT(rn) (PL_regkind[OP(rn)] == EXACT)
-#define HAS_TEXT(rn) ( \
- PL_regkind[OP(rn)] == EXACT || PL_regkind[OP(rn)] == REF \
-)
+#define HAS_TEXT(rn) ( IS_EXACT(rn) || PL_regkind[OP(rn)] == REF )
+
+#if 0
+/* Currently these are only used when PL_regkind[OP(rn)] == EXACT so
+ we don't need this definition. */
+#define IS_TEXT(rn) ( OP(rn)==EXACT || OP(rn)==REF || OP(rn)==NREF )
+#define IS_TEXTF(rn) ( OP(rn)==EXACTF || OP(rn)==REFF || OP(rn)==NREFF )
+#define IS_TEXTFL(rn) ( OP(rn)==EXACTFL || OP(rn)==REFFL || OP(rn)==NREFFL )
+
+#else
+/* ... so we use this as its faster. */
+#define IS_TEXT(rn) ( OP(rn)==EXACT )
+#define IS_TEXTF(rn) ( OP(rn)==EXACTF )
+#define IS_TEXTFL(rn) ( OP(rn)==EXACTFL )
+
+#endif
/*
Search for mandatory following text node; for lookahead, the text must
/* end shift should be non negative here */
}
-#ifdef DEBUGGING /* 7/99: reports of failure (with the older version) */
+#ifdef QDEBUGGING /* 7/99: reports of failure (with the older version) */
if (end_shift < 0)
Perl_croak(aTHX_ "panic: end_shift: %"IVdf" pattern:\n%s\n ",
(IV)end_shift, prog->precomp);
-#define REXEC_TRIE_READ_CHAR(trie_type, trie, uc, uscan, len, uvc, charid, \
-foldlen, foldbuf, uniflags) STMT_START { \
+#define REXEC_TRIE_READ_CHAR(trie_type, trie, widecharmap, uc, uscan, len, \
+uvc, charid, foldlen, foldbuf, uniflags) STMT_START { \
switch (trie_type) { \
case trie_utf8_fold: \
if ( foldlen>0 ) { \
} \
else { \
charid = 0; \
- if (trie->widecharmap) { \
- SV** const svpp = hv_fetch(trie->widecharmap, \
+ if (widecharmap) { \
+ SV** const svpp = hv_fetch(widecharmap, \
(char*)&uvc, sizeof(UV), 0); \
if (svpp) \
charid = (U16)SvIV(*svpp); \
/* what trie are we using right now */
reg_ac_data *aho
= (reg_ac_data*)progi->data->data[ ARG( c ) ];
- reg_trie_data *trie=aho->trie;
+ reg_trie_data *trie
+ = (reg_trie_data*)progi->data->data[ aho->trie ];
+ HV *widecharmap = (HV*) progi->data->data[ aho->trie + 1 ];
const char *last_start = strend - trie->minlen;
#ifdef DEBUGGING
}
points[pointpos++ % maxlen]= uc;
- REXEC_TRIE_READ_CHAR(trie_type, trie, uc, uscan, len,
- uvc, charid, foldlen, foldbuf, uniflags);
+ REXEC_TRIE_READ_CHAR(trie_type, trie, widecharmap, uc,
+ uscan, len, uvc, charid, foldlen,
+ foldbuf, uniflags);
DEBUG_TRIE_EXECUTE_r({
dump_exec_pos( (char *)uc, c, strend, real_start,
s, do_utf8 );
}
+
+
/*
- regtry - try match at specific point
*/
if (locinput == reginfo->ganch)
break;
sayNO;
+
+ case KEEPS:
+ /* update the startpoint */
+ st->u.keeper.val = PL_regstartp[0];
+ PL_reginput = locinput;
+ PL_regstartp[0] = locinput - PL_bostr;
+ PUSH_STATE_GOTO(KEEPS_next, next);
+ /*NOT-REACHED*/
+ case KEEPS_next_fail:
+ /* rollback the start point change */
+ PL_regstartp[0] = st->u.keeper.val;
+ sayNO_SILENT;
+ /*NOT-REACHED*/
case EOL:
goto seol;
case MEOL:
/* what trie are we using right now */
reg_trie_data * const trie
= (reg_trie_data*)rexi->data->data[ ARG( scan ) ];
+ HV * widecharmap = (HV *)rexi->data->data[ ARG( scan ) + 1 ];
U32 state = trie->startstate;
if (trie->bitmap && trie_type != trie_utf8_fold &&
});
if ( base ) {
- REXEC_TRIE_READ_CHAR(trie_type, trie, uc, uscan, len,
- uvc, charid, foldlen, foldbuf, uniflags);
+ REXEC_TRIE_READ_CHAR(trie_type, trie, widecharmap, uc,
+ uscan, len, uvc, charid, foldlen,
+ foldbuf, uniflags);
if (charid &&
(base + charid > trie->uniquecharcount )
if ( ST.accepted == 1 ) {
/* only one choice left - just continue */
DEBUG_EXECUTE_r({
- reg_trie_data * const trie
- = (reg_trie_data*)rexi->data->data[ ARG(ST.me) ];
- SV ** const tmp = av_fetch( trie->words,
+ AV *const trie_words
+ = (AV *) rexi->data->data[ARG(ST.me)+TRIE_WORDS_OFFSET];
+ SV ** const tmp = av_fetch( trie_words,
ST.accept_buff[ 0 ].wordnum-1, 0 );
SV *sv= tmp ? sv_newmortal() : NULL;
}
DEBUG_EXECUTE_r({
- reg_trie_data * const trie
- = (reg_trie_data*)rexi->data->data[ ARG(ST.me) ];
- SV ** const tmp = av_fetch( trie->words,
+ AV *const trie_words
+ = (AV *) rexi->data->data[ARG(ST.me)+TRIE_WORDS_OFFSET];
+ SV ** const tmp = av_fetch( trie_words,
ST.accept_buff[ best ].wordnum - 1, 0 );
regnode *nextop=(!ST.jump || !ST.jump[ST.accept_buff[best].wordnum]) ?
ST.B :
} else {
nochange_depth = 0;
}
+ { regexp *ocurpm = PM_GETRE(PL_curpm);
+ char *osubbeg = rex->subbeg;
+ STRLEN osublen = rex->sublen;
{
/* execute the code in the {...} */
dSP;
OP_4tree * const oop = PL_op;
COP * const ocurcop = PL_curcop;
PAD *old_comppad;
+
n = ARG(scan);
PL_op = (OP_4tree*)rexi->data->data[n];
PAD_SAVE_LOCAL(old_comppad, (PAD*)rexi->data->data[n + 2]);
PL_regendp[0] = PL_reg_magic->mg_len = locinput - PL_bostr;
+ if (sv_yes_mark) {
+ SV *sv_mrk = get_sv("REGMARK", 1);
+ sv_setsv(sv_mrk, sv_yes_mark);
+ }
+ /* make sure that $1 and friends are available with nested eval */
+ PM_SETRE(PL_curpm,rex);
+ rex->subbeg = ocurpm->subbeg;
+ rex->sublen = ocurpm->sublen;
+
CALLRUNOPS(aTHX); /* Scalar context. */
SPAGAIN;
if (SP == before)
PL_op = oop;
PAD_RESTORE_LOCAL(old_comppad);
PL_curcop = ocurcop;
+
if (!logical) {
/* /(?{...})/ */
sv_setsv(save_scalar(PL_replgv), ret);
}
}
rei = RXi_GET(re);
+
+ /* restore PL_curpm after the eval */
+ PM_SETRE(PL_curpm,ocurpm);
+ rex->sublen = osublen;
+ rex->subbeg = osubbeg;
+
DEBUG_EXECUTE_r(
debug_start_match(re, do_utf8, locinput, PL_regeol,
"Matching embedded");
Renew(PL_reg_start_tmp, PL_reg_start_tmpl, char*);
else
Newx(PL_reg_start_tmp, PL_reg_start_tmpl, char*);
- }
+ }
+
eval_recurse_doit: /* Share code with GOSUB below this line */
/* run the pattern returned from (??{...}) */
PUSH_YES_STATE_GOTO(EVAL_AB, startpoint);
/* NOTREACHED */
}
+ /* restore PL_curpm after the eval */
+ PM_SETRE(PL_curpm,ocurpm);
+ rex->sublen = osublen;
+ rex->subbeg = osubbeg;
+ }
/* logical is 1, /(?(?{...})X|Y)/ */
sw = (bool)SvTRUE(ret);
logical = 0;
regnode *text_node = ST.B;
if (! HAS_TEXT(text_node))
FIND_NEXT_IMPT(text_node);
- if (HAS_TEXT(text_node)
- && PL_regkind[OP(text_node)] != REF)
+ /* this used to be
+
+ (HAS_TEXT(text_node) && PL_regkind[OP(text_node)] == EXACT)
+
+ But the former is redundant in light of the latter.
+
+ if this changes back then the macro for
+ IS_TEXT and friends need to change.
+ */
+ if (PL_regkind[OP(text_node)] == EXACT)
{
+
ST.c1 = (U8)*STRING(text_node);
ST.c2 =
- (OP(text_node) == EXACTF || OP(text_node) == REFF)
+ (IS_TEXTF(text_node))
? PL_fold[ST.c1]
- : (OP(text_node) == EXACTFL || OP(text_node) == REFFL)
+ : (IS_TEXTFL(text_node))
? PL_fold_locale[ST.c1]
: ST.c1;
}
if (! HAS_TEXT(text_node))
ST.c1 = ST.c2 = CHRTEST_VOID;
else {
- if (PL_regkind[OP(text_node)] == REF) {
+ if ( PL_regkind[OP(text_node)] != EXACT ) {
ST.c1 = ST.c2 = CHRTEST_VOID;
goto assume_ok_easy;
}
else
s = (U8*)STRING(text_node);
-
+
+ /* Currently we only get here when
+
+ PL_rekind[OP(text_node)] == EXACT
+
+ if this changes back then the macro for IS_TEXT and
+ friends need to change. */
if (!UTF) {
ST.c2 = ST.c1 = *s;
- if (OP(text_node) == EXACTF || OP(text_node) == REFF)
+ if (IS_TEXTF(text_node))
ST.c2 = PL_fold[ST.c1];
- else if (OP(text_node) == EXACTFL || OP(text_node) == REFFL)
+ else if (IS_TEXTFL(text_node))
ST.c2 = PL_fold_locale[ST.c1];
}
else { /* UTF */
- if (OP(text_node) == EXACTF || OP(text_node) == REFF) {
+ if (IS_TEXTF(text_node)) {
STRLEN ulen1, ulen2;
U8 tmpbuf1[UTF8_MAXBYTES_CASE+1];
U8 tmpbuf2[UTF8_MAXBYTES_CASE+1];
PerlIO_printf(Perl_debug_log,
"%*s %ssetting cutpoint to mark:%"SVf"...%s\n",
REPORT_CODE_OFF+depth*2, "",
- PL_colors[4], sv_commit, PL_colors[5]);
+ PL_colors[4], SVfARG(sv_commit), PL_colors[5]);
});
}
mark_state = ST.prev_mark;
case SKIP:
PL_reginput = locinput;
if (scan->flags) {
- /* (*CUT) : if we fail we cut here*/
+ /* (*SKIP) : if we fail we cut here*/
ST.mark_name = NULL;
ST.mark_loc = locinput;
PUSH_STATE_GOTO(SKIP_next,next);
} else {
- /* (*CUT:NAME) : if there is a (*MARK:NAME) fail where it was,
+ /* (*SKIP:NAME) : if there is a (*MARK:NAME) fail where it was,
otherwise do nothing. Meaning we need to scan
*/
regmatch_state *cur = mark_state;
cur = cur->u.mark.prev_mark;
}
}
- /* Didn't find our (*MARK:NAME) so ignore this (*CUT:NAME) */
+ /* Didn't find our (*MARK:NAME) so ignore this (*SKIP:NAME) */
break;
case SKIP_next_fail:
if (ST.mark_name) {
STATIC void
S_to_utf8_substr(pTHX_ register regexp *prog)
{
- if (prog->float_substr && !prog->float_utf8) {
- SV* const sv = newSVsv(prog->float_substr);
- prog->float_utf8 = sv;
- sv_utf8_upgrade(sv);
- if (SvTAIL(prog->float_substr))
- SvTAIL_on(sv);
- if (prog->float_substr == prog->check_substr)
- prog->check_utf8 = sv;
- }
- if (prog->anchored_substr && !prog->anchored_utf8) {
- SV* const sv = newSVsv(prog->anchored_substr);
- prog->anchored_utf8 = sv;
- sv_utf8_upgrade(sv);
- if (SvTAIL(prog->anchored_substr))
- SvTAIL_on(sv);
- if (prog->anchored_substr == prog->check_substr)
- prog->check_utf8 = sv;
- }
+ int i = 1;
+ do {
+ if (prog->substrs->data[i].substr
+ && !prog->substrs->data[i].utf8_substr) {
+ SV* const sv = newSVsv(prog->substrs->data[i].substr);
+ prog->substrs->data[i].utf8_substr = sv;
+ sv_utf8_upgrade(sv);
+ if (SvVALID(prog->substrs->data[i].substr))
+ fbm_compile(sv, 0);
+ if (SvTAIL(prog->substrs->data[i].substr))
+ SvTAIL_on(sv);
+ if (prog->substrs->data[i].substr == prog->check_substr)
+ prog->check_utf8 = sv;
+ }
+ } while (i--);
}
STATIC void
S_to_byte_substr(pTHX_ register regexp *prog)
{
dVAR;
- if (prog->float_utf8 && !prog->float_substr) {
- SV* sv = newSVsv(prog->float_utf8);
- prog->float_substr = sv;
- if (sv_utf8_downgrade(sv, TRUE)) {
- if (SvTAIL(prog->float_utf8))
- SvTAIL_on(sv);
- } else {
- SvREFCNT_dec(sv);
- prog->float_substr = sv = &PL_sv_undef;
- }
- if (prog->float_utf8 == prog->check_utf8)
- prog->check_substr = sv;
- }
- if (prog->anchored_utf8 && !prog->anchored_substr) {
- SV* sv = newSVsv(prog->anchored_utf8);
- prog->anchored_substr = sv;
- if (sv_utf8_downgrade(sv, TRUE)) {
- if (SvTAIL(prog->anchored_utf8))
- SvTAIL_on(sv);
- } else {
- SvREFCNT_dec(sv);
- prog->anchored_substr = sv = &PL_sv_undef;
+ int i = 1;
+ do {
+ if (prog->substrs->data[i].utf8_substr
+ && !prog->substrs->data[i].substr) {
+ SV* sv = newSVsv(prog->substrs->data[i].utf8_substr);
+ if (sv_utf8_downgrade(sv, TRUE)) {
+ if (SvVALID(prog->substrs->data[i].utf8_substr))
+ fbm_compile(sv, 0);
+ if (SvTAIL(prog->substrs->data[i].utf8_substr))
+ SvTAIL_on(sv);
+ } else {
+ SvREFCNT_dec(sv);
+ sv = &PL_sv_undef;
+ }
+ prog->substrs->data[i].substr = sv;
+ if (prog->substrs->data[i].utf8_substr == prog->check_utf8)
+ prog->check_substr = sv;
}
- if (prog->anchored_utf8 == prog->check_utf8)
- prog->check_substr = sv;
- }
+ } while (i--);
}
/*