From: Zefram Date: Wed, 1 Feb 2012 21:40:24 +0000 (+0000) Subject: be adaptive about deleting the realloc filter X-Git-Tag: 0.006009~1 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=4e9e26b62d00dcf657478bae02c37745f15be9f6;p=p5sagit%2FDevel-Declare.git be adaptive about deleting the realloc filter Filters can only be deleted in the correct order (reverse of the order in which they were added). Insisting on deleting the filter would break if another filter were added after ours and is still around. Not deleting the filter at all would break if another filter were added earlier and attempts to delete itself later. We can play nicely to the maximum possible extent by deleting our filter iff it is currently deletable (i.e., it is on the top of the filter stack). Can still run into trouble in more complex situations, but can't avoid that. --- diff --git a/Changes b/Changes index cab43f9..2af6d1f 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,7 @@ Changes for Devel-Declare + - Be adaptive about whether to delete the line reallocation filter, + so as to play as nicely as possible with other kinds of source filter. - Document that injecting newlines doesn't work. - Fix a C declaration after statement, which broke compatibility with older compilers (Jan Dubois). diff --git a/Declare.xs b/Declare.xs index 4952520..44d0a72 100644 --- a/Declare.xs +++ b/Declare.xs @@ -399,9 +399,23 @@ STATIC OP *dd_ck_entereval(pTHX_ OP *o, void *user_data) { static I32 dd_filter_realloc(pTHX_ int idx, SV *sv, int maxlen) { + SV *filter_datasv; const I32 count = FILTER_READ(idx+1, sv, maxlen); SvGROW(sv, DD_PREFERRED_LINESTR_SIZE); - /* filter_del(dd_filter_realloc); */ + /* Filters can only be deleted in the correct order (reverse of the + order in which they were added). Insisting on deleting the filter + here would break if another filter were added after ours and is + still around. Not deleting the filter at all would break if another + filter were added earlier and attempts to delete itself later. + We can play nicely to the maximum possible extent by deleting our + filter iff it is currently deletable (i.e., it is on the top of + the filter stack). Can still run into trouble in more complex + situations, but can't avoid that. */ + if (PL_rsfp_filters && AvFILLp(PL_rsfp_filters) >= 0 && + (filter_datasv = FILTER_DATA(AvFILLp(PL_rsfp_filters))) && + IoANY(filter_datasv) == FPTR2DPTR(void *, dd_filter_realloc)) { + filter_del(dd_filter_realloc); + } return count; } diff --git a/t/filter0.t b/t/filter0.t new file mode 100644 index 0000000..b84b402 --- /dev/null +++ b/t/filter0.t @@ -0,0 +1,25 @@ +use warnings; +use strict; + +BEGIN { + eval { require Filter::Util::Call }; + if($@ ne "") { + require Test::More; + Test::More::plan(skip_all => "Filter::Util::Call unavailable"); + } +} + +use Devel::Declare (); +use Filter::Util::Call qw(filter_add filter_del); +use Test::More tests => 2; + +sub my_quote($) { $_[0] } + +my $i = 0; + +BEGIN { Devel::Declare->setup_for(__PACKAGE__, { my_quote => { const => sub { } } }); } +BEGIN { filter_add(sub { filter_del(); $_ .= "ok \$i++ == 0;"; return 1; }); } + +ok $i++ == 1; + +1; diff --git a/t/filter1.t b/t/filter1.t new file mode 100644 index 0000000..0240290 --- /dev/null +++ b/t/filter1.t @@ -0,0 +1,25 @@ +use warnings; +use strict; + +BEGIN { + eval { require Filter::Util::Call }; + if($@ ne "") { + require Test::More; + Test::More::plan(skip_all => "Filter::Util::Call unavailable"); + } +} + +use Devel::Declare (); +use Filter::Util::Call qw(filter_add filter_del); +use Test::More tests => 2; + +sub my_quote($) { $_[0] } + +my $i = 0; + +BEGIN { filter_add(sub { filter_del(); $_ .= "ok \$i++ == 0;"; return 1; }); } +BEGIN { Devel::Declare->setup_for(__PACKAGE__, { my_quote => { const => sub { } } }); } + +ok $i++ == 1; + +1;