マクロはいくつかの異なる方法で定義、再定義、削除することができます。 また現在の定義を失うことなく一時的にマクロを再定義しておいて、 後で元の定義に戻すこともできます。
通常はマクロを定義したり再定義するときは、
組み込みマクロdefine
を使います。
define(name [, expansion])
これはnameがexpansionに展開されるように定義します。 もしexpansionが与えられなかったときは、空文字列だと見なされます。
define
は展開されると消滅します。
次の例では、マクロfooが`Hello World.'に展開されるように 定義しています。
define(`foo', `Hello world.') => foo =>Hello world.
出力に空行がある理由は、マクロ定義の直後にある改行文字が
定義の一部ではなく、従って出力にそのままコピーされるためです。
これはdnl
マクロを使うことで避けることができます。
詳しくはSee section 入力中の空白(whitespace)を削除するを参照してください。
マクロdefine
は引数が与えられたときだけ認識されます。
マクロは引数を取ることができます。n番目の引数は$n
として
展開用テキストの中で示し、マクロが展開されるときにn番目の
実引数(actual argument)に置き換えられます。
次の例は2つの引数を取るマクロです。2つの引数の順番を単純に交換します。
define(`exch', `$2, $1') => exch(arg1, arg2) =>arg2, arg1
これはdefine
への引数の順番を逆にしたいときなどに使えます。
define(`exch', `$2, $1') => define(exch(``expansion text'', ``macro'')) => macro =>expansion text
二重になった引用符の説明についてはSee section マクロの引数をクォートするを参照してください。
GNU m4
では`$'に続く数字は複数の桁でもよいので、
マクロはいくつでも引数を取ることができます。
これと違いUNIXのm4
では1桁の数字しか認識されません。
特殊なケースとして、0番目の引数$0
は常に現在展開されているマクロの名前
となります。
define(`test', ``Macro name: $0'') => test =>Macro name: test
クォートされたテキストを展開後のテキストに含めたい時は、 クォートは入れ子にできることを思い出しましょう。したがって、
define(`foo', `This is macro `foo'.') => foo =>This is macro foo.
展開されたテキストに含まれる`foo'は、 クォートされた文字列(quoted string)であり名前(name)ではないので、 再走査によって展開はされず、 引用符がはぎ取られるだけです(see section 字句・構文解析の規則)。
与えられた実引数(actual arguments)の個数や全ての実引数をまとめて表すための 特別な表記方法があります。
マクロを呼び出すときに与えられた実引数の個数は、
展開用テキストの中で$#
として表します。
したがって与えられた実引数の個数を表示するマクロは次のようになります。
define(`nargs', `$#') => nargs =>0 nargs() =>1 nargs(arg1, arg2, arg3) =>3
展開用テキストの中で$*
という表記をすることで、
全ての実引数を(クォートはせずに)コンマで区切ったものを表すことができます。
define(`echo', `$*') => echo(arg1, arg2, arg3 , arg4) =>arg1,arg2,arg3 ,arg4
引数をそれぞれクォートしなければならないことがよくありますが、
そんなときは$@
という表記を使います。
これは各引数がクォートされることを除けば$*
と同じです。
define(`echo', `$@') => echo(arg1, arg2, arg3 , arg4) =>arg1,arg2,arg3 ,arg4
引用符はどこに行ったのでしょうか? もちろん展開後のテキストを
再走査したときにm4
が食べてしまったのです。
違いを見るために、次のようにしてみましょう。
define(`echo1', `$*') => define(`echo2', `$@') => define(`foo', `This is macro `foo'.') => echo1(foo) =>This is macro This is macro foo.. echo2(foo) =>This is macro foo.
これが理解できないときはSee section マクロの呼び出しをトレースするを参照してください。
展開用テキストに記号`$'が存在し、それに続く部分がm4
に理解できる
ものでないときは、`$'は他のテキストと同じように
マクロ展開後のテキストへ単にコピーされます。
define(`foo', `$$$ hello $$$') => foo =>$$$ hello $$$
マクロを`$12'などに展開させたいときは、
$
の後に一組の引用符を置きます。
これによって、m4
がその$
記号を引数への参照だと解釈してまうのを
防ぐことができます。
undefine
を使えばマクロの定義を削除することができます。
undefine(name)
これによってマクロnameが削除されます。 展開されてしまうのを防ぐためにマクロの名前は必ずクォートしなくてはなりません。
undefine
は展開されると消滅します。
foo =>foo define(`foo', `expansion text') => foo =>expansion text undefine(`foo') => foo =>foo
nameがマクロとして定義されていなくても問題はありません。
その場合はundefine
が何もしないだけです。
undefine
は引数が与えられたときだけ認識されます。
すでに定義済みのマクロの名前を替えることができます。
それには組み込みマクロdefn
が必要となります。
defn(name)
これはnameの定義をクォートしたものに展開されます。 引数が定義済みのマクロでないときは展開されると消滅します。
nameがユーザ定義マクロの場合、
クォートされた定義とは単にクォートされた展開用テキストのことです。
nameが組み込みマクロの場合、
展開後のテキストは、m4
の内部にある組み込みマクロの定義を指す
特殊なトークンとなります。
このトークンは、define
(および pushdef
)
の第2引数としてのみ意味を持ち、その他の文脈では無視されます。
通常の使用方法は、次の例でundefine
の名前をzap
に換える方法を
見るのが一番分かりやすいでしょう。
define(`zap', defn(`undefine')) => zap(`undefine') => undefine(`zap') =>undefine(zap)
このようにdefn
はユーザ定義マクロの定義や
組み込みマクロの定義をコピーするために使うことができます。
たとえ元のマクロが削除されても、もう一方の名前を使って
定義にアクセスすることができます。
defn
は引数が与えられたときだけ認識されます。
あるマクロを一時的に再定義しておき、後で元の定義に戻すことができます。
それにはdefine
とundefine
に良く似た、
組み込みマクロpushdef
とpopdef
を使います。
pushdef(name [, expansion]) popdef(name)
これらのマクロはスタック(stack)に似た仕組みで機能します。
pushdef
は、あるマクロを一時的に再定義します。
このときnameの前の定義は、新しい定義によって置き換えられる前に
保存されます。もし前の定義が存在しない場合は、
pushdef
はdefine
とまったく同じように機能します。
あるマクロに複数の定義が存在する場合(その中の一つだけがアクセス可能です)、
popdef
を使って一番上の定義を削除することができます。
前の定義が無い場合、popdef
はundefine
のように機能します。
define(`foo', `Expansion one.') => foo =>Expansion one. pushdef(`foo', `Expansion two.') => foo =>Expansion two. popdef(`foo') => foo =>Expansion one. popdef(`foo') => foo =>foo
define
によって、複数の定義を持つマクロを再定義したときは、
一番上の定義が新しい定義で置き換えられます。
undefine
によって定義を削除するときは、
一番上のもの一つだけではなく、すべての定義が削除されます。
define(`foo', `Expansion one.') => foo =>Expansion one. pushdef(`foo', `Expansion two.') => foo =>Expansion two. define(`foo', `Second expansion two.') => foo =>Second expansion two. undefine(`foo') => foo =>foo
pushdef
とdefn
を使えば、組み込みマクロを一時的に再定義することが
できます。
マクロpushdef
とpopdef
は引数が与えられたときだけ認識されます。
indir
を使うと、どんなマクロでも間接的に呼び出すことができます。
indir(name, ...)
indir
はマクロnameを残りの引数と共に呼び出します。
これを"不正な"名前を持つマクロを呼ぶのに使うことができます(define
はそういう名前でも定義できます。)
define(`$$internal$macro', `Internal macro (name `$0')') => $$internal$macro =>$$internal$macro indir(`$$internal$macro') =>Internal macro (name $$internal$macro)
ここでの要点は、大きなマクロ・パッケージで、
間違って呼ばれてしまうことのないマクロを定義できるということです。
それらは組み込みマクロindir
によってだけ呼びだすことができます。
builtin
を使えば、組み込みマクロを間接的に呼び出すことができます。
builtin(name, ...)
これは組み込みマクロnameを、残りの引数と共に呼び出します。 たとえnameに本来の定義を隠している別の定義が与えられていても、 本来の定義を呼び出します。
マクロbuiltin
は引数が与えられたときだけ認識されます。
Go to the first, previous, next, last section, table of contents.