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);
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)))
{
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;
}
}
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))
{
- 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++;
}
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;
/* 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':
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;
/* 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. */
}
-plan tests => 242; # Update this when adding/deleting tests.
+plan tests => 245; # Update this when adding/deleting tests.
run_tests() unless caller;
no re "eval";
undef $@;
- my $match = eval { /$a$c$a/ };
+ my $d = '(?{1})';
+ my $match = eval { /$a$c$a$d/ };
ok($@ && $@ =~ /Eval-group not allowed/ && !$match, $message);
is($b, '14', $message);
ok("bcd" =~ $r, "qr with run-time elements and code block");
}
+ # check that cascaded embedded regexes all see their own lexical
+ # environment
+
+ {
+ my ($r1, $r2, $r3, $r4);
+ my ($x1, $x2, $x3, $x4) = (5,6,7,8);
+ { my $x1 = 1; $r1 = qr/A(??{$x1})/; }
+ { my $x2 = 2; $r2 = qr/$r1(??{$x2})/; }
+ { my $x3 = 3; $r3 = qr/$r2(??{$x3})/; }
+ { my $x4 = 4; $r4 = qr/$r3(??{$x4})/; }
+ ok("A1234" =~ /^$r4$/, "cascaded qr");
+ }
+
+ # and again, but in a loop, with no external references
+ # being maintained to the qr's
+
+ {
+ my $r = 'A';
+ for my $x (1..4) {
+ $r = qr/$r(??{$x})/;
+ }
+ my $x = 5;
+ ok("A1234" =~ /^$r$/, "cascaded qr loop");
+ }
+
+
+ # and again, but compiling the qrs in an eval so there
+ # aren't even refs to the qrs from any ops
+
+ {
+ my $r = 'A';
+ for my $x (1..4) {
+ $r = eval q[ qr/$r(??{$x})/; ];
+ }
+ my $x = 5;
+ ok("A1234" =~ /^$r$/, "cascaded qr loop");
+ }
+
# forward declared subs should Do The Right Thing with any anon CVs
# within them (i.e. pad_fixup_inner_anons() should work)
a(?{f()+ - c - Missing right curly or square bracket
a(?{{1}+ - c - Missing right curly or square bracket
a(?{}})b - c -
-# XXX tmp disable this test - doesn't work for embedded qr// yet
-#a(?{"{"})b ab y - -
+a(?{"{"})b ab y - -
a(?{"\{"})b cabd y $& ab
a(?{"{"}})b - c - Sequence (?{...}) not terminated with ')'
-a(?{$::bl="\{"}).b caxbd y $::bl {
+a(?{$::bl="\{"}).b caxbd t $::bl {
x(~~)*(?:(?:F)?)? x~~ y - -
^a(?#xxx){3}c aaac y $& aaac
'^a (?#xxx) (?#yyy) {3}c'x aaac y $& aaac
([\w:]+::)?(\w+)$ abcd y $1-$2 -abcd
([\w:]+::)?(\w+)$ xy:z:::abcd y $1-$2 xy:z:::-abcd
^[^bcd]*(c+) aexycd y $1 c
-(?{$a=2})a*aa(?{local$a=$a+1})k*c(?{$b=$a}) yaaxxaaaacd y $b 3
-(?{$a=2})(a(?{local$a=$a+1}))*aak*c(?{$b=$a}) yaaxxaaaacd y $b 4
+(?{$a=2})a*aa(?{local$a=$a+1})k*c(?{$b=$a}) yaaxxaaaacd t $b 3
+(?{$a=2})(a(?{local$a=$a+1}))*aak*c(?{$b=$a}) yaaxxaaaacd t $b 4
(>a+)ab aaab n - -
(?>a+)b aaab y - -
([[:]+) a:[b]: y $1 :[
'abb$'m b\nca n - -
(^|x)(c) ca y $2 c
a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz x n - -
-a(?{$a=2;$b=3;($b)=$a})b yabz y $b 2
+a(?{$a=2;$b=3;($b)=$a})b yabz t $b 2
round\(((?>[^()]+))\) _I(round(xs * sz),1) y $1 xs * sz
'((?x:.) )' x y $1- x -
'((?-x:.) )'x x y $1- x-