struct subst {
I32 sbu_iters;
I32 sbu_maxiters;
- I32 sbu_safebase;
+ I32 sbu_rflags;
I32 sbu_oldsave;
bool sbu_once;
bool sbu_rxtainted;
};
#define sb_iters cx_u.cx_subst.sbu_iters
#define sb_maxiters cx_u.cx_subst.sbu_maxiters
-#define sb_safebase cx_u.cx_subst.sbu_safebase
+#define sb_rflags cx_u.cx_subst.sbu_rflags
#define sb_oldsave cx_u.cx_subst.sbu_oldsave
#define sb_once cx_u.cx_subst.sbu_once
#define sb_rxtainted cx_u.cx_subst.sbu_rxtainted
#define PUSHSUBST(cx) CXINC, cx = &cxstack[cxstack_ix], \
cx->sb_iters = iters, \
cx->sb_maxiters = maxiters, \
- cx->sb_safebase = safebase, \
+ cx->sb_rflags = r_flags, \
cx->sb_oldsave = oldsave, \
cx->sb_once = once, \
cx->sb_rxtainted = rxtainted, \
#define PL_reg_call_cc (PL_curinterp->Treg_call_cc)
#define PL_reg_eval_set (PL_curinterp->Treg_eval_set)
#define PL_reg_flags (PL_curinterp->Treg_flags)
+#define PL_reg_ganch (PL_curinterp->Treg_ganch)
#define PL_reg_re (PL_curinterp->Treg_re)
#define PL_reg_start_tmp (PL_curinterp->Treg_start_tmp)
#define PL_reg_start_tmpl (PL_curinterp->Treg_start_tmpl)
+#define PL_reg_sv (PL_curinterp->Treg_sv)
#define PL_regbol (PL_curinterp->Tregbol)
#define PL_regcc (PL_curinterp->Tregcc)
#define PL_regcode (PL_curinterp->Tregcode)
#define PL_Treg_call_cc PL_reg_call_cc
#define PL_Treg_eval_set PL_reg_eval_set
#define PL_Treg_flags PL_reg_flags
+#define PL_Treg_ganch PL_reg_ganch
#define PL_Treg_re PL_reg_re
#define PL_Treg_start_tmp PL_reg_start_tmp
#define PL_Treg_start_tmpl PL_reg_start_tmpl
+#define PL_Treg_sv PL_reg_sv
#define PL_Tregbol PL_regbol
#define PL_Tregcc PL_regcc
#define PL_Tregcode PL_regcode
#define PL_reg_call_cc (thr->Treg_call_cc)
#define PL_reg_eval_set (thr->Treg_eval_set)
#define PL_reg_flags (thr->Treg_flags)
+#define PL_reg_ganch (thr->Treg_ganch)
#define PL_reg_re (thr->Treg_re)
#define PL_reg_start_tmp (thr->Treg_start_tmp)
#define PL_reg_start_tmpl (thr->Treg_start_tmpl)
+#define PL_reg_sv (thr->Treg_sv)
#define PL_regbol (thr->Tregbol)
#define PL_regcc (thr->Tregcc)
#define PL_regcode (thr->Tregcode)
#define PL_reg_eval_set pPerl->PL_reg_eval_set
#undef PL_reg_flags
#define PL_reg_flags pPerl->PL_reg_flags
+#undef PL_reg_ganch
+#define PL_reg_ganch pPerl->PL_reg_ganch
#undef PL_reg_re
#define PL_reg_re pPerl->PL_reg_re
#undef PL_reg_start_tmp
#define PL_reg_start_tmp pPerl->PL_reg_start_tmp
#undef PL_reg_start_tmpl
#define PL_reg_start_tmpl pPerl->PL_reg_start_tmpl
+#undef PL_reg_sv
+#define PL_reg_sv pPerl->PL_reg_sv
#undef PL_regbol
#define PL_regbol pPerl->PL_regbol
#undef PL_regcc
else {
maxiters += (strend - s) * rx->nparens;
while (s < strend && --limit &&
- CALLREGEXEC(rx, s, strend, orig, 1, Nullsv, NULL, 0))
+ CALLREGEXEC(rx, s, strend, orig, 1, sv, NULL, 0))
{
TAINT_IF(RX_MATCH_TAINTED(rx));
if (rx->subbase
/* Are we done */
if (cx->sb_once || !CALLREGEXEC(rx, s, cx->sb_strend, orig,
- s == m, Nullsv, NULL,
- cx->sb_safebase ? 0 : REXEC_COPY_STR))
+ s == m, Nullsv, cx->sb_targ,
+ ((cx->sb_rflags & REXEC_COPY_STR)
+ ? 0 : REXEC_COPY_STR)))
{
SV *targ = cx->sb_targ;
sv_catpvn(dstr, s, cx->sb_strend - s);
register char *s;
char *strend;
I32 global;
- I32 safebase;
+ I32 r_flags;
char *truebase;
register REGEXP *rx = pm->op_pmregexp;
bool rxtainted;
I32 minmatch = 0;
I32 oldsave = PL_savestack_ix;
I32 update_minmatch = 1;
- SV *screamer;
if (PL_op->op_flags & OPf_STACKED)
TARG = POPs;
}
if (rx->minlen > len) goto failure;
- screamer = ( (SvSCREAM(TARG) && rx->check_substr
- && SvTYPE(rx->check_substr) == SVt_PVBM
- && SvVALID(rx->check_substr))
- ? TARG : Nullsv);
truebase = t = s;
if (global = pm->op_pmflags & PMf_GLOBAL) {
rx->startp[0] = 0;
}
}
}
- safebase = ((gimme != G_ARRAY && !global && rx->nparens)
+ r_flags = ((gimme != G_ARRAY && !global && rx->nparens)
|| SvTEMP(TARG) || PL_sawampersand)
? REXEC_COPY_STR : 0;
+ if (SvSCREAM(TARG) && rx->check_substr
+ && SvTYPE(rx->check_substr) == SVt_PVBM
+ && SvVALID(rx->check_substr))
+ r_flags |= REXEC_SCREAM;
+
if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) {
SAVEINT(PL_multiline);
PL_multiline = pm->op_pmflags & PMf_MULTILINE;
}
if (rx->check_substr) {
if (!(rx->reganch & ROPT_NOSCAN)) { /* Floating checkstring. */
- if ( screamer ) {
+ if (r_flags & REXEC_SCREAM) {
I32 p = -1;
char *b;
rx->float_substr = Nullsv;
}
}
- if (CALLREGEXEC(rx, s, strend, truebase, minmatch,
- screamer, NULL, safebase))
+ if (CALLREGEXEC(rx, s, strend, truebase, minmatch, TARG, NULL, r_flags))
{
PL_curpm = pm;
if (pm->op_pmflags & PMf_ONCE)
bool once;
bool rxtainted;
char *orig;
- I32 safebase;
+ I32 r_flags;
register REGEXP *rx = pm->op_pmregexp;
STRLEN len;
int force_on_match = 0;
I32 oldsave = PL_savestack_ix;
I32 update_minmatch = 1;
- SV *screamer;
/* known replacement string? */
dstr = (pm->op_pmflags & PMf_CONST) ? POPs : Nullsv;
pm = PL_curpm;
rx = pm->op_pmregexp;
}
- screamer = ( (SvSCREAM(TARG) && rx->check_substr
- && SvTYPE(rx->check_substr) == SVt_PVBM
- && SvVALID(rx->check_substr))
- ? TARG : Nullsv);
- safebase = (rx->nparens || SvTEMP(TARG) || PL_sawampersand)
+ r_flags = (rx->nparens || SvTEMP(TARG) || PL_sawampersand)
? REXEC_COPY_STR : 0;
+ if (SvSCREAM(TARG) && rx->check_substr
+ && SvTYPE(rx->check_substr) == SVt_PVBM
+ && SvVALID(rx->check_substr))
+ r_flags |= REXEC_SCREAM;
if (pm->op_pmflags & (PMf_MULTILINE|PMf_SINGLELINE)) {
SAVEINT(PL_multiline);
PL_multiline = pm->op_pmflags & PMf_MULTILINE;
orig = m = s;
if (rx->check_substr) {
if (!(rx->reganch & ROPT_NOSCAN)) { /* It floats. */
- if (screamer) {
+ if (r_flags & REXEC_SCREAM) {
I32 p = -1;
char *b;
c = dstr ? SvPV(dstr, clen) : Nullch;
/* can do inplace substitution? */
- if (c && clen <= rx->minlen && (once || !(safebase & REXEC_COPY_STR))
+ if (c && clen <= rx->minlen && (once || !(r_flags & REXEC_COPY_STR))
&& !(rx->reganch & ROPT_LOOKBEHIND_SEEN)) {
- if (!CALLREGEXEC(rx, s, strend, orig, 0, screamer, NULL, safebase)) {
+ if (!CALLREGEXEC(rx, s, strend, orig, 0, TARG, NULL, r_flags)) {
SPAGAIN;
PUSHs(&PL_sv_no);
LEAVE_SCOPE(oldsave);
RETURN;
}
- if (CALLREGEXEC(rx, s, strend, orig, 0, screamer, NULL, safebase)) {
+ if (CALLREGEXEC(rx, s, strend, orig, 0, TARG, NULL, r_flags)) {
if (force_on_match) {
force_on_match = 0;
s = SvPV_force(TARG, len);
sv_catpvn(dstr, c, clen);
if (once)
break;
- } while (CALLREGEXEC(rx, s, strend, orig, s == m, Nullsv, NULL, safebase));
+ } while (CALLREGEXEC(rx, s, strend, orig, s == m, Nullsv, NULL, r_flags));
sv_catpvn(dstr, s, strend - s);
(void)SvOOK_off(TARG);
PL_regdata = prog->data;
PL_reg_re = prog;
}
-
+
/*
- regexec_flags - match a regexp against a string
*/
I32
regexec_flags(register regexp *prog, char *stringarg, register char *strend,
- char *strbeg, I32 minend, SV *screamer, void *data, U32 flags)
+ char *strbeg, I32 minend, SV *sv, void *data, U32 flags)
/* strend: pointer to null at end of string */
/* strbeg: real beginning of string */
/* minend: end of match must be >=minend after stringarg. */
start_shift = prog->check_offset_min; /* okay to underestimate on CC */
/* Should be nonnegative! */
end_shift = minlen - start_shift - CHR_SVLEN(prog->check_substr);
- if (screamer) {
+ if (flags & REXEC_SCREAM) {
if (PL_screamfirst[BmRARE(prog->check_substr)] >= 0)
- s = screaminstr(screamer, prog->check_substr,
+ s = screaminstr(sv, prog->check_substr,
start_shift + (stringarg - strbeg),
end_shift, &scream_pos, 0);
else
(strend - startpos > 60 ? "..." : ""))
);
+ if (prog->reganch & ROPT_GPOS_SEEN) {
+ MAGIC *mg;
+ int pos = 0;
+
+ if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)
+ && (mg = mg_find(sv, 'g')) && mg->mg_len >= 0)
+ pos = mg->mg_len;
+ PL_reg_ganch = startpos + pos;
+ }
+
/* Simplest case: anchored match need be tried only once. */
/* [unless only anchor is BOL and multiline is set] */
- if (prog->reganch & ROPT_ANCH) {
+ if (prog->reganch & (ROPT_ANCH & ~ROPT_ANCH_GPOS)) {
if (regtry(prog, startpos))
goto got_it;
- else if (!(prog->reganch & ROPT_ANCH_GPOS) &&
- (PL_multiline || (prog->reganch & ROPT_IMPLICIT)
- || (prog->reganch & ROPT_ANCH_MBOL)))
+ else if (PL_multiline || (prog->reganch & ROPT_IMPLICIT)
+ || (prog->reganch & ROPT_ANCH_MBOL)) /* XXXX SBOL? */
{
if (minlen)
dontbother = minlen - 1;
}
}
goto phooey;
+ } else if (prog->reganch & ROPT_ANCH_GPOS) {
+ if (regtry(prog, PL_reg_ganch))
+ goto got_it;
+ goto phooey;
}
/* Messy cases: unanchored match. */
dontbother = end_shift;
strend = HOPc(strend, -dontbother);
while ( (s <= last) &&
- (screamer
- ? (s = screaminstr(screamer, must, HOPc(s, back_min) - strbeg,
+ ((flags & REXEC_SCREAM)
+ ? (s = screaminstr(sv, must, HOPc(s, back_min) - strbeg,
end_shift, &scream_pos, 0))
: (s = fbm_instr((unsigned char*)HOP(s, back_min),
(unsigned char*)strend, must, 0))) ) {
char *last;
I32 oldpos = scream_pos;
- if (screamer) {
- last = screaminstr(screamer, prog->float_substr, s - strbeg,
+ if (flags & REXEC_SCREAM) {
+ last = screaminstr(sv, prog->float_substr, s - strbeg,
end_shift, &scream_pos, 1); /* last one */
if (!last) {
last = scream_olds; /* Only one occurence. */
break;
sayNO;
case GPOS:
- if (locinput == PL_regbol)
+ if (locinput == PL_reg_ganch)
break;
sayNO;
case EOL:
#define ROPT_LOOKBEHIND_SEEN 0x00100
#define ROPT_EVAL_SEEN 0x00200
#define ROPT_TAINTED_SEEN 0x00400
+#define ROPT_ANCH_SBOL 0x00800
/* 0xf800 of reganch is used by PMf_COMPILETIME */
#define REXEC_COPY_STR 1 /* Need to copy the string. */
#define REXEC_CHECKED 2 /* check_substr already checked. */
+#define REXEC_SCREAM 4 /* use scream table. */
#define ReREFCNT_inc(re) ((re && re->refcnt++), re)
#define ReREFCNT_dec(re) pregfree(re)
# the format supported by op/regexp.t. If you want to add a test
# that does fit that format, add it to op/re_tests, not here.
-print "1..162\n";
+print "1..168\n";
BEGIN {
chdir 't' if -d 't';
print "ok $test\n";
$test++;
+$str = 'abcde';
+pos $str = 2;
+
+print "not " if $str =~ /^\G/;
+print "ok $test\n";
+$test++;
+
+print "not " if $str =~ /^.\G/;
+print "ok $test\n";
+$test++;
+
+print "not " unless $str =~ /^..\G/;
+print "ok $test\n";
+$test++;
+
+print "not " if $str =~ /^...\G/;
+print "ok $test\n";
+$test++;
+
+print "not " unless $str =~ /.\G./ and $& eq 'bc';
+print "ok $test\n";
+$test++;
+
+print "not " unless $str =~ /\G../ and $& eq 'cd';
+print "ok $test\n";
+$test++;
+
# see if matching against temporaries (created via pp_helem()) is safe
{ foo => "ok $test\n".$^X }->{foo} =~ /^(.*)\n/g;
print "$1\n";
PERLVAR(Tregcc, CURCUR *) /* from regexec.c */
PERLVAR(Treg_call_cc, struct re_cc_state *) /* from regexec.c */
PERLVAR(Treg_re, regexp *) /* from regexec.c */
+PERLVAR(Treg_ganch, char *) /* position of \G */
+PERLVAR(Treg_sv, SV *) /* what we match against */
PERLVARI(Tregcompp, regcomp_t, FUNC_NAME_TO_PTR(pregcomp))
/* Pointer to RE compiler */