ExtUtils-PerlPP

 view release on metacpan or  search on metacpan

PerlPP.pm  view on Meta::CPAN


Fix defaults, for example installation paths.

=item -

Including or excluding code sections. It is a matter of taste whether one
likes to see

    if ($] < 5.003) {
	# Thirty lines of code following here
        ...
    } else {
        # A single line of code
        ...
    }

when already using Perl 5.005. I don't.

=back


This module is dedicated to simplify such tasks. In short, you can use
it like this:


=head2 Create a new preprocessor

You start with creating an instance of I<ExtUtils::PerlPP> by calling
the I<new> constructor:

    my $ppp = ExtUtils::PerlPP->new(%attr);

The constructor accepts a list of attributes, including the following:

=over 8

=item in_fh

The input file, any kind of IO object, for example an instance of
IO::File or IO::Scalar. More general: It can be any object that offers
a I<getline> method.

A scalar value (to be distinguished from an IO::Scalar instance!) will
be interpreted as a file name that the method opens for you.

=item out_fh

The output file; another IO object or any other object that offers a
I<print> method. A scalar value is accepted as output file name.

=item config

A hash ref of preprocessor variables. In other words

    $ppp->{'config'}->{'var'} = 1;

is what C<-Dvar=val> is for the C preprocessor. Similarly you can compare

    delete $ppp->{'config'};

with C<-Uvar>. See L<"Macro replacements"> below. Unlike C, variables may
be arbitrarily complex, in particular you can use hash or array refs as
values.

Surprisingly you may pass a scalar value again: In that case the file of
the same name evaluated and the result is used as a configuration hash.
In other words

    $ppp->{'config'} = "myapp.cfg";

is similar to

    $ppp->{'config'} = do "myapp.cfg";

Such config files can easily be created using the I<Data::Dumper> module.
L<Data::Dumper(3)>.

=item no_config_default

If a variable name is used, but no such attribute is present in the
I<config> hash, then by default the variable is looked up in the
C<$Config> from the I<Config> module. This behaviour is suppressed,
if you set I<no_config_default> to a TRUE value. L<Config(3)>.

=item no_makedirs

By default directories are created silently if required. For example,
if you pass a value of C</usr/local/foo/bar> as output file and only
C</usr/local> exists, then the subdirectory C<foo> will be created.
The option I<no_makedirs> suppresses this behaviour.

=back


=head2 Running the preprocessor

This is done by executing

    $ppp->parse();

A Perl exception will be thrown in case of errors, thus the complete
use might look like this:

    eval { $ppp->parse(); };
    if ($@) { print "An error occurred: $@\n" }


=head2 Using the frontend

Most applications won't call the I<new> or I<parse> methods directly,
but rather do a

    use ExtUtils::PerlPP;
    ppp('infile', 'outfile', 'configfile');

This is equivalent to

    my $parser = ExtUtils::PerlPP->new('in_fh' => 'infile',
				       'out_fh' => 'outfile',
                                       'config' => 'configfile');
    $parser->parse();

In order to be easily used within Makefiles, the ppp frontend can
read from @ARGV. That is, you can use the module like this:

    perl -MExtUtils::PerlPP -e ppp <infile> <outfile> <configfile>

from the commandline.


=head2 Macro replacements

The primary use of preprocessor variables (aka attributes of
C<$ppp->{'config'}>) is replacing patterns in the stream written to
the output file. With C<$c = $ppp->{'config'}> in mind the typical
patterns and their replacements are:

    ~~a~~		$c->{'a'}
    ~~b~~		$c->{'b'}
    ~~a->b~~		$c->{'a'}->{'b'}
    ~~a->e~~		$c->{'a'}->{'e'}
    ~~a->1~~		$c->{'a'}->[1]
    ~~a->1->b~~         $c->{'a'}->[1]->{'b'}

I hope the idea is obvious. Real world examples might be:

    my $config_file = "~~etc_dir~~/configuration";
    my $VERSION = "~~version~~";

Preprocessor variables need not be scalar values: If a variable contains a
code ref, then the module will execute

    &$var($ppp, $text);

and replace the pattern with the result. C<$text> is the pattern being
replaced, for example, if C<$ppp->{'config'}->{'bar'}> has the value
C<\&foo>, then C<~~bar~~> will be replaced with the result of

    foo($ppp, "bar");

Arguments are not yet supported.


=head2 Creating macros

When talking about code refs, we need a possibility to create them.
The best possibility is creating them within the input file, as in

    ~&foo&~ my($self, $text) = @_; $text x 2; ~&&~

This example is mainly equivalent to

    $ppp->{'config'}->{'foo'} = sub {
        my($self, $text) = @_; $text x 2;
    };

The C<~&var&~> definition must start at the beginning of a line, much
like the C preprocessor. The end pattern ~&&~ may appear at any point,
but the remaining line will be ignored.


=head2 Conditional output

The next application of a preprocessor is conditional output, as in an

    #ifdef var
    ...
    #endif

segment. This can be done with



( run in 1.063 second using v1.01-cache-2.11-cpan-39bf76dae61 )