Provided by: makepp_2.0.98.5-2.1_all bug

NAME

       makepp_builtins -- Builtin commands in makepp

DESCRIPTION

       A: awk,  C: &cat,
         chgrp,
         &chmod,
         chown,
         &cp,
         cpp,
         &cut,  D: date,  E: &echo,
         &expr,  F: false,
         fmt,  G: &grep,  H: head,  I: &install,  L: &ln,  M: m4,
         &mkdir,
         &mv,  P: &perl,
         &preprocess,
         &printf,  R: &rm,
         rmdir,  S: &sed,
         &sort,  T: tail,
         &template,
         &touch,
         tr,  U: &uninstall,
         &uniq,  Y: &yes

       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 "-i" and "-o" below instead).

       These commands start with "&", 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 "run".

       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 "define" statement.

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

       When these commands are not indented as rule actions, they get performed 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 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 "-ab" instead of "-a -b".  In the long form arguments may
       be given either glued on with an "=" sign or separately.  In the short form they may be given either
       glued on directly or separately.

   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 "&cut -f"):

       -A filename
       --args-file=filename
       --arguments-file=filename
           Read the file and parse it as possibly quoted whitespace- and/or newline-separated options.

       -f
       --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 "-o, --output=filename" option if
           it is to have any effect on that.

       -i shellcommand
       --inpipe=shellcommand
           Start the Shell command(s) and pipe the output into the builtin.  There may optionally be a  trailing
           "|"  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 "-" as a filename for
           the pipe output.  The pipe is emptied, but, unless you also  give  "--infail",  the  command  is  not
           waited  for,  so  it  can  terminate  in  parallel.   This  option  is  necessary because there is no
           redirection syntax.

       -I
       --infail
           If an "--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.

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

           filename
           >filename
               Simply write to file.

           >>filename
               Append to (not necessarily) existing file.

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

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

           This option is necessary because there is no redirection syntax.

       -O
       --outfail
           If an "--output" Shell command fails, that also causes the current builtin to fail.

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

       -s string
       --separator=string
           Locally sets $/ for the current builtin.  This splits input on string rather than line by line.

       -S
       --synclines
           Generate "#line ""NO"" """FILE"""" and "#line ""NO" lines, understood by many C-like languages.

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

   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 "&echo -n" or
       "&mkdir -p", and saving you the hassle of finding the path  to  &install  and  figuring  out  its  wildly
       varying  options.   In  a  compilation  environment,  it's useful to have the "--synclines" option, which
       normally only "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. "expr", "sed" ...), or complex options for specifying fields, delimiters,  columns  (e.g.
       "cut", "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 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  &template  command  to
       patch in the configuration, but not let makepp notice.

       &cat [option ...] filename ...
           Concatenates all the files into a single one.

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

       &chmod [option ...] mode filename ...
           Sets mode for all given files.  Mode must be an octal string.

           "Standard options": "-A, --args-file, --arguments-file=filename, -v, --verbose"

       &cp [option ...] sourcefile destfile
       &cp [option ...] sourcefile
       &cp [option ...] sourcefile ... destdir
           Copy  sourcefile  to destfile, one sourcefile to current directory or multiple sourcefiles to destdir
           with the same name.

           "Standard options": "-A, --args-file, --arguments-file=filename, -f, --force, -v, --verbose"

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

           -s
           --symbolic
           --symbolic-link
           --symlink
               Try to symbolically link the files.  If that fails, copy.

           See the note under &ln.

       &cut [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.

           "Standard options": "-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"

           -c list
           --characters=list
               Print  all the characters specified by list.  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 "cut", the order you request is respected.

               Unlike  in  Perl's  slice  operator  where a ".." range must be either positive or negative, &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. "1..-2" means everything but the
               first (0) and the last (-1).

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

           -d string
           --delimiter=string
               Set a new delimiter for input fields and output.  Unlike Unix "cut", this may have any length.

           -E
           --noescape
               Treat "\" as normal literals for "-p, --printf=format".

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

           -l list
           --lines=list
               Print  all  the lines specified by list.  List is as described under "-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.

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

           -p format
           --printf=format
               Apply format (with \escapes) to all fields or characters.

           -s
           --only-delimited
               Print only lines containing delimiters.

               &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

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

           \cA Is a control character ^A.

           \u  Upcases the following letter.

           \U  Upcases the rest, or up to the next "\E" or "\L" if found.

           \xHH, \x{HHHH}
               Is the character value of the given Hex code.  Note that numeric codes are not portable to EBCDIC
               platforms!

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

           "Standard options": "-A, --args-file, --arguments-file=filename, -f, --force, -o,  --output=filename,
           -O, --outfail, -v, --verbose"

           -E
           --noescape
               Treat "\" as normal literals.

           -n
           --nonewline
               Do not add a newline after the last string.  (Not understood by &printf.)

       &expr [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 "*", "(" or ">" 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 "expr" -- Perl's index function starts at 0
           (false) and returns -1 (true) for failure.

           "Standard options": "-A, --args-file, --arguments-file=filename, -f, --force, -o,  --output=filename,
           -O, --outfail, -v, --verbose"

           -n
           --nonewline
               Do not add a newline after the output.

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

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

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

           "Standard    options":    "-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 "--synclines" only makes sence with &perl if you use &Mpp::Cmds::print to output $_.  Only
           &grep has extra options:

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

           -l
           --list
           --files-with-matches
               Output  only  the  name  of  those  files  with  matches.   When  this  is  combined  with   "-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 "-vv", output the name of  files
               with no matches.

           -v
           --vice-versa
           --revert-match
           --invert-match
               Invert  the  sense  of matching, to select non-matching lines.  Note that this hides the standard
               option "-v" which must be given as "--verbose".

           -w filename
           --waste-file=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.

               &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)

       &install [option ...] sourcefile destfile
       &install [option ...] sourcefile ... destdir
       &install --directory [option ...] directory ...
           Move or rename sourcefile to destfile, or multiple sourcefiles to 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 &install gets logged to the end of the file pointed to by
           the  environment  variable  $INSTALL_LOG,  or, if that is not set but we are under a directory with a
           RootMakeppfile(.mk), to a file of .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 &install invocations.

           "Standard options": "-A, --args-file, --arguments-file=filename, -v, --verbose"

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

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

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

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

           --log=filename
           --logfile=filename
               Use filename instead of normal logfile.

           -m mode
           --mode=mode
               Sets mode for all destination files or directories.  Mode must be an octal string.

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

           -r
           --resolve
           --resolve-symbolic
           --resolve-symbolic-link
           --resolve-symlink
           -S
           --symbolic
           --symbolic-link
           --symlink
               Creates symbolic links instead of moving.  These options are passed  to  &ln  and  are  described
               there.

           -s
           --strip
               Calls the "strip" utility, which must be in the $PATH, on the destination files.

       &ln [option ...] sourcefile destfile
       &ln [option ...] sourcefile
       &ln [option ...] sourcefile ... destdir
           Link  sourcefile  to destfile, one sourcefile to current directory or multiple sourcefiles to destdir
           with the same name.

           "Standard options": "-A, --args-file, --arguments-file=filename, -f, --force, -v, --verbose"

           -r
           --resolve
           --resolve-symbolic
           --resolve-symbolic-link
           --resolve-symlink
               This is what you always wanted "ln -s" to do.  Create symbolic rather than hard links, not to the
               strings specified, but really to the given files.

           -s
           --symbolic
           --symbolic-link
           --symlink
               Create symbolic rather than hard links.

           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, &ln and "&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:

           export MAKEPP_LN_CP=1
               &ln --resolve or --symbolic will copy the files instead of creating a symbolic link.

           export MAKEPP_LN_CP=2
               &ln will copy the files instead of creating a hard link.

           export MAKEPP_LN_CP=3
               All invocations of &ln will copy the files instead of creating either kind of link.

       &mkdir [option ...] directory ...
           Create the directories.

           "Standard options": "-A, --args-file, --arguments-file=filename, -f, --force, -v, --verbose"

           -m mode
           --mode=mode
               Sets mode for all created directories, irrespective of the umask.  Mode must be an octal string.

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

       &mv [option ...] sourcefile destfile
       &mv [option ...] sourcefile
       &mv [option ...] sourcefile ... destdir
           Move or rename sourcefile to destfile, one sourcefile to current directory or multiple sourcefiles to
           destdir with the same name.

           "Standard options": "-A, --args-file, --arguments-file=filename, -f, --force, -v, --verbose"

       &preprocess [option ...] variable=definition ... filename ...
           This  preprocesses  the  files exactly the same way makepp does for makefiles.  This is more powerful
           than &template but syntactically not suited to files  with  lots  of  "$"-signs,  like  Makefiles  or
           scripts.

           Conditional  statements, as well as the statements "include"/"_include" (which here neither build the
           file nor search upwards), "perl"/"makeperl"/"perl_begin" or "sub"/"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 "$(...)" expression
           expansion.  To prevent statement from being recognized as such, you can precede them  with  an  empty
           expression  "$()".   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 "$()" 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.

           "Standard options": "-A, --args-file, --arguments-file=filename, -f, --force, -o,  --output=filename,
           -O, --outfail, -S, --synclines, -v, --verbose"

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

           -h \\%hash
           --hashref=\\%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 "--hashref" option.

       &rm [option ...] filename ...
           Delete files if you have directory write permission.  This is what Unix "rm -f" would  delete,  since
           it has a special protection for interactive use not needed in a Makefile.

           "Standard options": "-A, --args-file, --arguments-file=filename, -v, --verbose"

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

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

           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 "**" expressions to delete
           whole hierarchies.  Here's an example to be found in many top level make files.  Note that there is a
           "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 **/*)

       &sort [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.

           "Standard   options":    "-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"

           -c perlcode
           --compare=perlcode
               perlcode represents a Perl sort block, with the two sorting candidates in $a and $b.

           -n
           --numeric
           --numeric-sort
               This sorts sorts numerically on the beginnings of records.  Leading whitespace is  skipped.   You
               can use "--transform" and "--detransform" if the numbers are not at the beginning.

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

           -t perlcode
           --transform=perlcode
           -d perlcode
           --detransform=perlcode
               If you have a complex code, sorting gets more and more expensive in proportion to the  number  of
               records  n, because the code gets called O(n log(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 "--transform" perlcode gets mapped to the records in $_ one after
               another,  and  can  modify  them.  After sorting, the "--detransform" perlcode gets mapped to the
               modified records in $_ 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 "--compare"  perlcode
               can  pick  up  is  known  as  the Schwartzian Transform (ST).  Packing everything into the string
               itself, so that no "--compare" 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)

           -u
           --uniq
           --unique
               After sorting, eliminate duplicates.  These are either identical lines,  or  if  the  "--compare"
               option is given, ones which that perlcode reports as equivalent.

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

           @# comment @
               Note  that  despite  borrowing  from  script  "#"  line end comment syntax, this one is an inline
               comment.

           @MACRO@
               This construct is replaced by the value of the 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.

           @MACRO(arg1,arg2...)@
               Like the first one, but parametrized.  The args replace $1  through  $9  or  "${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 "@MACRO@" invocations, as in "@f(@x@)@", where "@x@" gets expanded
               before being replaced into the body of "f".

           @include(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, "-S,
               --synclines" ignores the file inclusion, making everything seem to come from the including file.

           @MACRO=definition@
           @MACRO?=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.

           @MACRO { Perlcode }@
               This also defines a macro, the body of which is a Perl sub.  The arguments, if there are any, get
               passed in as @_.

           @{ Perlcode }@
               This runs the Perlcode immediately and gets replaced by the return value.

           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 SPECIAL stands for any of the constructs shown above:

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

           @@SPECIAL@@ Normal text @@
           @@SPECIAL@@ Normal text @@\
               This is like the previous one.  However the 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
                   # @@

           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

           "Standard   options":    "-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"

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

           -h \\%hash
           --hashref=\\%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 "--hashref" option.  A
               hash value may also be a code reference, in that case the function gets called, as with "@macro {
               Perlcode }@" definitions.

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

           -m /prefix/suffix/afterprefix/[aftersuffix/]
           --multiline=/prefix/suffix/afterprefix/[aftersuffix/]
               Use prefix, suffix and afterprefix before  and  after  SPECIAL  and  at  the  end  of  the  block
               respectively  instead  of  "@@".   If 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.  an  XML-ish,  to
               which you must add "--defined" if you want to preserve other tags, not defined by you:

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

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

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

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

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

       &touch [option ...] filename ...
           Updates the modification and access timestamps of each file to now.  If the file  doesn't  exist,  it
           gets created.

           "Standard options": "-A, --args-file, --arguments-file=filename, -v, --verbose"

       &uninstall [option ...] [filename ...]
           Uninstall  files  previously  installed by &install.  The filenames are logfiles written by &install.
           If none are given, nor an "--inpipe" option, reads the default logfile of &install.

           "Standard options":  "-A,  --args-file,  --arguments-file=filename,  -i,  --inpipe=shellcommand,  -I,
           --infail, -v, --verbose"

       &uniq [option ...] filename ...
           Discard all but one of successive equal lines.

           "Standard    options":    "-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"

           -c perlcode
           --compare=perlcode
               This  Perlcode  gets  the  previous  and  current  lines in $a and $b and shall return true if it
               considers the two lines equal.

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

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

       awk Use &sed.

       chgrp
       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 &install command.

       cpp Use &preprocess or &template.

       date
           Either of these partially does the same thing:

               &expr localtime
               &expr gmtime

       false
           Use &expr with no argument or 0.

       head
       tail
           You can achieve the same result with &grep or "&cut --lines":

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

       fmt This is mentioned here since Perl provides a related functionality.  However I had problems using the
           "format"  declaration  in a makefile.  What does work is the underlying "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)

       m4  Use &preprocess or &template.

       rmdir
           Use &rm.

       tr  Use &sed.

AUTHOR

       Daniel Pfeiffer (occitan@esperanto.org)

perl v5.32.0                                       2021-01-06                                 MAKEPP_BUILTINS(1)