次: Changequote is Evil, 前: One Macro Call, 上: M4 Quotation
これ以降の例では,以下のマクロを使用しています.
define([car], [$1])
define([active], [ACT, IVE])
define([array], [int tab[10]])
追加の埋め込まれたマクロ呼び出しは,それぞれ興味深い引用符について,その 他の可能性を導き出します.
car(active)
=>ACT
car([active])
=>ACT, IVE
car([[active]])
=>active
最初の状況では,トップレベルではcarの引数を探し,`active' が
見つかります.M4はマクロを適用する前のその引数と等価なので,
`active'は展開され,結果として以下のようになります.
car(ACT, IVE)
=>ACT
二番目の状況では,トップレベルはcarの最初で唯一の引数として
`active'を与えるので,結果として以下のようになります.
active
=>ACT, IVE
すなわち,マクロが呼び出された後で,引数が評価されます.三番目の
状況では,carは`[active]'を受けとり,結果として以下のように
なります.
[active]
=>active
上記で見たものと同じですね.
より現実的な例を適用して,上記の例に与えてみましょう.
car(int tab[10];)
=>int tab10;
car([int tab[10];])
=>int tab10;
car([[int tab[10];]])
=>int tab[10];
う〜ん? 最初の状況は簡単に理解できますが,なぜ二番目が間違っていて,三
番目は正しいのでしょうか?それを理解するために,M4がマクロを展開した後,
結果として生じるテキストがすぐにマクロを展開に従って引用符が取り除かれる
ことを知っておく必要があります.これは,引用符の削除が二回行なわれること
を意味します — 最初に引数としてcarマクロに渡されるとき,二回目
はcarマクロが最初の引数を展開するときです.
Autoconfマクロcarの作者として,ユーザがcarの引数を二重の引
用符にする必要があることは間違っていると考えるようにし,マクロを修
正してください.引用符で囲まれているcarに対して,それを
qarと呼ぶことにしましょう.
define([qar], [[$1]])
そして,qarが適切に修正されていることを調査してみます.
qar([int tab[10];])
=>int tab[10];
あぁ!そうした方が良さそうですね.
しかし,自分が行なったことに注意してください.現在その引数はリテラル文字 列ですが,引数を展開した結果をユーザが使用したい場合,引用符で囲ま れていないマクロを使用する必要があります.
qar(active)
=>ACT
carを用いて行なっていたことを再生成したい状況を考えます.
car([active])
=>ACT, IVE
まだ駄目ですね.cppマクロの組を生成するマクロを使用したい状況を考
えてみましょう.
define([my_includes], [#include <stdio.h>])
car([my_includes])
=>#include <stdio.h>
qar(my_includes)
error-->EOF in argument list
このマクロqarは,引数を二重に引用符で囲むので,ユーザはマクロの呼
び出しを引用符で囲まないままにしておくよう強制されるので,それは危険です.
カンマとその他のアクティブなシンボルは,マクロに渡される前にM4で解釈され,
それはユーザが期待している手法ではないことが多いものです.また,
qarは,他のマクロとは異なる動作をするので,Autoconfでは避けるべき
例外になります.