マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

TeX プログラムのデバッグで絶望する前に知るべきこと (1)

絶望的な状況であるのは否めない。ただ、絶望的に絶望する前にできることもある。

今ある道具を使いこなす

TeX には「デバッグのために用意されている機能」が幾つかある。なので、「テクニック」以前の問題として、非自明な「デバッグ」が必要な複雑な TeX プログラムを書こうとする者には、それらの使い方の習得が不可欠であることは当然であろう。この記事では単にプリミティブを列挙するだけに留めるので、知らないものがある場合は是非とも手元の TeX の参考書で調べてみてほしい。

ただし注意しておきたいことがある。これらのデバッグ用機能は e-TeX において強化充実が行われていて、その中に非常に重要なものも含まれている。従って、e-TeX の説明書((TeX Live や W32TeX では「texdoc etex」で PDF 文書が開かれる。))の当該の部分も読んでおきたい。(以下の説明では、e-TeX 拡張機能に ☆ 印を付した。)

tracingナントカ

以下に挙げる \tracing... という名前の整数パラメタは、その値が正である場合に、TeX 処理系の特定種類の実行トレース出力を行う。要するに、「TeX 中で何をやってるかを教えてくれる」わけである。(以下では、各パラメタに対応するトレースの種類を述べる。)トレース出力は通常はログファイルにのみ書き出されるが、\tracingonline の値が正である場合は端末にも出力される。

  • \tracingmacros ≧ 1: マクロの展開の状況を出力する。
    • ≧ 2:トークン列パラメタ(\everypar 等)の展開状況も出力する。
  • \tracingoutput ≧ 1: ページを書き出す時にそのボックスのダンプを出力する。((\showbox と同じ形式。なので、\showboxdepth 等のパラメタが関与する。))
  • \tracingcommands ≧ 1: 実行されたプリミティブ命令。 ※「空白トークンの漏洩」の箇所を突き止める為の必需品。
    • ≧ 2: 条件判定(\if-トークン)の結果を出力する。
    • ≧ 3 ☆: 接頭辞プリミティブに続いてそれが修飾したプリミティブ命令も出力する。((\tracingcommands ≦ 2 の場合、\global\count0=1 を実行する際に \global のみ記録されて \count はされない、という少し嫌な動作になる。))
  • \tracingassigns ≧ 1 ☆: 代入操作の状況(代入前後の値)。
  • \tracingrestores ≧ 1: グルーピングを脱出した時の代入の巻き戻し。
  • \tracingifs ≧ 1 ☆: 条件分岐のネストの出入り。
  • \tracinggroups ≧ 1 ☆: グルーピングのネストの出入り。
  • \tracingnesting ≧ 1 ☆: 条件分岐/グルーピングのネストとファイル入力のネストがずれた場合の警告。
    • ≧ 2 ☆: 現在コンテキストの詳細情報を出力する。
  • \tracingscantokens ≧ 1 ☆: \scantokens の開始と終了。
  • \tracinglostchars ≧ 1 : 現在(欧文)フォントで未定義のコード位置の文字を出力した場合の警告。(LaTeX での初期値 = 1)
    • ≧ 2 ☆: \tracingonline の値に関わらず警告を端末に出力する。
  • \tracingparagraphs ≧ 1 : 行分割アルゴリズムの状況。
  • \tracingpages ≧ 1 : ページ分割アルゴリズムの状況。
  • \tracingstats ≧ 1: 使用されたメモリの量の情報。(LaTeX での初期値 = 1*1
    • ≧ 2:ページ出力時にそのページでのメモリ使用量を出力する。

このリストは「私が判断する重要度の降順」で並べた。プログラムのデバッグで一番大事なのは間違いなく \tracingmacros なので、tracingナントカ が未経験だという人はまずこのパラメタ名を覚えよう。

例えば、次のような LaTeX 文書をコンパイルすると:

\documentclass{article}
\begin{document}\tracingonline=1 % トレースを端末にも出力
\tracingmacros=1 \tracingcommands=1 % マクロ展開と命令実行のトレースを有効に
\TeX!
\tracingmacros=0 \tracingcommands=0 % マクロ展開と命令実行のトレースを有効に
\end{document}

以下のようなトレース出力が端末とログに出力される。

\TeX ->T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX\@
{vertical mode: the letter T}
{horizontal mode: the letter T}
{\kern}
{\lower}
{restricted horizontal mode: the letter E}
{end-group character }}
{horizontal mode: \kern}
{the letter X}

\@->\spacefactor \@m
{\spacefactor}
{the character !}
{blank space  }

ここで、{ で始まっているのが \tracingcommands による命令実行のトレース((「the letter T」が 2 度実行されているように見えるが、これはここで垂直モード→水平モードの切替が起こったからである。もちろん、実際には「T」は一度しか実行(印字)されていない。))で、-> を含むものが \tracingmacros によるマクロ(\TeX\@)の展開のトレースである。一番最後に「行末による空白トークン」が実行されているのもしっかりと記録されている。

showナントカ

以下に挙げる \show... という名雨のプリミティブ命令は、特定の情報を“一旦停止”付きで出力する機能をもつ。

  • \showトークン〉 ‡: そのトークンの現在の意味(\meaning で出る文字列とほぼ同じもの*2)。
  • \showthe〈内部値〉 ‡: その内部値(パラメタ、レジスタなど)の現在の値(\the で出る文字列と同じもの((なのでこの後の \the の説明も参照されたい。)))。
  • \showtokens{トークン列〉} ☆‡: 引数のトークン列そのもの(展開しない)。
  • \showbox〈整数〉 : 指定番号のボックスレジスタの内容のダンプ。ボックスの中身を「どこまで」出力するかは以下の整数パラメタにより制御される。
    • \showboxdepth : ボックスのネストについて、ダンプ出力の対象とする深さの最大値。
    • \showboxbreadth : 各ネストレベルについて、ダンプ出力の対象とする要素数の最大値。
  • \showifs ☆: 現在の条件分岐のネストの状況。
  • \showgroups ☆: 現在の条件分岐のネストの状況。
  • \showlists : 「現在構築中のボックスの中身」の情報。
  • \showmode ‡〔pTeX系のみ〕: 現在の和文間空白(\autospacing)と和欧文間空白(\autoxspacing)の有無の指定。

これらの命令(先と同じく、「重要度順」に並べた)は何か情報をログファイルや端末に書き出すとともに、ちょうど TeX でエラーが発生した時と同じように、実行コンテキストを出力してさらにユーザの入力待ちに入る。情報を(ログファイルだけでなく)端末にも出力するかは \tracingonline の指定に従うが、上の一覧で ‡ 印を付けたものは常に端末にも出力される。(なお、ログファイルにのみ出力する場合でも実行は一旦停止する。*3

例えば、LaTeX で次の文が実行されたとする:

\show\TeX

すると、端末に次のように出力されて入力待ち状態になる。

*\show\TeX
> \TeX=macro:
->T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX\@.
<*> \show\TeX

?

ここでの操作方法は、エラーで「?」プロンプトが出た場合と全く同じである。多くの場合は Enter キーを空打ちすることになるだろう。

\showbox については昔の記事で詳細な解説を行ったのでそちらを参照してほしい。

(つづけ)

*1:そう、LaTeX を実行した時に一番最後に出てくるアレである。

*2:ただし読みやすくするため一部の箇所に改行が入っている。

*3:そして、ログ出力のバッファがフラッシュされるわけでもないので、ここでの停止中にログ出力を確認することはできない。何だかアレである。