within pattern */
int num_code_blocks; /* size of code_blocks[] */
int code_index; /* next code_blocks[] slot */
-#if ADD_TO_REGEXEC
+ SSize_t maxlen; /* mininum possible number of chars in string to match */
+#ifdef ADD_TO_REGEXEC
char *starttry; /* -Dr: where regtry was called. */
#define RExC_starttry (pRExC_state->starttry)
#endif
#define RExC_sawback (pRExC_state->sawback)
#define RExC_seen (pRExC_state->seen)
#define RExC_size (pRExC_state->size)
+#define RExC_maxlen (pRExC_state->maxlen)
#define RExC_npar (pRExC_state->npar)
#define RExC_nestroot (pRExC_state->nestroot)
#define RExC_extralen (pRExC_state->extralen)
if (RExC_seen & REG_GOSTART_SEEN) \
PerlIO_printf(Perl_debug_log,"REG_GOSTART_SEEN "); \
\
+ if (RExC_seen & REG_UNBOUNDED_QUANTIFIER_SEEN) \
+ PerlIO_printf(Perl_debug_log,"REG_UNBOUNDED_QUANTIFIER_SEEN "); \
+ \
PerlIO_printf(Perl_debug_log,"\n"); \
});
/* If this can match all upper Latin1 code points, have to add them
* as well */
- if (ANYOF_FLAGS(node) & ANYOF_NON_UTF8_NON_ASCII_ALL) {
+ if (OP(node) == ANYOF_NON_UTF8_NON_ASCII_ALL) {
_invlist_union(invlist, PL_UpperLatin1, &invlist);
}
} scan_frame;
-#define SCAN_COMMIT(s, data, m) scan_commit(s, data, m, is_inf)
-
STATIC SSize_t
S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp,
SSize_t *minlenp, SSize_t *deltap,
regnode_ssc accum;
regnode * const startbranch=scan;
- if (flags & SCF_DO_SUBSTR)
- SCAN_COMMIT(pRExC_state, data, minlenp); /* Cannot merge
- strings after
- this. */
- if (flags & SCF_DO_STCLASS)
+ if (flags & SCF_DO_SUBSTR) {
+ /* Cannot merge strings after this. */
+ scan_commit(pRExC_state, data, minlenp, is_inf);
+ }
+
+ if (flags & SCF_DO_STCLASS)
ssc_init_zero(pRExC_state, &accum);
while (OP(scan) == code) {
/* some form of infinite recursion, assume infinite length
* */
if (flags & SCF_DO_SUBSTR) {
- SCAN_COMMIT(pRExC_state,data,minlenp);
+ scan_commit(pRExC_state, data, minlenp, is_inf);
data->longest = &(data->longest_float);
}
is_inf = is_inf_internal = 1;
/* Search for fixed substrings supports EXACT only. */
if (flags & SCF_DO_SUBSTR) {
assert(data);
- SCAN_COMMIT(pRExC_state, data, minlenp);
+ scan_commit(pRExC_state, data, minlenp, is_inf);
}
if (UTF) {
const U8 * const s = (U8 *)STRING(scan);
scan = NEXTOPER(scan);
goto do_curly;
}
- is_inf = is_inf_internal = 1;
- scan = regnext(scan);
if (flags & SCF_DO_SUBSTR) {
- SCAN_COMMIT(pRExC_state, data, minlenp);
+ scan_commit(pRExC_state, data, minlenp, is_inf);
/* Cannot extend fixed substrings */
data->longest = &(data->longest_float);
}
+ is_inf = is_inf_internal = 1;
+ scan = regnext(scan);
goto optimize_curly_tail;
case CURLY:
if (stopparen>0 && (OP(scan)==CURLYN || OP(scan)==CURLYM)
next_is_eval = (OP(scan) == EVAL);
do_curly:
if (flags & SCF_DO_SUBSTR) {
- if (mincount == 0) SCAN_COMMIT(pRExC_state,data,minlenp);
+ if (mincount == 0)
+ scan_commit(pRExC_state, data, minlenp, is_inf);
/* Cannot extend fixed substrings */
pos_before = data->pos_min;
}
is_inf_internal |= deltanext == SSize_t_MAX
|| (maxcount == REG_INFTY && minnext + deltanext > 0);
is_inf |= is_inf_internal;
- if (is_inf)
+ if (is_inf) {
delta = SSize_t_MAX;
- else
+ } else {
delta += (minnext + deltanext) * maxcount
- minnext * mincount;
-
+ }
/* Try powerful optimization CURLYX => CURLYN. */
if ( OP(oscan) == CURLYX && data
&& data->flags & SF_IN_PAR
pars++;
if (flags & SCF_DO_SUBSTR) {
SV *last_str = NULL;
+ STRLEN last_chrs = 0;
int counted = mincount != 0;
if (data->last_end > 0 && mincount != 0) { /* Ends with a
l -= old;
/* Get the added string: */
last_str = newSVpvn_utf8(s + old, l, UTF);
+ last_chrs = UTF ? utf8_length((U8*)(s + old),
+ (U8*)(s + old + l)) : l;
if (deltanext == 0 && pos_before == b) {
/* What was added is a constant string */
if (mincount > 1) {
+
SvGROW(last_str, (mincount * l) + 1);
repeatcpy(SvPVX(last_str) + l,
SvPVX_const(last_str), l,
SvUTF8(sv) && SvMAGICAL(sv) ?
mg_find(sv, PERL_MAGIC_utf8) : NULL;
if (mg && mg->mg_len >= 0)
- mg->mg_len += CHR_SVLEN(last_str) - l;
+ mg->mg_len += last_chrs * (mincount-1);
}
+ last_chrs *= mincount;
data->last_end += l * (mincount - 1);
}
} else {
if (mincount != maxcount) {
/* Cannot extend fixed substrings found inside
the group. */
- SCAN_COMMIT(pRExC_state,data,minlenp);
+ scan_commit(pRExC_state, data, minlenp, is_inf);
if (mincount && last_str) {
SV * const sv = data->last_found;
MAGIC * const mg = SvUTF8(sv) && SvMAGICAL(sv) ?
mg->mg_len = -1;
sv_setsv(sv, last_str);
data->last_end = data->pos_min;
- data->last_start_min =
- data->pos_min - CHR_SVLEN(last_str);
+ data->last_start_min = data->pos_min - last_chrs;
data->last_start_max = is_inf
? SSize_t_MAX
- : data->pos_min + data->pos_delta
- - CHR_SVLEN(last_str);
+ : data->pos_min + data->pos_delta - last_chrs;
}
data->longest = &(data->longest_float);
}
case REF:
case CLUMP:
if (flags & SCF_DO_SUBSTR) {
- SCAN_COMMIT(pRExC_state,data,minlenp); /* Cannot expect
- anything... */
+ /* Cannot expect anything... */
+ scan_commit(pRExC_state, data, minlenp, is_inf);
data->longest = &(data->longest_float);
}
is_inf = is_inf_internal = 1;
min++;
delta++; /* Because of the 2 char string cr-lf */
if (flags & SCF_DO_SUBSTR) {
- SCAN_COMMIT(pRExC_state,data,minlenp); /* Cannot expect
- anything... */
+ /* Cannot expect anything... */
+ scan_commit(pRExC_state, data, minlenp, is_inf);
data->pos_min += 1;
data->pos_delta += 1;
data->longest = &(data->longest_float);
else if (REGNODE_SIMPLE(OP(scan))) {
if (flags & SCF_DO_SUBSTR) {
- SCAN_COMMIT(pRExC_state,data,minlenp);
+ scan_commit(pRExC_state, data, minlenp, is_inf);
data->pos_min++;
}
min++;
}
break;
+ case ANYOF_NON_UTF8_NON_ASCII_ALL:
case ANYOF:
if (flags & SCF_DO_STCLASS_AND)
ssc_and(pRExC_state, data->start_class,
/* NPOSIXD matches all upper Latin1 code points unless the
* target string being matched is UTF-8, which is
- * unknowable until match time */
- if (PL_regkind[OP(scan)] == NPOSIXD) {
- _invlist_union_complement_2nd(my_invlist,
- PL_XPosix_ptrs[_CC_ASCII], &my_invlist);
+ * unknowable until match time. Since we are going to
+ * invert, we want to get rid of all of them so that the
+ * inversion will match all */
+ if (OP(scan) == NPOSIXD) {
+ _invlist_subtract(my_invlist, PL_UpperLatin1,
+ &my_invlist);
}
join_posix:
data->flags |= (OP(scan) == MEOL
? SF_BEFORE_MEOL
: SF_BEFORE_SEOL);
- SCAN_COMMIT(pRExC_state, data, minlenp);
+ scan_commit(pRExC_state, data, minlenp, is_inf);
}
else if ( PL_regkind[OP(scan)] == BRANCHJ
if ((flags & SCF_DO_SUBSTR) && data->last_found) {
f |= SCF_DO_SUBSTR;
if (scan->flags)
- SCAN_COMMIT(pRExC_state, &data_fake,minlenp);
+ scan_commit(pRExC_state, &data_fake, minlenp, is_inf);
data_fake.last_found=newSVsv(data->last_found);
}
}
if ((flags & SCF_DO_SUBSTR) && data_fake.last_found) {
if (RExC_rx->minlen<*minnextp)
RExC_rx->minlen=*minnextp;
- SCAN_COMMIT(pRExC_state, &data_fake, minnextp);
+ scan_commit(pRExC_state, &data_fake, minnextp, is_inf);
SvREFCNT_dec_NN(data_fake.last_found);
if ( data_fake.minlen_fixed != minlenp )
}
else if ( PL_regkind[OP(scan)] == ENDLIKE ) {
if (flags & SCF_DO_SUBSTR) {
- SCAN_COMMIT(pRExC_state,data,minlenp);
+ scan_commit(pRExC_state, data, minlenp, is_inf);
flags &= ~SCF_DO_SUBSTR;
}
if (data && OP(scan)==ACCEPT) {
else if (OP(scan) == LOGICAL && scan->flags == 2) /* Embedded follows */
{
if (flags & SCF_DO_SUBSTR) {
- SCAN_COMMIT(pRExC_state,data,minlenp);
+ scan_commit(pRExC_state, data, minlenp, is_inf);
data->longest = &(data->longest_float);
}
is_inf = is_inf_internal = 1;
SSize_t max1 = 0, min1 = SSize_t_MAX;
regnode_ssc accum;
- if (flags & SCF_DO_SUBSTR) /* XXXX Add !SUSPEND? */
- SCAN_COMMIT(pRExC_state, data,minlenp); /* Cannot merge strings
- after this. */
+ if (flags & SCF_DO_SUBSTR) { /* XXXX Add !SUSPEND? */
+ /* Cannot merge strings after this. */
+ scan_commit(pRExC_state, data, minlenp, is_inf);
+ }
if (flags & SCF_DO_STCLASS)
ssc_init_zero(pRExC_state, &accum);
delta += (trie->maxlen - trie->minlen);
flags &= ~SCF_DO_STCLASS; /* xxx */
if (flags & SCF_DO_SUBSTR) {
- SCAN_COMMIT(pRExC_state,data,minlenp); /* Cannot expect
- anything... */
+ /* Cannot expect anything... */
+ scan_commit(pRExC_state, data, minlenp, is_inf);
data->pos_min += trie->minlen;
data->pos_delta += (trie->maxlen - trie->minlen);
if (trie->maxlen != trie->minlen)
*scanp = scan;
*deltap = is_inf_internal ? SSize_t_MAX : delta;
+
if (flags & SCF_DO_SUBSTR && is_inf)
data->pos_delta = SSize_t_MAX - data->pos_min;
if (is_par > (I32)U8_MAX)
DEBUG_STUDYDATA("post-fin:",data,depth);
- return min < stopmin ? min : stopmin;
+ {
+ SSize_t final_minlen= min < stopmin ? min : stopmin;
+
+ if (!(RExC_seen & REG_UNBOUNDED_QUANTIFIER_SEEN) && (RExC_maxlen < final_minlen + delta)) {
+ RExC_maxlen = final_minlen + delta;
+ }
+ return final_minlen;
+ }
+ /* not-reached */
}
STATIC U32
RExC_sawback = 0;
RExC_seen = 0;
+ RExC_maxlen = 0;
RExC_in_lookbehind = 0;
RExC_seen_zerolen = *exp == '^' ? -1 : 0;
RExC_extralen = 0;
&& data.last_start_min == 0 && data.last_end > 0
&& !RExC_seen_zerolen
&& !(RExC_seen & REG_VERBARG_SEEN)
- && !((RExC_seen & REG_GPOS_SEEN) || (r->intflags & PREGf_ANCH_GPOS)))
+ && !(RExC_seen & REG_GPOS_SEEN)
+ ){
r->extflags |= RXf_CHECK_ALL;
+ }
scan_commit(pRExC_state, &data,&minlen,0);
longest_float_length = CHR_SVLEN(data.longest_float);
/* A temporary algorithm prefers floated substr to fixed one to dig
* more info. */
if (longest_fixed_length > longest_float_length) {
+ r->substrs->check_ix = 0;
r->check_end_shift = r->anchored_end_shift;
r->check_substr = r->anchored_substr;
r->check_utf8 = r->anchored_utf8;
r->check_offset_min = r->check_offset_max = r->anchored_offset;
- if (r->intflags & PREGf_ANCH_SINGLE)
+ if (r->intflags & (PREGf_ANCH_SBOL|PREGf_ANCH_GPOS))
r->intflags |= PREGf_NOSCAN;
}
else {
+ r->substrs->check_ix = 1;
r->check_end_shift = r->float_end_shift;
r->check_substr = r->float_substr;
r->check_utf8 = r->float_utf8;
if (SvTAIL(r->check_substr ? r->check_substr : r->check_utf8))
r->extflags |= RXf_INTUIT_TAIL;
}
+ r->substrs->data[0].max_offset = r->substrs->data[0].min_offset;
+
/* XXX Unneeded? dmq (shouldn't as this is handled elsewhere)
if ( (STRLEN)minlen < longest_float_length )
minlen= longest_float_length;
}
}
+ if (RExC_seen & REG_UNBOUNDED_QUANTIFIER_SEEN) {
+ r->extflags |= RXf_UNBOUNDED_QUANTIFIER_SEEN;
+ r->maxlen = REG_INFTY;
+ }
+ else {
+ r->maxlen = RExC_maxlen;
+ }
+
/* Guard against an embedded (?=) or (?<=) with a longer minlen than
the "real" pattern. */
DEBUG_OPTIMISE_r({
- PerlIO_printf(Perl_debug_log,"minlen: %"IVdf" r->minlen:%"IVdf"\n",
- (IV)minlen, (IV)r->minlen);
+ PerlIO_printf(Perl_debug_log,"minlen: %"IVdf" r->minlen:%"IVdf" maxlen:%ld\n",
+ (IV)minlen, (IV)r->minlen, RExC_maxlen);
});
r->minlenret = minlen;
if (r->minlen < minlen)
assert(s >= rx->subbeg);
assert((STRLEN)rx->sublen >= (STRLEN)((s - rx->subbeg) + i) );
if (i >= 0) {
-#if NO_TAINT_SUPPORT
+#ifdef NO_TAINT_SUPPORT
sv_setpvn(sv, s, i);
#else
const int oldtainted = TAINT_get;
ARG1_SET(ret, (U16)min);
ARG2_SET(ret, (U16)max);
}
+ if (max == REG_INFTY)
+ RExC_seen |= REG_UNBOUNDED_QUANTIFIER_SEEN;
goto nest_check;
}
reginsert(pRExC_state, STAR, ret, depth+1);
ret->flags = 0;
RExC_naughty += 4;
+ RExC_seen |= REG_UNBOUNDED_QUANTIFIER_SEEN;
}
else if (op == '*') {
min = 0;
reginsert(pRExC_state, PLUS, ret, depth+1);
ret->flags = 0;
RExC_naughty += 3;
+ RExC_seen |= REG_UNBOUNDED_QUANTIFIER_SEEN;
}
else if (op == '+') {
min = 1;
FLAGS(ret) = get_regex_charset(RExC_flags);
*flagp |= SIMPLE;
if (! SIZE_ONLY && (U8) *(RExC_parse + 1) == '{') {
- ckWARNdep(RExC_parse, "\"\\b{\" is deprecated; use \"\\b\\{\" or \"\\b[{]\" instead");
+ /* diag_listed_as: Use "%s" instead of "%s" */
+ vFAIL("Use \"\\b\\{\" instead of \"\\b{\"");
}
goto finish_meta_pat;
case 'B':
FLAGS(ret) = get_regex_charset(RExC_flags);
*flagp |= SIMPLE;
if (! SIZE_ONLY && (U8) *(RExC_parse + 1) == '{') {
- ckWARNdep(RExC_parse, "\"\\B{\" is deprecated; use \"\\B\\{\" or \"\\B[{]\" instead");
+ /* diag_listed_as: Use "%s" instead of "%s" */
+ vFAIL("Use \"\\B\\{\" instead of \"\\B{\"");
}
goto finish_meta_pat;
}
case 'c':
p++;
- ender = grok_bslash_c(*p++, UTF, SIZE_ONLY);
+ ender = grok_bslash_c(*p++, SIZE_ONLY);
break;
case '8': case '9': /* must be a backreference */
--p;
goto recode_encoding;
break;
case 'c':
- value = grok_bslash_c(*RExC_parse++, UTF, SIZE_ONLY);
+ value = grok_bslash_c(*RExC_parse++, SIZE_ONLY);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7':
#ifndef HAS_ISASCII
&& classnum != _CC_ASCII
#endif
-#ifndef HAS_ISBLANK
- && classnum != _CC_BLANK
-#endif
) {
/* See if it already matches the complement of this POSIX
? &posixes
: &nposixes;
SV** source_ptr = &PL_XPosix_ptrs[classnum];
-#ifndef HAS_ISBLANK
- /* If the platform doesn't have isblank(), we handle locale
- * with the hardcoded ASII values. */
- if (LOC && classnum == _CC_BLANK) {
- _invlist_subtract(*source_ptr,
- PL_UpperLatin1,
- source_ptr);
- }
-#endif
-
_invlist_union_maybe_complement_2nd(
*posixes_ptr,
*source_ptr,
if (op > POSIXA) { /* /aa is same as /a */
op = POSIXA;
}
-#ifndef HAS_ISBLANK
- if (op == POSIXL
- && (namedclass == ANYOF_BLANK
- || namedclass == ANYOF_NBLANK))
- {
- op = POSIXA;
- }
-#endif
join_posix:
/* The odd numbered ones are the complements of the
if (DEPENDS_SEMANTICS) {
/* Under /d, everything in the upper half of the Latin1 range
* matches these complements */
- ANYOF_FLAGS(ret) |= ANYOF_NON_UTF8_NON_ASCII_ALL;
+ OP(ret) = ANYOF_NON_UTF8_NON_ASCII_ALL;
}
else if (AT_LEAST_ASCII_RESTRICTED) {
/* Under /a and /aa, everything above ASCII matches these
sv_catpvs(sv, "^");
}
- if (flags & ANYOF_NON_UTF8_NON_ASCII_ALL) {
+ if (OP(o) == ANYOF_NON_UTF8_NON_ASCII_ALL) {
sv_catpvs(sv, "{non-utf8-latin1-all}");
}