|
Packit |
745572 |
# Call.pm
|
|
Packit |
745572 |
#
|
|
Packit |
745572 |
# Copyright (c) 1995-2011 Paul Marquess. All rights reserved.
|
|
Packit |
745572 |
# Copyright (c) 2011-2014 Reini Urban. All rights reserved.
|
|
Packit |
745572 |
# Copyright (c) 2014-2017 cPanel Inc. All rights reserved.
|
|
Packit |
745572 |
#
|
|
Packit |
745572 |
# This program is free software; you can redistribute it and/or
|
|
Packit |
745572 |
# modify it under the same terms as Perl itself.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
package Filter::Util::Call ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
require 5.006 ; # our
|
|
Packit |
745572 |
require Exporter;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use XSLoader ();
|
|
Packit |
745572 |
use strict;
|
|
Packit |
745572 |
use warnings;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
our @ISA = qw(Exporter);
|
|
Packit |
745572 |
our @EXPORT = qw( filter_add filter_del filter_read filter_read_exact) ;
|
|
Packit |
745572 |
our $VERSION = "1.58" ;
|
|
Packit |
745572 |
our $XS_VERSION = $VERSION;
|
|
Packit |
745572 |
$VERSION = eval $VERSION;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub filter_read_exact($)
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my ($size) = @_ ;
|
|
Packit |
745572 |
my ($left) = $size ;
|
|
Packit |
745572 |
my ($status) ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
unless ( $size > 0 ) {
|
|
Packit |
745572 |
require Carp;
|
|
Packit |
745572 |
Carp::croak("filter_read_exact: size parameter must be > 0");
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
# try to read a block which is exactly $size bytes long
|
|
Packit |
745572 |
while ($left and ($status = filter_read($left)) > 0) {
|
|
Packit |
745572 |
$left = $size - length $_ ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
# EOF with pending data is a special case
|
|
Packit |
745572 |
return 1 if $status == 0 and length $_ ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
return $status ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub filter_add($)
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my($obj) = @_ ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
# Did we get a code reference?
|
|
Packit |
745572 |
my $coderef = (ref $obj eq 'CODE');
|
|
Packit |
745572 |
|
|
Packit |
745572 |
# If the parameter isn't already a reference, make it one.
|
|
Packit |
745572 |
if (!$coderef and (!ref($obj) or ref($obj) =~ /^ARRAY|HASH$/)) {
|
|
Packit |
745572 |
$obj = bless (\$obj, (caller)[0]);
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
# finish off the installation of the filter in C.
|
|
Packit |
745572 |
Filter::Util::Call::real_import($obj, (caller)[0], $coderef) ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
XSLoader::load('Filter::Util::Call');
|
|
Packit |
745572 |
|
|
Packit |
745572 |
1;
|
|
Packit |
745572 |
__END__
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head1 NAME
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Filter::Util::Call - Perl Source Filter Utility Module
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head1 SYNOPSIS
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Filter::Util::Call ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head1 DESCRIPTION
|
|
Packit |
745572 |
|
|
Packit |
745572 |
This module provides you with the framework to write I<Source Filters>
|
|
Packit |
745572 |
in Perl.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
An alternate interface to Filter::Util::Call is now available. See
|
|
Packit |
745572 |
L<Filter::Simple> for more details.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
A I<Perl Source Filter> is implemented as a Perl module. The structure
|
|
Packit |
745572 |
of the module can take one of two broadly similar formats. To
|
|
Packit |
745572 |
distinguish between them, the first will be referred to as I
|
|
Packit |
745572 |
filter> and the second as I<closure filter>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Here is a skeleton for the I<method filter>:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
package MyFilter ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Filter::Util::Call ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub import
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my($type, @arguments) = @_ ;
|
|
Packit |
745572 |
filter_add([]) ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub filter
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my($self) = @_ ;
|
|
Packit |
745572 |
my($status) ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
$status = filter_read() ;
|
|
Packit |
745572 |
$status ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
1 ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
and this is the equivalent skeleton for the I<closure filter>:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
package MyFilter ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Filter::Util::Call ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub import
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my($type, @arguments) = @_ ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
filter_add(
|
|
Packit |
745572 |
sub
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my($status) ;
|
|
Packit |
745572 |
$status = filter_read() ;
|
|
Packit |
745572 |
$status ;
|
|
Packit |
745572 |
} )
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
1 ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
To make use of either of the two filter modules above, place the line
|
|
Packit |
745572 |
below in a Perl source file.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use MyFilter;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
In fact, the skeleton modules shown above are fully functional I
|
|
Packit |
745572 |
Filters>, albeit fairly useless ones. All they does is filter the
|
|
Packit |
745572 |
source stream without modifying it at all.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
As you can see both modules have a broadly similar structure. They both
|
|
Packit |
745572 |
make use of the C<Filter::Util::Call> module and both have an C<import>
|
|
Packit |
745572 |
method. The difference between them is that the I<method filter>
|
|
Packit |
745572 |
requires a I<filter> method, whereas the I<closure filter> gets the
|
|
Packit |
745572 |
equivalent of a I<filter> method with the anonymous sub passed to
|
|
Packit |
745572 |
I<filter_add>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
To make proper use of the I<closure filter> shown above you need to
|
|
Packit |
745572 |
have a good understanding of the concept of a I<closure>. See
|
|
Packit |
745572 |
L<perlref> for more details on the mechanics of I<closures>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head2 B<use Filter::Util::Call>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The following functions are exported by C<Filter::Util::Call>:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
filter_add()
|
|
Packit |
745572 |
filter_read()
|
|
Packit |
745572 |
filter_read_exact()
|
|
Packit |
745572 |
filter_del()
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head2 B<import()>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The C<import> method is used to create an instance of the filter. It is
|
|
Packit |
745572 |
called indirectly by Perl when it encounters the C<use MyFilter> line
|
|
Packit |
745572 |
in a source file (See L<perlfunc/import> for more details on
|
|
Packit |
745572 |
C<import>).
|
|
Packit |
745572 |
|
|
Packit |
745572 |
It will always have at least one parameter automatically passed by Perl
|
|
Packit |
745572 |
- this corresponds to the name of the package. In the example above it
|
|
Packit |
745572 |
will be C<"MyFilter">.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Apart from the first parameter, import can accept an optional list of
|
|
Packit |
745572 |
parameters. These can be used to pass parameters to the filter. For
|
|
Packit |
745572 |
example:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use MyFilter qw(a b c) ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
will result in the C<@_> array having the following values:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
@_ [0] => "MyFilter"
|
|
Packit |
745572 |
@_ [1] => "a"
|
|
Packit |
745572 |
@_ [2] => "b"
|
|
Packit |
745572 |
@_ [3] => "c"
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Before terminating, the C<import> function must explicitly install the
|
|
Packit |
745572 |
filter by calling C<filter_add>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head2 B<filter_add()>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The function, C<filter_add>, actually installs the filter. It takes one
|
|
Packit |
745572 |
parameter which should be a reference. The kind of reference used will
|
|
Packit |
745572 |
dictate which of the two filter types will be used.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
If a CODE reference is used then a I<closure filter> will be assumed.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
If a CODE reference is not used, a I<method filter> will be assumed.
|
|
Packit |
745572 |
In a I<method filter>, the reference can be used to store context
|
|
Packit |
745572 |
information. The reference will be I<blessed> into the package by
|
|
Packit |
745572 |
C<filter_add>, unless the reference was already blessed.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
See the filters at the end of this documents for examples of using
|
|
Packit |
745572 |
context information using both I<method filters> and I
|
|
Packit |
745572 |
filters>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head2 B<filter() and anonymous sub>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Both the C<filter> method used with a I<method filter> and the
|
|
Packit |
745572 |
anonymous sub used with a I<closure filter> is where the main
|
|
Packit |
745572 |
processing for the filter is done.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The big difference between the two types of filter is that the I
|
|
Packit |
745572 |
filter> uses the object passed to the method to store any context data,
|
|
Packit |
745572 |
whereas the I<closure filter> uses the lexical variables that are
|
|
Packit |
745572 |
maintained by the closure.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Note that the single parameter passed to the I<method filter>,
|
|
Packit |
745572 |
C<$self>, is the same reference that was passed to C<filter_add>
|
|
Packit |
745572 |
blessed into the filter's package. See the example filters later on for
|
|
Packit |
745572 |
details of using C<$self>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Here is a list of the common features of the anonymous sub and the
|
|
Packit |
745572 |
C<filter()> method.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=over 5
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=item B<$_>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Although C<$_> doesn't actually appear explicitly in the sample filters
|
|
Packit |
745572 |
above, it is implicitly used in a number of places.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Firstly, when either C<filter> or the anonymous sub are called, a local
|
|
Packit |
745572 |
copy of C<$_> will automatically be created. It will always contain the
|
|
Packit |
745572 |
empty string at this point.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Next, both C<filter_read> and C<filter_read_exact> will append any
|
|
Packit |
745572 |
source data that is read to the end of C<$_>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Finally, when C<filter> or the anonymous sub are finished processing,
|
|
Packit |
745572 |
they are expected to return the filtered source using C<$_>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
This implicit use of C<$_> greatly simplifies the filter.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=item B<$status>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The status value that is returned by the user's C<filter> method or
|
|
Packit |
745572 |
anonymous sub and the C<filter_read> and C<read_exact> functions take
|
|
Packit |
745572 |
the same set of values, namely:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
< 0 Error
|
|
Packit |
745572 |
= 0 EOF
|
|
Packit |
745572 |
> 0 OK
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=item B<filter_read> and B<filter_read_exact>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
These functions are used by the filter to obtain either a line or block
|
|
Packit |
745572 |
from the next filter in the chain or the actual source file if there
|
|
Packit |
745572 |
aren't any other filters.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The function C<filter_read> takes two forms:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
$status = filter_read() ;
|
|
Packit |
745572 |
$status = filter_read($size) ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The first form is used to request a I<line>, the second requests a
|
|
Packit |
745572 |
I<block>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
In line mode, C<filter_read> will append the next source line to the
|
|
Packit |
745572 |
end of the C<$_> scalar.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
In block mode, C<filter_read> will append a block of data which is <=
|
|
Packit |
745572 |
C<$size> to the end of the C<$_> scalar. It is important to emphasise
|
|
Packit |
745572 |
the that C<filter_read> will not necessarily read a block which is
|
|
Packit |
745572 |
I<precisely> C<$size> bytes.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
If you need to be able to read a block which has an exact size, you can
|
|
Packit |
745572 |
use the function C<filter_read_exact>. It works identically to
|
|
Packit |
745572 |
C<filter_read> in block mode, except it will try to read a block which
|
|
Packit |
745572 |
is exactly C<$size> bytes in length. The only circumstances when it
|
|
Packit |
745572 |
will not return a block which is C<$size> bytes long is on EOF or
|
|
Packit |
745572 |
error.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
It is I<very> important to check the value of C<$status> after I<every>
|
|
Packit |
745572 |
call to C<filter_read> or C<filter_read_exact>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=item B<filter_del>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The function, C<filter_del>, is used to disable the current filter. It
|
|
Packit |
745572 |
does not affect the running of the filter. All it does is tell Perl not
|
|
Packit |
745572 |
to call filter any more.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
See L<Example 4: Using filter_del> for details.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=item I<real_import>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Internal function which adds the filter, based on the L<filter_add>
|
|
Packit |
745572 |
argument type.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=item I<unimport()>
|
|
Packit |
745572 |
|
|
Packit |
745572 |
May be used to disable a filter, but is rarely needed. See L<filter_del>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=back
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head1 LIMITATIONS
|
|
Packit |
745572 |
|
|
Packit |
745572 |
See L<perlfilter/LIMITATIONS> for an overview of the general problems
|
|
Packit |
745572 |
filtering code in a textual line-level only.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=over
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=item __DATA__ is ignored
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The content from the __DATA__ block is not filtered.
|
|
Packit |
745572 |
This is a serious limitation, e.g. for the L<Switch> module.
|
|
Packit |
745572 |
See L<http://search.cpan.org/perldoc?Switch#LIMITATIONS> for more.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=item Max. codesize limited to 32-bit
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Currently internal buffer lengths are limited to 32-bit only.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=back
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head1 EXAMPLES
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Here are a few examples which illustrate the key concepts - as such
|
|
Packit |
745572 |
most of them are of little practical use.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The C<examples> sub-directory has copies of all these filters
|
|
Packit |
745572 |
implemented both as I<method filters> and as I<closure filters>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head2 Example 1: A simple filter.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Below is a I<method filter> which is hard-wired to replace all
|
|
Packit |
745572 |
occurrences of the string C<"Joe"> to C<"Jim">. Not particularly
|
|
Packit |
745572 |
Useful, but it is the first example and I wanted to keep it simple.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
package Joe2Jim ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Filter::Util::Call ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub import
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my($type) = @_ ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
filter_add(bless []) ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub filter
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my($self) = @_ ;
|
|
Packit |
745572 |
my($status) ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
s/Joe/Jim/g
|
|
Packit |
745572 |
if ($status = filter_read()) > 0 ;
|
|
Packit |
745572 |
$status ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
1 ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Here is an example of using the filter:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Joe2Jim ;
|
|
Packit |
745572 |
print "Where is Joe?\n" ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
And this is what the script above will print:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Where is Jim?
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head2 Example 2: Using the context
|
|
Packit |
745572 |
|
|
Packit |
745572 |
The previous example was not particularly useful. To make it more
|
|
Packit |
745572 |
general purpose we will make use of the context data and allow any
|
|
Packit |
745572 |
arbitrary I<from> and I<to> strings to be used. This time we will use a
|
|
Packit |
745572 |
I<closure filter>. To reflect its enhanced role, the filter is called
|
|
Packit |
745572 |
C<Subst>.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
package Subst ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Filter::Util::Call ;
|
|
Packit |
745572 |
use Carp ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub import
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
croak("usage: use Subst qw(from to)")
|
|
Packit |
745572 |
unless @_ == 3 ;
|
|
Packit |
745572 |
my ($self, $from, $to) = @_ ;
|
|
Packit |
745572 |
filter_add(
|
|
Packit |
745572 |
sub
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my ($status) ;
|
|
Packit |
745572 |
s/$from/$to/
|
|
Packit |
745572 |
if ($status = filter_read()) > 0 ;
|
|
Packit |
745572 |
$status ;
|
|
Packit |
745572 |
})
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
1 ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
and is used like this:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Subst qw(Joe Jim) ;
|
|
Packit |
745572 |
print "Where is Joe?\n" ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head2 Example 3: Using the context within the filter
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Here is a filter which a variation of the C<Joe2Jim> filter. As well as
|
|
Packit |
745572 |
substituting all occurrences of C<"Joe"> to C<"Jim"> it keeps a count
|
|
Packit |
745572 |
of the number of substitutions made in the context object.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Once EOF is detected (C<$status> is zero) the filter will insert an
|
|
Packit |
745572 |
extra line into the source stream. When this extra line is executed it
|
|
Packit |
745572 |
will print a count of the number of substitutions actually made.
|
|
Packit |
745572 |
Note that C<$status> is set to C<1> in this case.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
package Count ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Filter::Util::Call ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub filter
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my ($self) = @_ ;
|
|
Packit |
745572 |
my ($status) ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
if (($status = filter_read()) > 0 ) {
|
|
Packit |
745572 |
s/Joe/Jim/g ;
|
|
Packit |
745572 |
++ $$self ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
elsif ($$self >= 0) { # EOF
|
|
Packit |
745572 |
$_ = "print q[Made ${$self} substitutions\n]" ;
|
|
Packit |
745572 |
$status = 1 ;
|
|
Packit |
745572 |
$$self = -1 ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
$status ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub import
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my ($self) = @_ ;
|
|
Packit |
745572 |
my ($count) = 0 ;
|
|
Packit |
745572 |
filter_add(\$count) ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
1 ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Here is a script which uses it:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Count ;
|
|
Packit |
745572 |
print "Hello Joe\n" ;
|
|
Packit |
745572 |
print "Where is Joe\n" ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Outputs:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Hello Jim
|
|
Packit |
745572 |
Where is Jim
|
|
Packit |
745572 |
Made 2 substitutions
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head2 Example 4: Using filter_del
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Another variation on a theme. This time we will modify the C<Subst>
|
|
Packit |
745572 |
filter to allow a starting and stopping pattern to be specified as well
|
|
Packit |
745572 |
as the I<from> and I<to> patterns. If you know the I<vi> editor, it is
|
|
Packit |
745572 |
the equivalent of this command:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
:/start/,/stop/s/from/to/
|
|
Packit |
745572 |
|
|
Packit |
745572 |
When used as a filter we want to invoke it like this:
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use NewSubst qw(start stop from to) ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Here is the module.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
package NewSubst ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
use Filter::Util::Call ;
|
|
Packit |
745572 |
use Carp ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
sub import
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my ($self, $start, $stop, $from, $to) = @_ ;
|
|
Packit |
745572 |
my ($found) = 0 ;
|
|
Packit |
745572 |
croak("usage: use Subst qw(start stop from to)")
|
|
Packit |
745572 |
unless @_ == 5 ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
filter_add(
|
|
Packit |
745572 |
sub
|
|
Packit |
745572 |
{
|
|
Packit |
745572 |
my ($status) ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
if (($status = filter_read()) > 0) {
|
|
Packit |
745572 |
|
|
Packit |
745572 |
$found = 1
|
|
Packit |
745572 |
if $found == 0 and /$start/ ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
if ($found) {
|
|
Packit |
745572 |
s/$from/$to/ ;
|
|
Packit |
745572 |
filter_del() if /$stop/ ;
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
$status ;
|
|
Packit |
745572 |
} )
|
|
Packit |
745572 |
|
|
Packit |
745572 |
}
|
|
Packit |
745572 |
|
|
Packit |
745572 |
1 ;
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head1 Filter::Simple
|
|
Packit |
745572 |
|
|
Packit |
745572 |
If you intend using the Filter::Call functionality, I would strongly
|
|
Packit |
745572 |
recommend that you check out Damian Conway's excellent Filter::Simple
|
|
Packit |
745572 |
module. Damian's module provides a much cleaner interface than
|
|
Packit |
745572 |
Filter::Util::Call. Although it doesn't allow the fine control that
|
|
Packit |
745572 |
Filter::Util::Call does, it should be adequate for the majority of
|
|
Packit |
745572 |
applications. It's available at
|
|
Packit |
745572 |
|
|
Packit |
745572 |
http://search.cpan.org/dist/Filter-Simple/
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head1 AUTHOR
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Paul Marquess
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head1 DATE
|
|
Packit |
745572 |
|
|
Packit |
745572 |
26th January 1996
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=head1 LICENSE
|
|
Packit |
745572 |
|
|
Packit |
745572 |
Copyright (c) 1995-2011 Paul Marquess. All rights reserved.
|
|
Packit |
745572 |
Copyright (c) 2011-2014 Reini Urban. All rights reserved.
|
|
Packit |
745572 |
Copyright (c) 2014-2017 cPanel Inc. All rights reserved.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
This program is free software; you can redistribute it and/or
|
|
Packit |
745572 |
modify it under the same terms as Perl itself.
|
|
Packit |
745572 |
|
|
Packit |
745572 |
=cut
|
|
Packit |
745572 |
|