「段落先頭」という罠
ところで、このような割と単純な「アウトな空白」によるバグは、少しでもテストをしていれば気付くはず、と考える人もいるだろう。だが、実際には「アウトな空白」のバグは、「テストケースの作り方」が悪いために見過ごされてしまう危険性が高いのである。
\documentclass{article} \makeatletter % スライド掲載のコードを"そのまま"書いた \newcount\@m \newcount\@k \def\factorial#1{% \@m = 1 \relax \@k = 1 \relax \@whilenum \@m < #1 \do {% \advance \@m 1 \relax \multiply \@k \@m \relax } \the\@k } \makeatother \begin{document} % \factorial "だけ"置いてテストしている. 720 \factorial{6} \newcounter{myVal} \setcounter{myVal}{6} \factorial{\value{myVal}} \end{document}
自分で実装したマクロ \factorial
の動作を検証しようとして上記のように「\factorial
だけ」書いたようなソースをコンパイルしたとする。すると結果は次のようになり、余計な空きは全く出現しない。
ここで「余計な空き」が出現しない理由は、TeX の一般的な組版規則として、「段落先頭にある空白トークンは無視される(水平空きを生じない)」*1からである。つまり、マクロを段落の先頭に書いた場合は、たとえ「アウトな空白トークン」が実行されていても、結果に空きは出現しないのである。
無論、この性質は「バグが露見しない」というだけで全く嬉しいことでない。後になって「段落内」でそのマクロを使う機会がありそこで初めてバグが発覚するという最悪の事態を迎えるだけである。*2そういう事態を避けたいのであれば、次の事を心がけることを推奨したい。
「段落内」で使われうるマクロ(命令)のテストをする場合は、
必ず、「段落内」での使用をテストケースに含める。
本当に恐ろしい「段落先頭という罠」
この「段落先頭という罠」は熟練した TeXnician も無縁ではないようである。実際、CTAN に登録されているパッケージでも、「段落内」で利用すると「アウトな空白」による空きを無残にさらけ出してしまうものが存在する。 その中でも衝撃的なのは、最近発見された次のバグである。
graphicx パッケージを dvipdfmx で利用していてかつ xbb ファイルの自動生成を有効にしている状態を仮定する。ここで「段落内」で使用した \includegraphics
命令において実際に xbb の自動生成(extractbb の起動)が行われた場合、*3挿入された画像の直前に余計な空白が出現する。
この不具合の原因はドライバ定義ファイル dvipdfmx.def に混入した「アウトな空白」である。
\def\Gread@pdf#1{% \begingroup \@tempcnta\z@ ……(略)…… \ifeof\@inputcheck \immediate\write18{extractbb \Gin@base\Gin@ext} ←行末に % がない!! \immediate\openin\@inputcheck#1 % \fi ……(略)…… \expandafter\Gread@parse@bb\@gtempa\\}
驚くべきは、このバグは 5 年以上の間気付かれずに残っていたことである。文書に画像を挿入する時、ほとんどの場合は \includegraphics
だけで段落をなすように配置される。これはすなわち段落先頭にあることになるので、この場合には空白が現れない。また稀に「段落内」に \includegraphics
を置くことがあっても、画像自体が余白を持っていることが多くて、そのため数 pt の欧文空白はやはり気付き難かったのであろう。