*
**** Alterations to Henry's code are...
****
- **** Copyright (c) 1991-2002, Larry Wall
+ **** Copyright (c) 1991-2003, Larry Wall
****
**** You may distribute under the terms of either the GNU General Public
**** License or the Artistic License, as specified in the README file.
char *i_strpos = strpos;
SV *dsv = PERL_DEBUG_PAD_ZERO(0);
#endif
+ RX_MATCH_UTF8_set(prog,do_utf8);
if (prog->reganch & ROPT_UTF8) {
DEBUG_r(PerlIO_printf(Perl_debug_log,
);
});
- if (prog->minlen > CHR_DIST((U8*)strend, (U8*)strpos)) {
+ /* CHR_DIST() would be more correct here but it makes things slow. */
+ if (prog->minlen > strend - strpos) {
DEBUG_r(PerlIO_printf(Perl_debug_log,
"String too short... [re_intuit_start]\n"));
goto fail;
start_shift + (s - strbeg), end_shift, pp, 0);
else
goto fail_finish;
+ /* we may be pointing at the wrong string */
+ if (s && RX_MATCH_COPIED(prog))
+ s = prog->subbeg + (s - SvPVX(sv));
if (data)
*data->scream_olds = s;
}
t = s - prog->check_offset_max;
if (s - strpos > prog->check_offset_max /* signed-corrected t > strpos */
- && (!(prog->reganch & ROPT_UTF8)
+ && (!do_utf8
|| ((t = reghopmaybe3_c(s, -(prog->check_offset_max), strpos))
&& t > strpos)))
/* EMPTY */;
t = s - prog->check_offset_max;
if (s - strpos > prog->check_offset_max /* signed-corrected t > strpos */
- && (!(prog->reganch & ROPT_UTF8)
+ && (!do_utf8
|| ((t = reghopmaybe3_c(s, -prog->check_offset_max, strpos))
&& t > strpos))) {
/* Fixed substring is found far enough so that the match
PL_regdata = prog->data;
PL_bostr = startpos;
}
+ cache_re(prog);
s = find_byclass(prog, prog->regstclass, s, endpos, startpos, 1);
if (!s) {
#ifdef DEBUGGING
/* We know what class it must start with. */
switch (OP(c)) {
case ANYOF:
- while (s < strend) {
- STRLEN skip = do_utf8 ? UTF8SKIP(s) : 1;
-
- if (do_utf8 ?
- reginclass(c, (U8*)s, 0, do_utf8) :
- REGINCLASS(c, (U8*)s) ||
- (ANYOF_FOLD_SHARP_S(c, s, strend) &&
- /* The assignment of 2 is intentional:
- * for the sharp s, the skip is 2. */
- (skip = SHARP_S_SKIP)
- )) {
- if (tmp && (norun || regtry(prog, s)))
- goto got_it;
- else
- tmp = doevery;
- }
- else
- tmp = 1;
- s += skip;
+ if (do_utf8) {
+ while (s < strend) {
+ if ((ANYOF_FLAGS(c) & ANYOF_UNICODE) ||
+ !UTF8_IS_INVARIANT((U8)s[0]) ?
+ reginclass(c, (U8*)s, 0, do_utf8) :
+ REGINCLASS(c, (U8*)s)) {
+ if (tmp && (norun || regtry(prog, s)))
+ goto got_it;
+ else
+ tmp = doevery;
+ }
+ else
+ tmp = 1;
+ s += UTF8SKIP(s);
+ }
+ }
+ else {
+ while (s < strend) {
+ STRLEN skip = 1;
+
+ if (REGINCLASS(c, (U8*)s) ||
+ (ANYOF_FOLD_SHARP_S(c, s, strend) &&
+ /* The assignment of 2 is intentional:
+ * for the folded sharp s, the skip is 2. */
+ (skip = SHARP_S_SKIP))) {
+ if (tmp && (norun || regtry(prog, s)))
+ goto got_it;
+ else
+ tmp = doevery;
+ }
+ else
+ tmp = 1;
+ s += skip;
+ }
}
break;
case CANY:
SV *dsv0 = PERL_DEBUG_PAD_ZERO(0);
SV *dsv1 = PERL_DEBUG_PAD_ZERO(1);
#endif
+ RX_MATCH_UTF8_set(prog,do_utf8);
PL_regcc = 0;
: (s = fbm_instr((unsigned char*)HOP3(s, back_min, strend),
(unsigned char*)strend, must,
PL_multiline ? FBMrf_MULTILINE : 0))) ) {
+ /* we may be pointing at the wrong string */
+ if ((flags & REXEC_SCREAM) && RX_MATCH_COPIED(prog))
+ s = prog->subbeg + (s - SvPVX(sv));
DEBUG_r( did_match = 1 );
if (HOPc(s, -back_max) > last1) {
last1 = HOPc(s, -back_min);
goto phooey;
}
else if ((c = prog->regstclass)) {
- if (minlen && PL_regkind[(U8)OP(prog->regstclass)] != EXACT)
+ if (minlen) {
+ I32 op = (U8)OP(prog->regstclass);
/* don't bother with what can't match */
- strend = HOPc(strend, -(minlen - 1));
+ if (PL_regkind[op] != EXACT && op != CANY)
+ strend = HOPc(strend, -(minlen - 1));
+ }
DEBUG_r({
SV *prop = sv_newmortal();
char *s0;
end_shift, &scream_pos, 1); /* last one */
if (!last)
last = scream_olds; /* Only one occurrence. */
+ /* we may be pointing at the wrong string */
+ else if (RX_MATCH_COPIED(prog))
+ s = prog->subbeg + (s - SvPVX(sv));
}
else {
STRLEN len;
/* make sure $`, $&, $', and $digit will work later */
if ( !(flags & REXEC_NOT_FIRST) ) {
- if (RX_MATCH_COPIED(prog)) {
- Safefree(prog->subbeg);
- RX_MATCH_COPIED_off(prog);
- }
+ RX_MATCH_COPY_FREE(prog);
if (flags & REXEC_COPY_STR) {
I32 i = PL_regeol - startpos + (stringarg - strbeg);
-
- s = savepvn(strbeg, i);
- prog->subbeg = s;
+#ifdef PERL_COPY_ON_WRITE
+ if ((SvIsCOW(sv)
+ || (SvFLAGS(sv) & CAN_COW_MASK) == CAN_COW_FLAGS)) {
+ if (DEBUG_C_TEST) {
+ PerlIO_printf(Perl_debug_log,
+ "Copy on write: regexp capture, type %d\n",
+ (int) SvTYPE(sv));
+ }
+ prog->saved_copy = sv_setsv_cow(prog->saved_copy, sv);
+ prog->subbeg = SvPVX(prog->saved_copy);
+ assert (SvPOKp(prog->saved_copy));
+ } else
+#endif
+ {
+ RX_MATCH_COPIED_on(prog);
+ s = savepvn(strbeg, i);
+ prog->subbeg = s;
+ }
prog->sublen = i;
- RX_MATCH_COPIED_on(prog);
}
else {
prog->subbeg = strbeg;
$` inside (?{}) could fail... */
PL_reg_oldsaved = prog->subbeg;
PL_reg_oldsavedlen = prog->sublen;
+#ifdef PERL_COPY_ON_WRITE
+ PL_nrs = prog->saved_copy;
+#endif
RX_MATCH_COPIED_off(prog);
}
else
PL_reglastparen = &prog->lastparen;
PL_reglastcloseparen = &prog->lastcloseparen;
prog->lastparen = 0;
+ prog->lastcloseparen = 0;
PL_regsize = 0;
DEBUG_r(PL_reg_starttry = startpos);
if (PL_reg_start_tmpl <= prog->nparens) {
regprop(prop, scan);
{
char *s0 =
- do_utf8 ?
+ do_utf8 && OP(scan) != CANY ?
pv_uni_display(dsv0, (U8*)(locinput - pref_len),
pref0_len, 60, UNI_DISPLAY_REGEX) :
locinput - pref_len;
int len0 = do_utf8 ? strlen(s0) : pref0_len;
- char *s1 = do_utf8 ?
+ char *s1 = do_utf8 && OP(scan) != CANY ?
pv_uni_display(dsv1, (U8*)(locinput - pref_len + pref0_len),
pref_len - pref0_len, 60, UNI_DISPLAY_REGEX) :
locinput - pref_len + pref0_len;
int len1 = do_utf8 ? strlen(s1) : pref_len - pref0_len;
- char *s2 = do_utf8 ?
+ char *s2 = do_utf8 && OP(scan) != CANY ?
pv_uni_display(dsv2, (U8*)locinput,
PL_regeol - locinput, 60, UNI_DISPLAY_REGEX) :
locinput;
dSP;
OP_4tree *oop = PL_op;
COP *ocurcop = PL_curcop;
- SV **ocurpad = PL_curpad;
+ PAD *old_comppad;
SV *ret;
n = ARG(scan);
PL_op = (OP_4tree*)PL_regdata->data[n];
DEBUG_r( PerlIO_printf(Perl_debug_log, " re_eval 0x%"UVxf"\n", PTR2UV(PL_op)) );
- PL_curpad = AvARRAY((AV*)PL_regdata->data[n + 2]);
+ PAD_SAVE_LOCAL(old_comppad, (PAD*)PL_regdata->data[n + 2]);
PL_regendp[0] = PL_reg_magic->mg_len = locinput - PL_bostr;
{
CALLRUNOPS(aTHX); /* Scalar context. */
SPAGAIN;
if (SP == before)
- ret = Nullsv; /* protect against empty (?{}) blocks. */
+ ret = &PL_sv_undef; /* protect against empty (?{}) blocks. */
else {
ret = POPs;
PUTBACK;
}
PL_op = oop;
- PL_curpad = ocurpad;
+ PAD_RESTORE_LOCAL(old_comppad);
PL_curcop = ocurcop;
if (logical) {
if (logical == 2) { /* Postponed subexpression. */
MAGIC *mg = Null(MAGIC*);
re_cc_state state;
CHECKPOINT cp, lastcp;
-
- if(SvROK(ret) || SvRMAGICAL(ret)) {
- SV *sv = SvROK(ret) ? SvRV(ret) : ret;
-
- if(SvMAGICAL(sv))
- mg = mg_find(sv, PERL_MAGIC_qr);
+ int toggleutf;
+ register SV *sv;
+
+ if(SvROK(ret) && SvSMAGICAL(sv = SvRV(ret)))
+ mg = mg_find(sv, PERL_MAGIC_qr);
+ else if (SvSMAGICAL(ret)) {
+ if (SvGMAGICAL(ret))
+ sv_unmagic(ret, PERL_MAGIC_qr);
+ else
+ mg = mg_find(ret, PERL_MAGIC_qr);
}
+
if (mg) {
re = (regexp *)mg->mg_obj;
(void)ReREFCNT_inc(re);
I32 onpar = PL_regnpar;
Zero(&pm, 1, PMOP);
+ if (DO_UTF8(ret)) pm.op_pmdynflags |= PMdf_DYN_UTF8;
re = CALLREGCOMP(aTHX_ t, t + len, &pm);
if (!(SvFLAGS(ret)
- & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)))
+ & (SVs_TEMP | SVs_PADTMP | SVf_READONLY
+ | SVs_GMG)))
sv_magic(ret,(SV*)ReREFCNT_inc(re),
PERL_MAGIC_qr,0,0);
PL_regprecomp = oprecomp;
*PL_reglastcloseparen = 0;
PL_reg_call_cc = &state;
PL_reginput = locinput;
+ toggleutf = ((PL_reg_flags & RF_utf8) != 0) ^
+ ((re->reganch & ROPT_UTF8) != 0);
+ if (toggleutf) PL_reg_flags ^= RF_utf8;
/* XXXX This is too dramatic a measure... */
PL_reg_maxiter = 0;
PL_regcc = state.cc;
PL_reg_re = state.re;
cache_re(PL_reg_re);
+ if (toggleutf) PL_reg_flags ^= RF_utf8;
/* XXXX This is too dramatic a measure... */
PL_reg_maxiter = 0;
PL_regcc = state.cc;
PL_reg_re = state.re;
cache_re(PL_reg_re);
+ if (toggleutf) PL_reg_flags ^= RF_utf8;
/* XXXX This is too dramatic a measure... */
PL_reg_maxiter = 0;
/* If it could work, try it. */
if (c == (UV)c1 || c == (UV)c2)
{
- TRYPAREN(paren, n, PL_reginput);
+ TRYPAREN(paren, ln, PL_reginput);
REGCP_UNWIND(lastcp);
}
}
/* If it could work, try it. */
else if (c1 == -1000)
{
- TRYPAREN(paren, n, PL_reginput);
+ TRYPAREN(paren, ln, PL_reginput);
REGCP_UNWIND(lastcp);
}
/* Couldn't or didn't -- move forward. */
register bool do_utf8 = PL_reg_match_utf8;
scan = PL_reginput;
- if (max != REG_INFTY && max < loceol - scan)
+ if (max == REG_INFTY)
+ max = I32_MAX;
+ else if (max < loceol - scan)
loceol = scan + max;
switch (OP(p)) {
case REG_ANY:
if (PL_regdata->what[n] == 's') {
SV *rv = (SV*)PL_regdata->data[n];
AV *av = (AV*)SvRV((SV*)rv);
+ SV **ary = AvARRAY(av);
SV **a, **b;
/* See the end of regcomp.c:S_reglass() for
* documentation of these array elements. */
- si = *av_fetch(av, 0, FALSE);
- a = av_fetch(av, 1, FALSE);
- b = av_fetch(av, 2, FALSE);
-
+ si = *ary;
+ a = SvTYPE(ary[1]) == SVt_RV ? &ary[1] : 0;
+ b = SvTYPE(ary[2]) == SVt_PVAV ? &ary[2] : 0;
+
if (a)
sw = *a;
else if (si && doinit) {
{
char flags = ANYOF_FLAGS(n);
bool match = FALSE;
- UV c;
+ UV c = *p;
STRLEN len = 0;
STRLEN plen;
- c = do_utf8 ? utf8n_to_uvchr(p, UTF8_MAXLEN, &len,
- ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY) : *p;
+ if (do_utf8 && !UTF8_IS_INVARIANT(c))
+ c = utf8n_to_uvchr(p, UTF8_MAXLEN, &len,
+ ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANY);
plen = lenp ? *lenp : UNISKIP(NATIVE_TO_UNI(c));
if (do_utf8 || (flags & ANYOF_UNICODE)) {
if (PL_reg_oldsaved) {
PL_reg_re->subbeg = PL_reg_oldsaved;
PL_reg_re->sublen = PL_reg_oldsavedlen;
+#ifdef PERL_COPY_ON_WRITE
+ PL_reg_re->saved_copy = PL_nrs;
+#endif
RX_MATCH_COPIED_on(PL_reg_re);
}
PL_reg_magic->mg_len = PL_reg_oldpos;