Blame Call/Call.pm

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