if (SvTAINTED(TOPs))
cx->sb_rxtainted |= SUBST_TAINT_REPL;
sv_catsv_nomg(dstr, POPs);
- /* XXX: the RX_GOFS stuff is to adjust for positive offsets of
- * \G for instance s/(.)\G//g with positive pos(). See #69056 and #114884
- * This whole \G thing makes a *lot* of things more difficult than they
- * should be. - Yves */
- /* Are we done */
if (CxONCE(cx) || s < orig ||
- !CALLREGEXEC(rx, s - RX_GOFS(rx), cx->sb_strend, orig,
- (s == m) + RX_GOFS(rx), cx->sb_targ, NULL,
+ !CALLREGEXEC(rx, s, cx->sb_strend, orig,
+ (s == m), cx->sb_targ, NULL,
(REXEC_IGNOREPOS|REXEC_NOT_FIRST)))
{
SV *targ = cx->sb_targ;
bool rxtainted;
const I32 gimme = GIMME;
STRLEN len;
- I32 minmatch = 0;
const I32 oldsave = PL_savestack_ix;
- I32 update_minmatch = 1;
I32 had_zerolen = 0;
if (PL_op->op_flags & OPf_STACKED)
}
else if (!(RX_EXTFLAGS(rx) & RXf_GPOS_FLOAT))
curpos = mg->mg_len;
- minmatch = (mg->mg_flags & MGf_MINMATCH) ? RX_GOFS(rx) + 1 : 0;
- update_minmatch = 0;
+ else
+ curpos = mg->mg_len;
+ /* last time pos() was set, it was zero-length match */
+ if (mg->mg_flags & MGf_MINMATCH)
+ had_zerolen = 1;
}
}
#ifdef PERL_SAWAMPERSAND
play_it_again:
if (global) {
- s = truebase + curpos - RX_GOFS(rx);
- if ((s + RX_MINLEN(rx)) > strend || s < truebase) {
- DEBUG_r(PerlIO_printf(Perl_debug_log, "Regex match can't succeed, so not even tried\n"));
- goto nope;
- }
- if (update_minmatch++)
- minmatch = had_zerolen;
+ s = truebase + curpos;
}
if (!CALLREGEXEC(rx, (char*)s, (char *)strend, (char*)truebase,
- minmatch, TARG, NULL, r_flags))
+ had_zerolen, TARG, NULL, r_flags))
goto nope;
PL_curpm = pm;
if (!mg) {
mg = sv_magicext_mglob(TARG);
}
+ assert(RX_OFFS(rx)[0].start != -1); /* XXX get rid of next line? */
if (RX_OFFS(rx)[0].start != -1) {
mg->mg_len = RX_OFFS(rx)[0].end;
- if (RX_OFFS(rx)[0].start + RX_GOFS(rx) == (UV)RX_OFFS(rx)[0].end)
+ if (RX_ZERO_LEN(rx))
mg->mg_flags |= MGf_MINMATCH;
else
mg->mg_flags &= ~MGf_MINMATCH;
}
}
if (global) {
- assert(RX_OFFS(rx)[0].start != -1);
curpos = (UV)RX_OFFS(rx)[0].end;
- had_zerolen = (RX_OFFS(rx)[0].start != -1
- && (RX_OFFS(rx)[0].start + RX_GOFS(rx)
- == (UV)curpos));
+ had_zerolen = RX_ZERO_LEN(rx);
PUTBACK; /* EVAL blocks may use stack */
r_flags |= REXEC_IGNOREPOS | REXEC_NOT_FIRST;
goto play_it_again;
struct regexp *const prog = ReANY(rx);
char *s;
regnode *c;
- char *startpos = stringarg;
+ char *startpos;
I32 minlen; /* must match at least this many chars */
I32 dontbother = 0; /* how many characters not to try at end */
I32 end_shift = 0; /* Same for the end. */ /* CC */
PERL_UNUSED_ARG(data);
/* Be paranoid... */
- if (prog == NULL || startpos == NULL) {
+ if (prog == NULL || stringarg == NULL) {
Perl_croak(aTHX_ "NULL regexp parameter");
return 0;
}
DEBUG_EXECUTE_r(
- debug_start_match(rx, utf8_target, startpos, strend,
+ debug_start_match(rx, utf8_target, stringarg, strend,
"Matching");
);
+ if (prog->extflags & RXf_GPOS_SEEN) {
+ /* in the presence of \G, we may need to start looking earlier in
+ * the string than the suggested start point of stringarg:
+ * if gofs->prog is set, then that's a known, fixed minimum
+ * offset, such as
+ * /..\G/: gofs = 2
+ * /ab|c\G/: gofs = 1
+ * or if the minimum offset isn't known, then we have to go back
+ * to the start of the string, e.g. /w+\G/
+ */
+ if (prog->gofs) {
+ if (stringarg - prog->gofs < strbeg) {
+ minend += (stringarg - strbeg);
+ stringarg = strbeg;
+ }
+ else {
+ stringarg -= prog->gofs;
+ minend += prog->gofs;
+ }
+ }
+ else if (prog->extflags & RXf_GPOS_FLOAT) {
+ minend += (stringarg - strbeg);
+ stringarg = strbeg;
+ }
+ }
+
+ minlen = prog->minlen;
+ if ((stringarg + minlen) > strend || stringarg < strbeg) {
+ DEBUG_r(PerlIO_printf(Perl_debug_log,
+ "Regex match can't succeed, so not even tried\n"));
+ return 0;
+ }
+
+ startpos = stringarg;
+
if ((RX_EXTFLAGS(rx) & RXf_USE_INTUIT)
&& !(flags & REXEC_CHECKED))
{
oldsave = PL_savestack_ix;
multiline = prog->extflags & RXf_PMf_MULTILINE;
- minlen = prog->minlen;
if (strend - startpos < (minlen+(prog->check_offset_min<0?prog->check_offset_min:0))) {
DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log,
#define RX_LASTPAREN(prog) (ReANY(prog)->lastparen)
#define RX_LASTCLOSEPAREN(prog) (ReANY(prog)->lastcloseparen)
#define RX_SAVED_COPY(prog) (ReANY(prog)->saved_copy)
+/* last match was zero-length */
+#define RX_ZERO_LEN(prog) \
+ (RX_OFFS(prog)[0].start + RX_GOFS(prog) == (UV)RX_OFFS(prog)[0].end)
#endif /* PLUGGABLE_RE_EXTENSION */