出力切替え(diversions)は出力を一時的に保存しておく方法です。
m4
では好きなときに出力を一時ファイルへ切替え(divert)ておき、
後で再び出力ストリームへと逆切替え(undiverted)することができます。
切り替え先番号は0から数え上げます。切替え先0は通常の出力ストリームです。
同時に存在できる切替え先の数は主としてそれらを記述するために使われるメモリ
によって制限されます。
これはGNU m4
が切替え先の情報とそこへの出力をメモリに置いておこうとするためです。
しかし全ての切替え先に必要なメモリの総量には制限があります(現在は512Kです)。
この最大値を超えそうになったときは、一番大きな切替え先の内容を入れるために
一時ファイルが作られ、その分のメモリが他の切替え先のために開放されます。
したがって理論上は切替え先の数が利用可能なファイル・ディスクリプタの数
によって制限されることがありえます。
divert(opt number)
numberは使用する切替え先です。 numberを省略したときはゼロとして解釈されます。
divert
は展開されると消滅します。
m4
への入力がすべて処理されると、
その時点で存在するすべての切替え先が自動的に番号の順で逆切替え(undivert)
されて、そこにたまっていたテキストが出力されます。
divert(1) This text is diverted. divert => This text is not diverted. =>This text is not diverted. ^D => =>This text is diverted.
同じ引数でdivert
を何回か呼び出すと、
切替え先にある以前のテキストは上書きされずに、
新しいテキストが以前のテキストの後に追加されてゆきます。
存在するはずのない切替え先へ出力を切替えるとそこから後の出力は 単に捨てられます。 よくある不要な出力の例はマクロ定義の後にある改行です。 次はそれらを避ける方法です。
divert(-1) define(`foo', `Macro `foo'.') define(`bar', `Macro `bar'.') divert =>
これはm4
でのプログラミング上の一般的な慣用句のひとつです。
切替え先に出力されたテキスト(diverted text)は組み込みマクロ
undivert
を使って明示的に逆切替え(undivert)することができます。
undivert(opt number, ...)
このマクロは引数で指定された切替え先を、指定された順に逆切替えして出力します。 引数が与えられなかったときは、すべての切替え先を番号順に逆切替えします。
undivert
は展開されると消滅します。
divert(1) This text is diverted. divert => This text is not diverted. =>This text is not diverted. undivert(1) => =>This text is diverted. =>
最後にある2つの空行に注目してください。
1つはundivert
に続く改行によるもので、
もう一方はなんとdivert
に続く改行によるものです!
切替え先のテキストはしばしばこのような空行で始まります。
切替え先のテキスト(diverted text)は逆切替え(undiverted)されると、
m4
によって再走査されずに、
現在の出力(切替え先)に直接コピーされます。
したがってある切替え先(diversion)に出力中に、
逆切替え(undivert)しても問題ありません。
逆切替えをすると、その切替え先にあるテキストは破棄されるので そのテキストを取り出せるのは1回だけです。
divert(1) This text is diverted first. divert(0)undivert(1)dnl => =>This text is diverted first. undivert(1) => divert(1) This text is also diverted but not appended. divert(0)undivert(1)dnl => =>This text is also diverted but not appended.
現在の切替え先(current diversion)を逆切替え(undivert)しようとしても 黙殺されます。
GNU m4
では名前を指定したファイルを逆切替え(undivert)することができます。
数字以外の引数を与えると、その名前をもつファイルの内容が
現在の出力(切替え先)に解釈されずにコピーされます。
これによって組み込みマクロinclude
の機能が補完されます(see section 名前を指定してファイルをインクルードする)。
次の例で違いを説明します。ファイル`foo'の内容は`bar'だとします。
define(`bar', `BAR') => undivert(`foo') =>bar => include(`foo') =>BAR =>
組み込みマクロdivnum
は現在の切替え先(current diversion)の番号に展開されます。
divnum
Initial divnum =>Initial 0 divert(1) Diversion one: divnum divert(2) Diversion two: divnum divert => ^D => =>Diversion one: 1 => =>Diversion two: 2
逆切替えされて出力されるテキスト自身が切替え先に出力されてしまうのを防ぐため
に最後にある引数無しのdivert
の呼び出しが必要です。
(訳者注: 誤訳の可能性あり。原文は
The last call of divert
without argument is necessary, since the
undiverted text would otherwise be diverted itself.)
出力を切替えているときは切替え先のテキストが実際に
必要となるかどうかは分からないことがよくあります。
テキストが溜っている切替え先は入力が終りに達した段階で
メインの出力ストリームにすべて出力されるので、
切替え先にたまっているテキストを破棄するためのなんらかの手段が必要です。
すべての切替え先のテキストを破棄したいときは
m4
への入力を`divert(-1)'とそれに続く明示的な`undivert'
で終えるのが最も簡単でしょう。
divert(1) Diversion one: divnum divert(2) Diversion two: divnum divert(-1) undivert ^D
このとき出力はいっさいありません。
特定の切替え先のテキストは次のマクロで消去できます。
define(`cleardivert', `pushdef(`_num', divnum)divert(-1)undivert($@)divert(_num)popdef(`_num')') =>
undivert
と同じように呼び出しますが、
その効果は引数として与えられた切替え先のテキストを消去することです。
(このマクロにはひどいバグがあります!
それを見つけて直せるか挑戦してみてください。)
Go to the first, previous, next, last section, table of contents.