Subject: | terminator given by hash reference has no effect |
If the second argument of FILTER is a reference to a hash and the hash
has a value associated with key 'terminator', the terminator is not
actually used as terminator. This is because "%terminator" is given to
filter closure and values in the hash reference is not copied to the
"%termianator".
The easiest way to fix it is to copy the values in the hash reference
to copy "%terminator". However, attached patch employs another
approach. The given hash reference is passed through to filter closure.
This gives possibility to modify "becomes" value in filter function or
terminator regexp (in this case, via (?{code}) construct).
In addition, "becomes" in terminator hash reference is not mentioned in
the current documentation. I try to descibe it in the attached patch,
accoding to my understandings.
Subject: | Filter-Simple-0.82.patch |
--- /usr/lib/perl5/5.8/Filter/Simple.pm 2005-06-27 11:31:44.000000000 +0900
+++ Filter/Simple.pm 2007-08-26 02:45:08.021129600 +0900
@@ -160,24 +160,27 @@
my $ows = qr/(?:[ \t]+|#[^\n]*)*/;
sub gen_filter_import {
- my ($class, $filter, $terminator) = @_;
- my %terminator;
+ my ($class, $filter, $terminator_) = @_;
+ my $terminator;
my $prev_import = *{$class."::import"}{CODE};
return sub {
my ($imported_class, @args) = @_;
my $def_terminator =
qr/^(?:\s*no\s+$imported_class\s*;$ows|__(?:END|DATA)__)\r?$/;
- if (!defined $terminator) {
- $terminator{terminator} = $def_terminator;
+ if (!defined $terminator_) {
+ $terminator->{terminator} = $def_terminator;
}
- elsif (!ref $terminator || ref $terminator eq 'Regexp') {
- $terminator{terminator} = $terminator;
+ elsif (!ref $terminator_ || ref $terminator_ eq 'Regexp') {
+ $terminator->{terminator} = $terminator_;
}
- elsif (ref $terminator ne 'HASH') {
+ elsif (ref $terminator_ ne 'HASH') {
croak "Terminator must be specified as scalar or hash ref"
}
- elsif (!exists $terminator->{terminator}) {
- $terminator{terminator} = $def_terminator;
+ else {
+ if (!exists $terminator_->{terminator}) {
+ $terminator_->{terminator} = $def_terminator;
+ }
+ $terminator = $terminator_;
}
filter_add(
sub {
@@ -186,8 +189,8 @@
my $data = "";
while ($status = filter_read()) {
return $status if $status < 0;
- if ($terminator{terminator} &&
- m/$terminator{terminator}/) {
+ if ($terminator->{terminator} &&
+ m/$terminator->{terminator}/) {
$lastline = $_;
last;
}
@@ -199,8 +202,8 @@
$_ = $data;
$filter->($imported_class, @args) unless $status < 0;
if (defined $lastline) {
- if (defined $terminator{becomes}) {
- $_ .= $terminator{becomes};
+ if (defined $terminator->{becomes}) {
+ $_ .= $terminator->{becomes};
}
elsif ($lastline =~ $def_terminator) {
$_ .= $lastline;
@@ -429,6 +432,13 @@
(in which case the terminator is the value associated with the key
C<'terminator'>.
+If you need to terminate filtering, you need to ensure that filtered result
+ends by C<no ModuleName;> or a line including the same effect. Otherwise,
+applying filter continues beyond the terminator line!! If the second argument
+is a reference to a hash, it can be achieved by setting the value associated
+with the key C<'becomes'>. A line including terminator is replaced with the
+value associated with the key C<'becomes'>.
+
For example, to cause the previous filter to filter only up to a line of the
form:
@@ -441,6 +451,7 @@
FILTER {
s/BANG\s+BANG/die 'BANG' if \$BANG/g;
+ $_ .= "no BANG;\n"; # to ensure filter ends
}
qr/^\s*GNAB\s+esu\s*;\s*?$/;
@@ -448,9 +459,19 @@
FILTER {
s/BANG\s+BANG/die 'BANG' if \$BANG/g;
+ $_ .= "no BANG;\n"; # to ensure filter ends
}
{ terminator => qr/^\s*GNAB\s+esu\s*;\s*?$/ };
+or:
+
+ FILTER {
+ s/BANG\s+BANG/die 'BANG' if \$BANG/g;
+ }
+ { terminator => qr/^\s*GNAB\s+esu\s*;\s*?$/,
+ becomes => "no BANG\n"; # to ensure filter ends
+ };
+
and to prevent the filter's being turned off in any way:
package BANG;