ここまでは、文字列を別の (固定された) 文字列に置換するという、最も単純なマクロ処理について説明してきました。マクロは、呼び出しごとに結果が異なるように定義することもできます。マクロの置換テキスト (マクロ define() の 2 番目の引数) は、そのマクロが実際に使用されるときに、$n の部分が n 番目の引数に置換されます。したがって、以下のように定義された bump() は、bump(x) の場合、x = x + 1 と同義になります。
define(bump, $1 = $1 + 1)
マクロには、任意の数の引数を指定できますが、個別にアクセスできるのは最初の 9 個 ($1 〜 $9) だけです。$0 はそのマクロ自身の名前です。すでに説明したように、指定されていない引数は、NULL 文字列に置換されます。そのため、以下のように、引数を連結するマクロを定義できます。
define(cat, $1$2$3$4$5$6$7$8$9)
つまり、cat (x、y、z) の結果は xyz になります。引数 $4 〜 $9 は、対応する引数が指定されていないため、NULL になります。
引数の収集時に引数の先頭にある引用符で囲まれていない空白文字、タブ、復帰改行は破棄されます。それ以外の空白はそのまま残ります。したがって、以下のマクロの場合には、a は b cとして定義されます。
define(a, b c)
引数はコンマによって区切られます。括弧で囲まれたコンマは引数の区切りとはみなされません。以下の例では、2 つの引数 a と (b,c) を使用しています。このように括弧で囲むことによって、コンマや括弧を引数として指定することができます。
define(a, (b,c))
以下の例では、 $(** は、その後で呼び出すマクロに指定された引数のリストに置換されます。その引数リストの中の各項目はコンマで区切られます。したがって、以下の例の結果は、1, 2 になります。
define(a, 1) define(b, 2) define(star, `$(**') star(a, b)
また、以下の例では m4 は star() の引数を収集するときに a と b から引用符を取り除き、star() を評価するときに a と b を展開するので、上記の例と結果は同じになります。
star(`a', `b')
$@ は、その後で呼び出すマクロの各引数が引用符で囲まれている以外は、$(** と同義です。したがって、以下の例では at() が評価されるときに引用符が再び引数に付けられるので、結果は a,b となります。
define(a, 1) define(b, 2) define(at, `$@') at(`a', `b')
$# は、その後で呼び出すマクロの引数の総数に置換されます。したがって、以下の例の結果は、3 になります。
define(sharp, `$#') sharp(1, 2, 3)
以下の場合は、結果は 1 になります。
sharp()
また以下の場合は、結果は 0 になります。
sharp
組み込みマクロの shift() は、1 つ目の引数以外のすべての引数を返します。1 つ目の引数以外の引数は、引用符で囲まれコンマで区切られて入力に返されます。最も単純な例を以下に示します。
shift(1, 2, 3)
この例の場合は、結果は 2、3 になります。$@ の場合と同様に、引用符で引数を囲むことによって、その引数の展開を遅らせることができます。したがって以下の例の場合は、shift() が評価されるときに引用符がまた引数に付けられるので、結果は b となります。
define(a, 100) define(b, 200) shift(`a', `b')