'tpp' is TiPi PreProcessor.

Preprocessor directives are lines of the form:
//# command ...
(there can be any spaces before "//", before and after "#").  In the
output, all lines matching this and with a recognized COMMAND are
omitted.

Comment lines are a special case with COMMAND equal to "//":
//# // ....

Empty lines:
//#


Define a macro (substitution is deferred):
//# def name := value

Define a macro (with immediate substitution):
//# def name = value

Define a macro from a numerical expression:
//# eval name op expression
with OP one of: =, +=, -=, *=, /=, %=, <<=, or >>=.

Spaces between NAME and VALUE and at the end of the line are ignored.
The VALUE field is the remaining part of the line after the NAME field
with leading and trailing spaces trimmed.  It is not possible to have
preprocessor comments after the VALUE filed (it is however allowed
after the EXPRESSION field of an '#eval' directive).  If VALUE is
omitted, an empty macro is defined, for instance: //# def name or //#
let name

To cancel definition of macro(s):
//# undef name1 [name2 ...]

Note that contrarily to C preprocessor, overwritting an existing
definition is not forbidden.  However, to avoid infinite substitution
loops, the "def" directive:
//# def name value
will substitute ${name} where it appears in VALUE.  This "feature" can be
exploited to append or prepend stuff to an existing macro.  For instance:
//# def list a
//# def list ${list}, b
//# def list ${list}, c
wil result a macro named "list" with contents "a, b, c".  Obviously, the
same result can be obtained with the "let" directive.  But a more
fancy result is obtained with:
//# def list ${prefix}1
//# def list ${list},${prefix}2
//# def list ${list},${prefix}3
which yields a macro "list" whose contents is "${prefix}1,${prefix}2,${prefix}3"
and can be used as a template to make lists after substitution:
//# let prefix foo
//# let FooList ${list}
//# let prefix bar
//# let BarList ${list}
yields "foo1,foo2,foo3" and "bar1,bar2,bar3" for the respective contents
of macros FooList and BarList.

With this kind of trick it is also possible to mimic the behavior of
macros with arguments (even though it is less readable).

Nested test:
   //# if EXPR1 // optional comment
   some text
   //# elif EXPR2 // optional comment
   some other text
   //# elif EXPR3 // optional comment
   yet some other text
   //# else // optional comment
   finally some text
   //# end // optional comment


Conditional loop:
    //# while EXPR // some optional comment
    ...
    //# end // another optional comment

Loop over a list or a range of values:

    //# for NAME in EXPR // some optional comment
    ...
    //# end // another optional comment

The body of the loop is repeated with macro NAME set to every values
in EXPR.  EXPR is recursively expanded and the result can be empty (the
body of the loop is just skipped), or a range (see below) or a list
of values.

A range of values has the form:

    FIRST : LAST

or

    FIRST : LAST : STEP

where (after macro expansion) FIRST, LAST and STEP are integers, if
omitted, STEP equals 1.  A zero-STEP is forbidden.  Numerical
expressions are not yet supported for these fields but you can use the
'#eval' directive to compute the range parameters.  For instance:

    //# eval last = ${x} + 3*${y}
    //# for i in 0 : ${last}
    ...
    //# end


Include another source (note that macro expansion is performed on the line):

    //#include <name>

or

    //#include "name"

A restriction is that '#if' ... #elif' ... '#end' and '#while' ... '#end'
blocks must be open and closed in a single included file.

Expressions involve integer arithmetic and tests:

  defined(name)         check whether macro NAME is defined
  ! defined(name)       check whether macro NAME is not defined
  expr1 || expr2        logical OR (with lazzy evaluation)
  expr1 && expr2        logical AND (with lazzy evaluation)
  "text"                litteral text for string comparison

Note that macros are recursively substituted if they appear in an expression
including whithin the double quotes of a string.


PREDEFINED MACROS
=================

The following macros are automatically defined (and are read-only):
  ${__FILE__}     yields the current input file name
  ${__LINE__}     yields the current line number in the current input file name
  ${__SPACE__}    yields an ordinary space
  ${__NEWLINE__}  yields a newline
  ${}             yields an ordinary dollar sign


MESSAGES
========

Print TEXT (after recursive macro substitution) on standard output:

//# echo TEXT

Print TEXT (after recursive macro substitution) on standard error output:

//# warn TEXT

It may be useful to examine the contents of some macros (without a
fully recursive expansion).  To that end, the following directive
prints TEXT (after a single round of macro substitution) on standard
error output:

//# debug TEXT

Print TEXT (after recursive macro substitution) on the standard error output and
raise an error:

//# error TEXT


EVOLUTION
=========

1. It may be useful to customize the syntax in order to accomodate to
   various programming languages.  For instance:

   @name@       to interpolate a macro
   @@           for a single @
   #@ command   for preprocessor directives

2. Macros with arguments (spaces stripped).

   ${macro(arg1,arg2,...)}

3. String functions (like predefined macros).

   ${substr(str,i1,i2,subs)}
   ${strmatch(string,pattern)}
   ...

4. Comments after expressions (tests or numerical expressions)
