.im man.im
.NM macro expand string definitions, with arguments
.SY macro
.FU
.ital macro
reads its input, looking for macro definitions of the form
.Q1
    define(ident,string)
.Q2
and writes its output with each subsequent instance of the identifier
.ital ident
replaced by the arbitrary sequence of characters
.ital string.

Within a replacement string, any dollar sign
.ital $
followed by a digit is replaced by an argument corresponding to that digit.
Arguments are written as a parenthesized list of strings following an
instance of the identifier, e.g.,
.Q1
ident(arg1,arg2,...)
.Q2
So
.ital $1
is replaced in the replacement string by
.ital arg1,
.ital $2
by
.ital arg2,
and so on;
.ital $0
is replaced by
.ital ident.
Missing arguments are taken as null strings;
extra arguments are ignored.

The replacement string in a definition is expanded before the definition
occurs, except that any sequence of characters between a grave
.ital `
and a balancing apostrophe
.ital \'
is taken literally, with the grave and apostrophe removed.
Thus, it is possible to make an alias for define by writing
.Q1
    define(def,`define($1,$2)')
.Q2

Additional predefined built-ins
are:

.ital ifelse(a,b,c,d)
is replaced by the string
.ital c
if the string
.ital a
exactly matches the string
.ital b;
otherwise it is replaced by the string
.ital d.

.ital expr(expression)
is replaced by the decimal string representation of the numeric value of
.ital expression.
For correct operation, the expression must consist of
parentheses, integer operands written as decimal digit strings, and
the operators
.ital +,
.ital -,
.ital *,
.ital /
(integer division), and
.ital %
(remainder).
Multiplication and division bind tighter than addition and subtraction,
but parentheses may be used to alter this order.

.ital substr(s,m,n)
is replaced by the substring of
.ital s
starting at location
.ital m
(counting from one)
and continuing at most
.ital n
characters.
If
.ital n
is omitted, it is taken as a very large number;
if
.ital m
is outside the string, the replacement string is null.
.ital m
and
.ital n
may be expressions suitable for
.ital expr.

.ital len(s)
is replaced by the string representing the length of its argument
in characters.

.ital changeq(xy)
changes the quote characters
to
.ital x
and
.ital y.
.ital changeq()
changes them back to
.ital `
and
.ital \'.

Each replacement string is rescanned for further possible
replacements, permitting multi-level definitions to be expanded to final
form.
.EG
The macro
.ital len
could be written in terms of the other built-ins as:
.Q1
define(`len',`ifelse($1,,0,`expr(1+len(substr($1,2)))')')
.Q2
.BUGS
A recursive definition of the form
.ital define(x,x)
will cause an infinite loop.
.br
Expression evaluation is fragile.
There is no unary minus.
.br
It is unwise to use parentheses as quote characters.
