SV * const filter_state = (SV *)IoTOP_GV(datasv);
SV * const filter_sub = (SV *)IoBOTTOM_GV(datasv);
int len = 0;
-
+ /* Filter API says that the filter appends to the contents of the buffer.
+ Usually the buffer is "", so the details don't matter. But if it's not,
+ then clearly what it contains is already filtered by this filter, so we
+ don't want to pass it in a second time.
+ I'm going to use a mortal in case the upstream filter croaks. */
+ SV *const upstream
+ = ((SvOK(buf_sv) && sv_len(buf_sv)) || SvGMAGICAL(buf_sv))
+ ? sv_newmortal() : buf_sv;
+
+ SvUPGRADE(upstream, SVt_PV);
/* I was having segfault trouble under Linux 2.2.5 after a
parse error occured. (Had to hack around it with a test
for PL_error_count == 0.) Solaris doesn't segfault --
not sure where the trouble is yet. XXX */
if (filter_has_file) {
- len = FILTER_READ(idx+1, buf_sv, maxlen);
+ len = FILTER_READ(idx+1, upstream, maxlen);
}
if (filter_sub && len >= 0) {
SAVETMPS;
EXTEND(SP, 2);
- DEFSV = buf_sv;
+ DEFSV = upstream;
PUSHMARK(SP);
PUSHs(sv_2mortal(newSViv(maxlen)));
if (filter_state) {
filter_del(S_run_user_filter);
}
+ if (upstream != buf_sv) {
+ sv_catsv(buf_sv, upstream);
+ }
return len;
}
require "test.pl";
}
use strict;
+use Filter::Util::Call;
-plan(tests => 12);
+plan(tests => 19);
unshift @INC, sub {
no warnings 'uninitialized';
my $fh;
open $fh, "<", \'pass("Can return file handles from \@INC");';
-do $fh;
+do $fh or die;
my @origlines = ("# This is a blank line\n",
"pass('Can return generators from \@INC');\n",
return defined $_ ? 1 : 0;
};
-do \&generator;
+do \&generator or die;
@lines = @origlines;
# Check that the array dereferencing works ready for the more complex tests:
-do [\&generator];
+do [\&generator] or die;
do [sub {
my $param = $_[1];
return defined $_ ? 1 : 0;
}, ["pass('Can return generators which take state');\n",
"pass('And return multiple lines');\n",
- ]];
+ ]] or die;
open $fh, "<", \'fail("File handles and filters work from \@INC");';
-do [$fh, sub {s/fail/pass/}];
+do [$fh, sub {s/fail/pass/}] or die;
open $fh, "<", \'fail("File handles and filters with state work from \@INC");';
-do [$fh, sub {s/$_[1]/pass/}, 'fail'];
+do [$fh, sub {s/$_[1]/pass/}, 'fail'] or die;
+
+print "# 2 tests with pipes from subprocesses.\n";
+
+open $fh, 'echo pass|' or die $!;
+
+do $fh or die;
+
+open $fh, 'echo fail|' or die $!;
+
+do [$fh, sub {s/$_[1]/pass/}, 'fail'] or die;
+
+sub rot13_filter {
+ filter_add(sub {
+ my $status = filter_read();
+ tr/A-Za-z/N-ZA-Mn-za-m/;
+ $status;
+ })
+}
+
+open $fh, "<", \<<'EOC';
+BEGIN {rot13_filter};
+cnff("This will rot13'ed prepend");
+EOC
+
+do $fh or die;
+
+open $fh, "<", \<<'EOC';
+ORTVA {ebg13_svygre};
+pass("This will rot13'ed twice");
+EOC
+
+do [$fh, sub {tr/A-Za-z/N-ZA-Mn-za-m/;}] or die;
+
+my $count = 32;
+sub prepend_rot13_filter {
+ filter_add(sub {
+ my $previous = defined $_ ? $_ : '';
+ # Filters should append to any existing data in $_
+ # But (logically) shouldn't filter it twice.
+ my $test = "fzrt!";
+ $_ = $test;
+ my $status = filter_read();
+ # Sadly, doing this inside the source filter causes an
+ # infinte loop
+ my $got = substr $_, 0, length $test, '';
+ is $got, $test, "Upstream didn't alter existing data";
+ tr/A-Za-z/N-ZA-Mn-za-m/;
+ $_ = $previous . $_;
+ die "Looping infinitely" unless $count--;
+ $status;
+ })
+}
+
+open $fh, "<", \<<'EOC';
+ORTVA {cercraq_ebg13_svygre};
+pass("This will rot13'ed twice");
+EOC
+
+do [$fh, sub {tr/A-Za-z/N-ZA-Mn-za-m/;}] or die;