ExtUtils-PerlPP

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

        ...

        if (!open(FILE, ">file")  ||  !(print FILE $script)  ||
            !close(FILE)) {
            die "Cannot write file: $!";
        }

    But in essence, what else is this than a Perl preprocessor?

    Traditionally you have to write such a Perl preprocessor for yourself
    all the time, although I have found that they always do the same, for
    example:

    -       Fix defaults, for example installation paths.

    -       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.

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

  Create a new preprocessor

    You start with creating an instance of *ExtUtils::PerlPP* by calling the
    *new* constructor:

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

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

    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 *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.

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

    config  A hash ref of preprocessor variables. In other words

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

            is what `-Dvar=val' is for the C preprocessor. Similarly you can
            compare

                delete $ppp->{'config'};

            with `-Uvar'. See the section on "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 *Data::Dumper*
            module. the Data::Dumper(3) manpage.

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

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

  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" }

  Using the frontend

    Most applications won't call the *new* or *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.

  Macro replacements

    The primary use of preprocessor variables (aka attributes of `$ppp-
    '{'config'}>) is replacing patterns in the stream written to the output
    file. With `$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. `$text' is the pattern being
    replaced, for example, if `$ppp-'{'config'}->{'bar'}> has the value
    `\&foo', then `~~bar~~' will be replaced with the result of

        foo($ppp, "bar");

    Arguments are not yet supported.

  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 `~&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.

  Conditional output

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

        #ifdef var
        ...
        #endif

    segment. This can be done with

        ~#if#~ <expression>
        ...



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