The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
=head1 NAME

makepp_builtins -- Builtin commands in makepp

=for vc $Id: makepp_builtins.pod,v 1.56 2014/07/08 22:37:36 pfeiffer Exp $

=head1 DESCRIPTION

=for genindex '&?(?!export|I<)\w+' makepp_builtins.pod

B<A:>E<nbsp>L<I<awk>|/awk>,E<nbsp>
B<C:>E<nbsp>L<&cat|/cat_option_filename>,
  L<I<chgrp>|/chgrp>,
  L<&chmod|/chmod_option_mode_filename>,
  L<I<chown>|/chgrp>,
  L<&cp|/cp_option_sourcefile_destfile>,
  L<I<cpp>|/cpp>,
  L<&cut|/cut_option_filename>,E<nbsp>
B<D:>E<nbsp>L<I<date>|/date>,E<nbsp>
B<E:>E<nbsp>L<&echo|/echo_option_string>,
  L<&expr|/expr_option_perlcode>,E<nbsp>
B<F:>E<nbsp>L<I<false>|/false>,
  L<I<fmt>|/fmt>,E<nbsp>
B<G:>E<nbsp>L<&grep|/grep_option_perlcode_filename>,E<nbsp>
B<H:>E<nbsp>L<I<head>|/head>,E<nbsp>
B<I:>E<nbsp>L<&install|/install_option_sourcefile_destfile>,E<nbsp>
B<L:>E<nbsp>L<&ln|/ln_option_sourcefile_destfile>,E<nbsp>
B<M:>E<nbsp>L<I<m4>|/m4>,
  L<&mkdir|/mkdir_option_directory>,
  L<&mv|/mv_option_sourcefile_destfile>,E<nbsp>
B<P:>E<nbsp>L<&perl|/grep_option_perlcode_filename>,
  L<&preprocess|/preprocess_option_variable_definition_filename>,
  L<&printf|/echo_option_string>,E<nbsp>
B<R:>E<nbsp>L<&rm|/rm_option_filename>,
  L<I<rmdir>|/rmdir>,E<nbsp>
B<S:>E<nbsp>L<&sed|/grep_option_perlcode_filename>,
  L<&sort|/sort_option_filename>,E<nbsp>
B<T:>E<nbsp>L<I<tail>|/head>,
  L<&template|/template_option_macro_definition_filename>,
  L<&touch|/touch_option_filename>,
  L<I<tr>|/tr>,E<nbsp>
B<U:>E<nbsp>L<&uninstall|/uninstall_option_filename>,
  L<&uniq|/uniq_option_filename>,E<nbsp>
B<Y:>E<nbsp>L<&yes|/echo_option_string>

There is a special Shell-like possibility to call built-in commands in a rule.
The only metacharacters recognized are comment signs, backslashes, single and
double quotes.  Only one command may be given per line, and I/O redirection is
not available (see C<-i> and C<-o> below instead).

These commands start with C<&>, which is the function character in Perl and
not a valid first character in Shell.  If no builtin command of that name can
be found, this is also the syntax for calling an external script within the
Perl instance performing the rule.  See L<C<run>|makepp_extending/run_script_arguments>.

These commands, as well as your self defined ones and Perl scripts can also be
called as a make function, returning the standard output.  This requires perl
to be built for PerlIO.  The newlines are converted to spaces, except when
evaluated within a C<define> statement.

    FIRST-WORDS ;= $(&cut -d' ' -f0 $(FILES))

When these commands are not indented as rule actions, they get
L<performed|makepp_statements/Commands> while reading the makefile.  You can
also access these commands stand-alone, e.g. if you need some features not
available in the Unix counterpart, via the L<makeppbuiltin|makeppbuiltin>
command.

These commands are mostly based on the GNU variant.  But many options (like
--backup, --interactive or --recursive) don't really make sense in a makefile.
So, even though they'd be easy to implement in Perl, they have been left out.
Also many Unix commands offer a variety of options that cover fairly
complicated cases (e.g. sort field specifications) while still being
inherently limited.  Allowing access to Perl, which is present anyway, gives
much more power here.

Lists of filenames may be empty, making it safe to call these commands with an
unchecked list.  Options in their short form may be glued together as in
C<-ab> instead of C<-a -b>.  In the long form arguments may be given either
glued on with an C<=> sign or separately.  In the short form they may be given
either glued on directly or separately.



=head2 Standard options

A few options are common to several builtins, though the short form is
sometimes hidden by a command's own option (as in C<&cut -f>):

=over

=item -A I<filename>

=item --args-file=I<filename>

=item --arguments-file=I<filename>

Read the file and parse it as possibly quoted whitespace- and/or newline-separated options.

=item -f

=item --force

Force the creation of the file(s) intended by the parameters, even if a
different kind of file or empty directory of that name already exists.  This
must precede the C<-o, --output=filename> option if it is to have any effect
on that.

=item -i I<shellcommand>

=item --inpipe=I<shellcommand>

Start the Shell command(s) and pipe the output into the builtin.  There may
optionally be a trailing C<|> character, to indicate this is a pipe.  With
this option no filenames need to be given.  But if you want to perform the
builtin on both files and the pipe output, you must use C<-> as a filename for
the pipe output.  The pipe is emptied, but, unless you also give C<--infail>,
the command is not waited for, so it can terminate in parallel.  This option
is necessary because there is no redirection syntax.

=item -I

=item --infail

If an C<--inpipe> Shell command fails, that also causes the current builtin to
fail.  This doesn't currently work on Strawberry and Win ActiveState, because
of the halfhearted way they emulate Unix fork/exec.  Cygwin gets it right
though.

=item -o I<filename>

=item --output=I<filename>

Write the output to this file, rather than stdout.  Filename may have any of these forms:

=over

=item I<filename>

=item >I<filename>

Simply write to file.

=item >>I<filename>

Append to (not necessarily) existing file.

=item +<I<filename>

Also open the file for input, allowing inplace editing.  With this option
variant no input filenames need to be given.  But if you want to perform the
builtin on more files, you must use C<-> as an input filename for this one.
In fact the output gets written to a temporary file which gets moved to
filename at the end.

=item |I<shellcommand>

Pipe the builtin's output to the Shell command(s).

=back

This option is necessary because there is no redirection syntax.

=item -O

=item --outfail

If an C<--output> Shell command fails, that also causes the current builtin to
fail.

=item -r I<number>

=item --record-size=I<number>

Locally sets C<$/> for the current builtin.  This splits input into records of
length I<number> rather than line by line.  If I<number> is zero, each input
file as a whole is one record.

=item -s I<string>

=item --separator=I<string>

Locally sets C<$/> for the current builtin.  This splits input on I<string>
rather than line by line.

=item -S

=item --synclines

Generate C<#line >I<C<NO>>C< ">I<C<FILE>>C<"> and C<#line >I<C<NO>> lines,
understood by many C-like languages.

=item -v

=item --verbose

Document the changes to the file system.  This must precede other options if
it is to document their effect.  If you pass this option to makepp itself, it
is as if you had given it for every single builtin command.

=back



=head2 Builtin commands

There are two motivations for having builtin commands in makepp.  The first is
to offer a set of utilities, which, unlike Shell commands, are guaranteed to
work the same everywhere, like L<C<&echo -n>|/echo_option_string> or
L<C<&mkdir -p>|/mkdir_option_directory>, and saving you the hassle of finding
the path to L<C<&install>|/install_option_sourcefile_destfile> and figuring
out its wildly varying options.  In a compilation environment, it's useful to
have the C<--synclines> option, which normally only C<m4> provides, on all
filters.

The other is a question of efficiency.  In general costly fork/execs should be
avoided where reasonably possible.  On Unix emulations like Cygwin or
BS2000/Posix, this becomes a noticeable win.  But, even on Linux, when the
makepp test suite was converted from external commands to builtins, there was
an overall saving of 3% user CPU usage and 15% system CPU usage.  (The tests
are of course heavy on primitive actions and hardly call the compiler.)

Consistency is also an issue, though we're not going to reform Unix.  Normally
commands have various nuances of regular expressions.  And many invent sort of
languages, each different of course, for doing something (e.g. C<expr>, C<sed>
...), or complex options for specifying fields, delimiters, columns
(e.g. C<cut>, C<sort> ...).

Here instead, anything fancy simply gets handled by Perl, giving both
consistency across all commands, and far more power than a whole bunch of
options.  Better yet, any I<Perlcode> these commands run for you, gets run in
the package of the Makefile.  So, rather than stuff Perl code into the rule
action, you can define functions and variables and use them within the
commands:

    sub my_filter {
      # Return true iff $_ is desirable
    }
    %.out: %.in Makeppfile
 	&grep &my_filter $(input) -o $(output)

If you use Perl functions or variables in your commands, makepp does not
recognize this as a dependency.  It is generally safer to tell makepp
everything, so rules which use Perl elements should depend on the makefile or
module providing those elements, as shown in the above example.

On the other hand ignorance may be desirable if you have a program that mixes
programmatic and configuration aspects in one file.  An example would be a WSDL
file containing both a web service interface definition and an IP address.
You could preprocess this file with the C<&template> command to patch in the
configuration, but not let makepp notice.

=over


=item &cat I<[option ...] filename ...>

Concatenates all the files into a single one.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force,
-i, --inpipe=shellcommand, -I, --infail, -o, --output=filename, -O, --outfail,
-S, --synclines, -v, --verbose>



=item &chmod I<[option ...] mode filename ...>

Sets I<mode> for all given files.  Mode must be an octal string.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -v, --verbose>



=item &cp I<[option ...] sourcefile destfile>

=item &cp I<[option ...] sourcefile>

=item &cp I<[option ...] sourcefile ... destdir>

Copy I<sourcefile> to I<destfile>, one I<sourcefile> to current directory or
multiple I<sourcefile>s to I<destdir> with the same name.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -v,
--verbose>

=over

=item -l

=item --link

Try to link the files.  If that fails, try symbolic link, if that is also
requested, else copy.

=item -s

=item --symbolic

=item --symbolic-link

=item --symlink

Try to symbolically link the files.  If that fails, copy.

=back

See the note under L<&ln|/ln_option_sourcefile_destfile>.



=item &cut I<[option ...] filename ...>

Print selected parts of lines from each file or selected lines, counting
across all files.  The output is separated by the delimiter which defaults to
TAB for fields and empty string for characters.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, --force, -i,
--inpipe=shellcommand, -I, --infail, -o, --output=filename, -O, --outfail, -r,
--record-size=number, --separator=string, -S, --synclines, -v, --verbose>

=over

=item -c I<list>

=item --characters=I<list>

Print all the characters specified by I<list>.  I<List> may be any Perl
expression returning a list of integers.  The integers can be either positive,
starting at zero to count from the beginning, or negative to count from the
end.  Unlike Unix C<cut>, the order you request is respected.

Unlike in Perl's slice operator where a ".." range must be either positive or
negative, C<&cut> allows starting with a positive and ending with a negative.
But this is only available if your expression consists only of numbers, commas
and "..".  E.g. C<1..-2> means everything but the first (0) and the last (-1).

The list expression can look at the whole line in C<$_>.  Changes to that will
be ignored, however, because when this expression is evaluated the line has
already been split to Perl's autosplit variable C<@::F>.  The numbers you
return are in fact indices to that list.

=item -d I<string>

=item --delimiter=I<string>

Set a new delimiter for input fields and output.  Unlike Unix C<cut>, this may
have any length.

=item -E

=item --noescape

Treat C<\> as normal literals for C<-p, --printf=format>.

=item -f I<list>

=item --fields=I<list>

Print all the groups specified by I<list>.  I<List> is as described under
C<-c, --characters=list>.  Note that this hides the standard option C<-f>
which must be given as C<--force>.

=item -l I<list>

=item --lines=I<list>

Print all the lines specified by I<list>.  I<List> is as described under C<-c,
--characters=list> with one major difference: The first line has number 1,
there is no line 0.  This is definitely inefficient for big files, if you have
a mixed positive to negative range in your list, as it reads everything to
memory.  Otherwise Perl could optimize this, but I don't know if it does.

=item -m

=item --matching

Print only matching lines, i.e. ones which have enough characters or fields.
This implies C<--only-delimited>, which is why you will miss single-field
lines with C<--fields=0>.

=item -p I<format>

=item --printf=I<format>

Apply format (with \escapes) to all fields or characters.

=item -s

=item --only-delimited

Print only lines containing delimiters.

=back

    &cut -c 10-20,-5,25- $(input)
    &cut -c 'grep $$_ % 3, 0..99' $(input) # 1st 100 columns not multiple of 3
    &cut -d: --fields 0,4 --printf='%10s is %s\n' /etc/passwd



=item &echo I<[option ...] string ...>

=item &printf I<[option ...] format argument ...>

=item &yes I<[option ...] string ...>

Writes all strings to stdout or the given outfile.  Both C<&echo> and C<&yes>
add a newline at the end.  The strings, or for C<&printf> the format, may
contain C<\> escapes, as they are known from C or modern Unix or Shell
C<echo>.  They are however as in Perl double-quotes, which means some
differences, like that a single trailing C<\> is not allowed.  Perl has a few
more interesting escapes, but the ones you might expect to do something
different are:

=over

=item \cA

Is a control character ^A.

=item \u

Upcases the following letter.

=item \U

Upcases the rest, or up to the next C<\E> or C<\L> if found.

=item \xI<HH>, \x{I<HHHH>}

Is the character value of the given Hex code.  Note that numeric codes are not
portable to EBCDIC platforms!

=back

Unlike Unix C<yes>, C<&yes> is exactly like C<&echo>, except that it repeats
the output for as long as it can, typically until an C<--output '| I<command>'>
terminates.  And, if C<&yes> has no arguments, it defaults to C<y>.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -o,
--output=filename, -O, --outfail, -v, --verbose>

=over

=item -E

=item --noescape

Treat C<\> as normal literals.

=item -n

=item --nonewline

Do not add a newline after the last string.  (Not understood by C<&printf>.)

=back



=item &expr I<[option ...] perlcode ...>

Print the scalar value of perlcode, which may be written as one or several
arguments.  Note that builtin commands are not parsed by the Shell, so C<*>,
C<(> or C<< > >> are not special.  But string quotes are parsed by makepp, so
Perl strings must be quoted twice, unless you want to use barewords.  If the
value is false, this fails.  Note that -- unlike in Unix C<expr> -- Perl's index
function starts at 0 (false) and returns -1 (true) for failure.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -o,
--output=filename, -O, --outfail, -v, --verbose>

=over

=item -n

=item --nonewline

Do not add a newline after the output.

=back

    &expr ($(VAR) - 3) * 2 < 1 && -1 || 1
    &expr "$(VAR) - 3 * 2 < 1 ? 'joy' : 'sorrow'" -o $(output)
    -&expr $(VAR) - 3 * 2 -o >>$(output)



=item &grep I<[option ...] perlcode filename ...>

=item &perl I<[option ...] perlcode filename ...>

=item &sed I<[option ...] perlcode filename ...>

All the files get read line by line (unless you gave a C<--separator> option),
and I<perlcode> gets evaluated for each line, before it gets printed.  C<&sed>
is similar to C<perl -pe>, while C<&grep> only outputs those lines for which
I<perlcode> returns a true value.  C<&perl> is similar to C<perl -ne>, only
outputting whatever you explicitly print in the I<perlcode>.  The line content
is available in C<$_>, which may be modified.

Of these three, only C<&grep> will fail if it outputs nothing.  Note that
there is no ignore-case option, since you would do that with C</I<regexp>/i>.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -i,
--inpipe=shellcommand, -I, --infail, -o, --output=filename, -O, --outfail, -r,
--record-size=number, -s, --separator=string, -S, --synclines, --verbose>

The option C<--synclines> only makes sence with C<&perl> if you use
C<&Mpp::Cmds::print> to output C<$_>.  Only C<&grep> has extra options:

=over

=item -c

=item --count

Suppress normal output; instead print a count of matching lines.  With the C<-v,
--invert-match> option (see below), count non-matching lines.

=item -l

=item --list

=item --files-with-matches

Output only the name of those files with matches.  When this is combined with
C<-v, --invert-match>, output the name of files with lines that don't match (a
bit absurdly but compatible with Unix -vl).  When this is combined with a
doubled C<-vv>, output the name of files with no matches.

=item -v

=item --vice-versa

=item --revert-match

=item --invert-match

Invert the sense of matching, to select non-matching lines.  Note that this
hides the standard option C<-v> which must be given as C<--verbose>.

=item -w I<filename>

=item --waste-file=I<filename>

An optional waste basket for collecting the rejected lines.  This is not only
for debugging your selection code, but also for splitting your input in two.
As with the normal output, you may modify $_ before returning false.

=back

    &sed s/foo/bar/ f1 f2 f3 -o outfile	# like sed s/foo/bar/ f1 f2 f3 >outfile
    &sed '$$_ = uc' f1 f2 f3 -o outfile	# like tr '[:lower:]' '[:upper:]' f1 f2 f3
    &grep '$$. % 3' f1 f2 f3 -o outfile	# eliminate every 3rd line
    &grep -c /match/i f1 f2 f3		# count the lines matching 'match' to STDOUT

Without pushing you to mass generate accessors, here's how you could do it by
simply putting a comment of RO or RW between each type and desired variable
name, all on one line.  The generated getter and optionally setter methods go
into the next found public or protected section:

    # Create get and maybe set method from "type /* R[OW] */ member;".
    sub cxx_accessors {
      $acc ||= '';		# Candidate for 5.10.0 state
      if( m!^\s*(.+?)\s*/\*\s*R([OW])\s*\*/\s*(.+?)\s*;! ) {
 	$acc .= "#line $.\n";	# Tell C++ where this came from
 	$acc .= "void set\u$3( const $1 &__tmp ) { $3 = __tmp; }"
 	  if $2 eq 'W';
 	$acc .= "const $1 &get\u$3() const { return $3; }\n";
      } elsif( /^\s*(?:public|protected)\s*:/ ) {
 	$_ .= $acc;
 	$acc = '';
      }
    }

    %.cc: %.cc.in		# Use &sed for I/O handling
  	&sed --sync-lines &cxx_accessors $(input) -o $(output)



=item &install I<[option ...] sourcefile destfile>

=item &install I<[option ...] sourcefile ... destdir>

=item &install --directory I<[option ...] directory ...>

Move or rename I<sourcefile> to I<destfile>, or multiple I<sourcefile>s to
I<destdir> with the same name.  This is the preferred way of transferring
build results to their final installation locations.

Every file system modification performed by C<&install> gets logged to the end
of the file pointed to by the environment variable C<$INSTALL_LOG>, or, if
that is not set but we are under a directory with a F<RootMakeppfile(.mk)>, to
a file of F<.install_log> in that directory, or else to that file in the
current directory.  You may want to delete the logfile before a series of
C<&install> invocations.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -v, --verbose>

=over

=item -c

=item --copy

Copy the files rather than moving them.  This is preferable, as it doesn't
force makepp to rebuild the file next time.  But it is not the default, for
compatibility with other install programs.

=item -d

=item --directory

In the third form form of this command create all the given directories and
any necessary parent directories.

=item -g I<group>

=item --group=I<group>

Change the group ownership of the destination files.  The group may be given
by name or numerically.

=item -l

=item --link

Try to link the files.  If that fails, copy.

=item --log=I<filename>

=item --logfile=I<filename>

Use I<filename> instead of normal logfile.

=item -m I<mode>

=item --mode=I<mode>

Sets I<mode> for all destination files or directories.  Mode must be an octal
string.

=item -o I<owner>

=item --owner=I<owner>

Change the ownership of the destination files.  The owner may be given by name
or numerically.

=item -r

=item --resolve

=item --resolve-symbolic

=item --resolve-symbolic-link

=item --resolve-symlink

=item -S

=item --symbolic

=item --symbolic-link

=item --symlink

Creates symbolic links instead of moving.  These options are passed to
L<C<&ln>|/ln_option_sourcefile_destfile> and are described there.

=item -s

=item --strip

Calls the C<strip> utility, which must be in the C<$PATH>, on the destination
files.

=back



=item &ln I<[option ...] sourcefile destfile>

=item &ln I<[option ...] sourcefile>

=item &ln I<[option ...] sourcefile ... destdir>

Link I<sourcefile> to I<destfile>, one I<sourcefile> to current directory or
multiple I<sourcefile>s to I<destdir> with the same name.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -v,
--verbose>

=over

=item -r

=item --resolve

=item --resolve-symbolic

=item --resolve-symbolic-link

=item --resolve-symlink

This is what you always wanted C<ln -s> to do.  Create symbolic rather than
hard links, not to the strings specified, but really to the given files.

=item -s

=item --symbolic

=item --symbolic-link

=item --symlink

Create symbolic rather than hard links.

=back

B<Note:> On various file or operating systems, this operation is not
supported.  Or it is, e.g. by Cygwin, but not understood by native Windows
compilers, if you use one.  For a makefile you can't change, to get at least
some sort of result, C<&ln> and C<&cp -l -s> can copy the files for you
instead (not directories though).  To achieve this, you need to export the
following variable before calling makepp:

=over

=item export MAKEPP_LN_CP=1

C<&ln> --resolve or --symbolic will copy the files instead of creating a
symbolic link.

=item export MAKEPP_LN_CP=2

C<&ln> will copy the files instead of creating a hard link.

=item export MAKEPP_LN_CP=3

All invocations of C<&ln> will copy the files instead of creating either kind
of link.

=back



=item &mkdir I<[option ...] directory ...>

Create the directories.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -v,
--verbose>

=over

=item -m I<mode>

=item --mode=I<mode>

Sets I<mode> for all created directories, irrespective of the umask.  Mode
must be an octal string.

=item -p

=item --parent

Also create any necessary parent directories.  Ignore directory creation
failure due to the directory already existing (even if it was created
concurrently by another process).

=back



=item &mv I<[option ...] sourcefile destfile>

=item &mv I<[option ...] sourcefile>

=item &mv I<[option ...] sourcefile ... destdir>

Move or rename I<sourcefile> to I<destfile>, one I<sourcefile> to current
directory or multiple I<sourcefile>s to I<destdir> with the same name.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -v,
--verbose>



=item &preprocess I<[option ...] variable=definition ... filename ...>

This preprocesses the files exactly the same way makepp does for makefiles.
This is more powerful than
L<C<&template>|/template_option_macro_definition_filename> but syntactically
not suited to files with lots of C<$>-signs, like Makefiles or scripts.

L<Conditional statements|makepp_statements/Conditionals>, as well as the
statements C<include>/C<_include> (which here neither build the file nor
search upwards), C<perl>/C<makeperl>/C<perl_begin> or C<sub>/C<makesub>, or
any statements you define within the file, are processed.  Empty and comment
lines are eliminated.

But, instead of learning build rules, it will output all remaining lines after
C<$(...)> expression expansion.  To prevent statement from being recognized
as such, you can precede them with an empty expression C<$()>.  The same
applies to lines you want to stay empty or which shall retain a leading
comment sign.  Likewise, if a trailing backslash is not to join a line with
the next, put C<$()> after it.

    A normal line gets output as is.
    A line with $(MAKEEXPRESSIONS) gets expanded and output.
    ifdef WANTTHIS      # does not get output whether defined or not
    might not get output
    endif
    include some files
    _include some files that might not exist # or -include
    $()include empty expression prevents keyword from being recognized.
    # Comment lines and empty lines get swallowed.

    $()# Unless they get masked with an empty expression.
    $()
    Empty expression prevents \$()
    backslash continuation from being recognized.

might give:

    A normal line gets output as is.
    A line with whatever gets expanded and output.
    lots of slurped in content here...
    include empty expression prevents keyword from being recognized.
    # Unless they get masked with an empty expression.

    Empty expression prevents \
    backslash continuation from being recognized.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -o,
--output=filename, -O, --outfail, -S, --synclines, -v, --verbose>

=over

=item -a

=item --assignment

Also treat assignments within the files as makepp would.  Alas such lines
can't be masked with an empty C<$()>, because it is legal to construct
variable names with expressions.  This additionally recognizes the statements
C<define>, C<export>/C<unexport> and C<override> (these can be masked with
C<$()>).

=item -h \\%I<hash>

=item --hashref=\\%I<hash>

This allows preallocation of the variable values, including long ones not easily
passed in a command.  The passed expression may be any Perl code that returns
a hash reference.  This is merged with any other variables passed to the command,
including from another C<--hashref> option.

=back



=item &rm I<[option ...] filename ...>

Delete files if you have directory write permission.  This is what Unix
C<rm -f> would delete, since it has a special protection for interactive use
not needed in a Makefile.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -v, --verbose>

=over

=item -f

=item --force

This prevents complaining about inexistent files.  That is a side effect this
option has in Unix, and the only one that makes sense here.

=item -m

=item --metainfo

In addition to the given files, this also deletes the meta information makepp
stores about them in the .makepp directory.  Thus makepp forgets all it ever
knew about the given files.  If the .makepp directory becomes empty after
this, it too is deleted.

=back

This will also delete given directories, but only if they are empty.  To
facilitate this, it will delete directories last, in the order of descending
depth.  So you can use C<**> expressions to delete whole hierarchies.  Here's
an example to be found in many top level make files.  Note that there is a
L<C<makeppclean>|makeppclean> utility that can do this more efficiently.

    $(phony cleanold):
 	&rm -fm $(only-stale **/*)

    $(phony clean): cleanold
 	&rm -f $(wildcard **/*.[ao])

    $(phony distclean): clean
 	&rm -fm $(only-targets **/*)



=item &sort I<[option ...] filename ...>

Sorts all files together in lexicographic order.  This is inefficient for
rather big files, because it happens completely in memory.  It will fail if
the combined size of all files exceeds the memory you are entitled to.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -i,
--inpipe=shellcommand, -I, --infail, -o, --output=filename, -O, --outfail,
--record-size=number, -s, --separator=string, -v, --verbose>

=over

=item -c I<perlcode>

=item --compare=I<perlcode>

I<perlcode> represents a Perl sort block, with the two sorting candidates in
C<$a> and C<$b>.

=item -n

=item --numeric

=item --numeric-sort

This sorts sorts numerically on the beginnings of records.  Leading whitespace
is skipped.  You can use C<--transform> and C<--detransform> if the numbers
are not at the beginning.

=item -r

=item --reverse

Output the results in the reverse order.  Note that this hides the standard
option C<-r> which must be given as C<--record-size>.

=item -t I<perlcode>

=item --transform=I<perlcode>

=item -d I<perlcode>

=item --detransform=I<perlcode>

If you have a complex code, sorting gets more and more expensive in proportion
to the number of records I<n>, because the code gets called O(I<n> log(I<n>))
times.  To avoid that, you can allow Perl to concentrate on sorting, by first
modifying the strings, such that complicated search criteria extraction
happens once per record, and modifying them back, once they are sorted.

If these options are given, the C<--transform> I<perlcode> gets mapped to the
records in C<$_> one after another, and can modify them.  After sorting, the
C<--detransform> I<perlcode> gets mapped to the modified records in C<$_> one
after another, and can modify them back.  You will usually use neither or both
of these options, unless you want to output modified lines.

Turning the strings into a structure of extracted sort criteria, which your
C<--compare> I<perlcode> can pick up is known as the Schwartzian Transform
(ST).  Packing everything into the string itself, so that no C<--compare>
I<perlcode> is needed, allowing the whole sorting to happen without performing
expensive Perl code, is known as the Guttmann-Rosler Transform (GRT).  You can
find tips by searching for those names on the web.

    # Expensively sort numerical expressions by value ($$ protects $ from makepp expansion)
    &sort --compare 'eval( $$a ) <=> eval( $$b )' $(input) -o >>$(output)

    # ST for case insensitive sorting
    &sort -t '[lc, $$_]' -c '$$a->[0] cmp $$b->[0]' -d '$$_->[1]' $(input) -o >>$(output)

    # GRT using modification functions defined elsewhere in the Makeppfile
    &sort -t &transform -d &detransform $(input) -o >>$(output)

=item -u

=item --uniq

=item --unique

After sorting, eliminate duplicates.  These are either identical lines, or if
the C<--compare> option is given, ones which that I<perlcode> reports as
equivalent.

=back



=item &template I<[option ...] macro=definition ... filename ...>

This is a macro preprocessor, not quite as powerful as the C preprocessor or
C<m4>.  See L<C<&preprocess>|/preprocess_option_variable_definition_filename>
for a more powerful alternative.  It was inspired by automake's macro
replacement in F<Makefile.am> and F<Makefile.in>.  But it goes beyond that.
Any normal text goes through unchanged.  Special constructs are by default
delimited with C<@>.  They must fit on one line unless you pass one of C<-r,
--record-size> or C<--separator>.

=over 4

=item @#I< comment >@

Note that despite borrowing from script C<#> line end comment syntax, this one
is an inline comment.

=item @I<MACRO>@

This construct is replaced by the value of the I<MACRO>.  Macro names must start
with a letter or underscore, followed by any number of letters, underscores,
minuses or dots.  Unlike in makepp names, underscore and minus are not
equivalent.

=item @I<MACRO>(I<arg1,arg2>...)@

Like the first one, but parametrized.  The args replace C<$1> through C<$9> or
C<${I<number>}> in the value.  Or, if the value is a Perl function, they are
passed as normal parameters.  The result then replaces the whole construct.
One level of macro nesting is possible in that the args in parenthesis may
contain plain C<@MACRO@> invocations, as in C<@f(@x@)@>, where C<@x@> gets
expanded before being replaced into the body of C<f>.

=item @include(I<filename>)@

This is the only predefined macro.  It is replaced by the &template-processed
content of the named file.  Like all macros this can occur in the middle of a
line.  Alas, because of that, C<-S, --synclines> ignores the file inclusion,
making everything seem to come from the including file.

=item @I<MACRO>=I<definition>@

=item @I<MACRO>?=I<definition>@

This defines a macro within the file.  This is replaced by nothing.
The second form only takes effect if the macro was not defined, presumably on
the command line.

=item @I<MACRO> { I<Perlcode> }@

This also defines a macro, the body of which is a Perl sub.  The arguments, if
there are any, get passed in as C<@_>.

=item @{ I<Perlcode> }@

This runs the I<Perlcode> immediately and gets replaced by the return value.

=back

So far we have only seen one syntax for embedding special things.  There is
another multiline syntax, and both allow a variation to suppress a newline.
These are the builtin syntaxes (which can be configured by options below).
Here I<SPECIAL> stands for any of the constructs shown above:

=over 4

=item @I<SPECIAL>@

=item @I<SPECIAL>@\

This can appear multiply anywhere on a line.  The variant immediately followed
by C<\> only works at the end of the line.  It also replaces the following
line break.

=item @@I<SPECIAL>@@ I<normal text> @@

=item @@I<SPECIAL>@@ I<normal text> @@\

This is like the previous one.  However the I<normal text>, which also gets
replaced, can span multiple lines.  You can put the special parts on comment
lines around source code that is only needed in an uninstalled script, to be
eliminated or replaced during the installation process:

    # @@# the next 2 lines will disappear @@
    echo You are running the uninstalled version of this script
    # @@
    # @@REPLAMCENT@@
    echo Something else will be here
    # @@

=back

A meaningless example showing the various possibilities:

    @m1=some definition@\
    @m2=foo $1 bar@\
    @middle_of_arg=iddl@\
    @m1@ @m2(m@middle_of_arg@e)@
    @@m2(many lines)@@
    ...
    @@ plain text 1 + 2 = @{ 1 + 2 }@

becomes

    some definition foo middle bar
    foo many lines bar plain text 1 + 2 = 3


L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f,
--force, -i, --inpipe=shellcommand, -I, --infail, -o, --output=filename, -O,
--outfail, -r, --record-size=number, --separator=string, -S, --synclines, -v,
--verbose>

=over

=item -d

=item --defined

Replace only instances of macros which are actually defined.  Without this
option the undefined ones will all be replaced by nothing.

=item -h \\%I<hash>

=item --hashref=\\%I<hash>

This allows preallocation of the macro values, including long ones not easily
passed in a command.  The passed expression may be any Perl code that returns
a hash reference.  This is merged with any other macros passed to the command,
including from another C<--hashref> option.  A hash value may also be a code
reference, in that case the function gets called, as with C<@macro {
I<Perlcode> }@> definitions.

=item -s I</prefix/suffix/>

=item --simple=I</prefix/suffix/>

Use I<prefix> and I<suffix> before and after I<SPECIAL> respectively instead
of C<@>.  The first character is the separator and need not be a slash.  These
values are Perl regexps.  You must not introduce grouping like C<(...)>, but
C<(?:...)> is ok.

=item -m I</prefix/suffix/afterprefix/[aftersuffix/]>

=item --multiline=I</prefix/suffix/afterprefix/[aftersuffix/]>

This redefines the alternate multiple line syntax.  Use I<prefix>, I<suffix>
and I<afterprefix> before and after I<SPECIAL> and at the end of the I<normal
text> respectively instead of C<@@>.  If I<aftersuffix> is also given, the
macro name must get repeated before it.  The first character is the separator
and need not be a slash.  E.g. XML-ish, to which you must add C<--defined> if
you want to preserve other tags, not defined by you:

    --defined --simple=|<|/>| --multiline=|<|>|</|>|

Or, better, use processing instructions C<< <?...?> >>, intended for such a
purpose:

    --defined --simple='_<\?_\?>_'

Or, if you want to combine this with C<&entity;> syntax for the simple macro
replacements (preserving numeric entities C<&#x263A;> which are not comments):

    --defined --simple='_&(?!#)_;_' --multiline='_<\?_(?=\?>)_\?>_'

This last one is a trick to obtain an alternate simple syntax: I<suffix> looks
forward to match the same as I<afterprefix>, making I<normal text> be empty.
I.e. this has the same effect as the simple regexps in the previous example.

=back



=item &touch I<[option ...] filename ...>

Updates the modification and access timestamps of each file to now.  If the
file doesn't exist, it gets created.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -v, --verbose>



=item &uninstall I<[option ...] [filename ...]>

Uninstall files previously installed by L<C<&install>|/install_option_sourcefile_destfile>.  The
I<filename>s are logfiles written by C<&install>.  If none are given, nor an
C<--inpipe> option, reads the default logfile of C<&install>.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -i,
--inpipe=shellcommand, -I, --infail, -v, --verbose>



=item &uniq I<[option ...] filename ...>

Discard all but one of successive equal lines.

L</Standard options>: C<-A, --args-file, --arguments-file=filename, -f, --force, -i,
--inpipe=shellcommand, -I, --infail, -o, --output=filename, -O, --outfail, -r,
--record-size=number, -s, --separator=string, -S, --synclines, -v, --verbose>

=over

=item -c I<perlcode>

=item --compare=I<perlcode>

This I<Perlcode> gets the previous and current lines in C<$a> and C<$b> and
shall return true if it considers the two lines equal.

=back

    &uniq --compare='lc( $$a ) eq lc $$b' $(inputs) -o $(output)

=back



=head2 Emulatable commands

Various things are not built in, but can be achieved with other commands:

=over

=item awk

Use L<C<&sed>|/grep_option_perlcode_filename>.


=item chgrp

=item chown

These commands are mostly not portable!  They will either quietly do nothing
or fail, depending on the system.  Generally only root may perform these
operations, which is why they are only available through the
L<C<&install>|/install_option_sourcefile_destfile> command.



=item cpp

Use L<C<&preprocess>|/preprocess_option_variable_definition_filename> or
L<C<&template>|/template_option_macro_definition_filename>.



=item date

Either of these partially does the same thing:

    &expr localtime
    &expr gmtime



=item false

Use L<C<&expr>|/expr_option_perlcode> with no argument or C<0>.



=item head

=item tail

You can achieve the same result with
L<C<&grep>|/grep_option_perlcode_filename> or L<C<&cut
--lines>|/cut_option_filename>:

    &grep 1..10 file		# first ten lines
    &grep 10..eof file		# all lines from tenth onwards
    &cut --lines -10..-1 file	# last ten lines

Note that 1..10 in C<&grep> is Perl's line number flip-flop operator, which
annoyingly starts at 1.  Don't start at 0, or the flip-flop will never become
true.



=item fmt

This is mentioned here since Perl provides a related functionality.  However I
had problems using the C<format> declaration in a makefile.  What does work is
the underlying C<formline> function.  E.g. to transform a csv file consisting
of names and prices to a tabular format:

    sub csv2txt {
      formline "\@<<<<<<<<<<<<<<< ^###########.##\n", split ',';
      $_ = $^A;
      $^A = '';
    }

    %.txt: %.csv
 	&sed &csv2txt $(input) -o $(output)



=item m4

Use L<C<&preprocess>|/preprocess_option_variable_definition_filename> or
L<C<&template>|/template_option_macro_definition_filename>.



=item rmdir

Use L<C<&rm>|/rm_option_filename>.



=item tr

Use L<C<&sed>|/grep_option_perlcode_filename>.


=back


=head1 AUTHOR

Daniel Pfeiffer (occitan@esperanto.org)