summaryrefslogtreecommitdiff
path: root/regcomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'regcomp.c')
-rw-r--r--regcomp.c77
1 files changed, 66 insertions, 11 deletions
diff --git a/regcomp.c b/regcomp.c
index ef19a0cac1..31e8431163 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -4703,13 +4703,15 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
for (svp = patternp; svp < patternp + pat_count; svp++) {
SV *sv, *msv = *svp;
+ SV *rx;
bool code = 0;
if (o) {
if (o->op_type == OP_NULL && (o->op_flags & OPf_SPECIAL)) {
+ assert(n < pRExC_state->num_code_blocks);
+ pRExC_state->code_blocks[n].start = SvCUR(pat);
+ pRExC_state->code_blocks[n].block = o;
+ pRExC_state->code_blocks[n].src_regex = NULL;
n++;
- assert(n <= pRExC_state->num_code_blocks);
- pRExC_state->code_blocks[n-1].start = SvCUR(pat);
- pRExC_state->code_blocks[n-1].block = o;
code = 1;
o = o->op_sibling; /* skip CONST */
assert(o);
@@ -4717,6 +4719,40 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
o = o->op_sibling;;
}
+ /* extract any code blocks within any embedded qr//'s */
+ rx = msv;
+ if (SvROK(rx))
+ rx = SvRV(rx);
+ if (SvTYPE(rx) == SVt_REGEXP
+ && RX_ENGINE((REGEXP*)rx) == RE_ENGINE_PTR)
+ {
+
+ RXi_GET_DECL(((struct regexp*)SvANY(rx)), ri);
+ if (ri->num_code_blocks) {
+ int i;
+ Renew(pRExC_state->code_blocks,
+ pRExC_state->num_code_blocks + ri->num_code_blocks,
+ struct reg_code_block);
+ pRExC_state->num_code_blocks += ri->num_code_blocks;
+ for (i=0; i < ri->num_code_blocks; i++) {
+ struct reg_code_block *src, *dst;
+ STRLEN offset = SvCUR(pat)
+ + ((struct regexp *)SvANY(rx))->pre_prefix;
+ assert(n < pRExC_state->num_code_blocks);
+ src = &ri->code_blocks[i];
+ dst = &pRExC_state->code_blocks[n];
+ dst->start = src->start + offset;
+ dst->end = src->end + offset;
+ dst->block = src->block;
+ dst->src_regex = (REGEXP*) SvREFCNT_inc( (SV*)
+ src->src_regex
+ ? src->src_regex
+ : (REGEXP*)rx);
+ n++;
+ }
+ }
+ }
+
if ((SvAMAGIC(pat) || SvAMAGIC(msv)) &&
(sv = amagic_call(pat, msv, concat_amg, AMGf_assign)))
{
@@ -4783,6 +4819,7 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
assert(i+1 < pRExC_state->num_code_blocks);
pRExC_state->code_blocks[++i].start = SvCUR(pat);
pRExC_state->code_blocks[i].block = o;
+ pRExC_state->code_blocks[i].src_regex = NULL;
is_code = 1;
}
}
@@ -4795,7 +4832,7 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
exp = SvPV_nomg(pat, plen);
- if (eng && eng != &PL_core_reg_engine) {
+ if (eng && eng != RE_ENGINE_PTR) {
if ((SvUTF8(pat) && IN_BYTES)
|| SvGMAGICAL(pat) || SvAMAGIC(pat))
{
@@ -7515,16 +7552,24 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp,U32 depth)
- RExC_start)
) {
/* this is a pre-compiled literal (?{}) */
- RExC_parse = RExC_start +
- pRExC_state->code_blocks[pRExC_state->code_index].end;
+ struct reg_code_block *cb =
+ &pRExC_state->code_blocks[pRExC_state->code_index];
+ RExC_parse = RExC_start + cb->end;
if (SIZE_ONLY)
RExC_seen_evals++;
else {
- OP *o =
- pRExC_state->code_blocks[pRExC_state->code_index].block;
- n = add_data(pRExC_state, 1,
+ OP *o = cb->block;
+ if (cb->src_regex) {
+ n = add_data(pRExC_state, 2, "rl");
+ RExC_rxi->data->data[n] =
+ (void*)SvREFCNT_inc((SV*)cb->src_regex);
+ RExC_rxi->data->data[n+1] = (void*)o->op_next;
+ }
+ else {
+ n = add_data(pRExC_state, 1,
(RExC_flags & PMf_HAS_CV) ? "L" : "l");
- RExC_rxi->data->data[n] = (void*)o->op_next;
+ RExC_rxi->data->data[n] = (void*)o->op_next;
+ }
}
pRExC_state->code_index++;
}
@@ -12208,8 +12253,12 @@ Perl_regfree_internal(pTHX_ REGEXP * const rx)
if (ri->u.offsets)
Safefree(ri->u.offsets); /* 20010421 MJD */
#endif
- if (ri->code_blocks)
+ if (ri->code_blocks) {
+ int n;
+ for (n = 0; n < ri->num_code_blocks; n++)
+ SvREFCNT_dec(ri->code_blocks[n].src_regex);
Safefree(ri->code_blocks);
+ }
if (ri->data) {
int n = ri->data->count;
@@ -12221,6 +12270,7 @@ Perl_regfree_internal(pTHX_ REGEXP * const rx)
/* If you add a ->what type here, update the comment in regcomp.h */
switch (ri->data->what[n]) {
case 'a':
+ case 'r':
case 's':
case 'S':
case 'u':
@@ -12443,10 +12493,14 @@ Perl_regdupe_internal(pTHX_ REGEXP * const rx, CLONE_PARAMS *param)
reti->num_code_blocks = ri->num_code_blocks;
if (ri->code_blocks) {
+ int n;
Newxc(reti->code_blocks, ri->num_code_blocks, struct reg_code_block,
struct reg_code_block);
Copy(ri->code_blocks, reti->code_blocks, ri->num_code_blocks,
struct reg_code_block);
+ for (n = 0; n < ri->num_code_blocks; n++)
+ reti->code_blocks[n].src_regex = (REGEXP*)
+ sv_dup_inc((SV*)(ri->code_blocks[n].src_regex), param);
}
else
reti->code_blocks = NULL;
@@ -12469,6 +12523,7 @@ Perl_regdupe_internal(pTHX_ REGEXP * const rx, CLONE_PARAMS *param)
/* legal options are one of: sSfpontTua
see also regcomp.h and pregfree() */
case 'a': /* actually an AV, but the dup function is identical. */
+ case 'r':
case 's':
case 'S':
case 'p': /* actually an AV, but the dup function is identical. */