Programming Utilities Guide

Arguments

So far you have been given information about the simplest form of macro processing, that is, replacing one string with another (fixed) string. Macros can also be defined so that different invocations have different results. In the replacement text for a macro (the second argument of its define()), any occurrence of $n is replaced by the nth argument when the macro is actually used. So the macro bump(), defined as

define(bump, $1 = $1 + 1)

is equivalent to x = x + 1 for bump(x).

A macro can have as many arguments as you want, but only the first nine are accessible individually, $1 through $9. $0 refers to the macro name itself. As noted, arguments that are not supplied are replaced by null strings, so a macro can be defined that concatenates its arguments:

define(cat, $1$2$3$4$5$6$7$8$9)

That is, cat(x, y, z) is equivalent to xyz. Arguments $4 through $9 are null since no corresponding arguments were provided.

Leading unquoted blanks, tabs, or newlines that occur during argument collection are discarded. All other white space is retained, so

define(a, b c)

defines a to be b c.

Arguments are separated by commas. A comma "protected" by parentheses does not terminate an argument. The following example has two arguments, a and (b,c). You can specify a comma or parenthesis as an argument by quoting it:

define(a, (b,c))

In the following example, $(** is replaced by a list of the arguments given to the macro in a subsequent invocation. The listed arguments are separated by commas. So

define(a, 1) 
define(b, 2) 
define(star, `$(**') 
star(a, b)

gives the result 1,2. So does

star(`a', `b')

because m4 strips the quotes from a and b as it collects the arguments of star(), then expands a and b when it evaluates star().

$@ is identical to $(** except that each argument in the subsequent invocation is quoted. That is,

define(a, 1) 
define(b, 2) 
define(at, `$@') 
at(`a', `b')

gives the result a,b because the quotes are put back on the arguments when at() is evaluated.

$# is replaced by the number of arguments in the subsequent invocation. So

define(sharp, `$#') 
sharp(1, 2, 3)

gives the result 3,

sharp()

gives the result 1, and

sharp

gives the result 0.

The built-in shift() returns all but its first argument. The other arguments are quoted and returned to the input with commas between. The simplest case

shift(1, 2, 3)

gives 2,3. As with $@, you can delay the expansion of the arguments by quoting them, so

define(a, 100) 
define(b, 200) 
shift(`a', `b')

gives the result b because the quotes are put back on the arguments when shift() is evaluated.