前回の記事では次のようなタイプの「TeX 言語の Quine」を作った。
元の TeX 文書ファイルと生成される PDF ファイルの内容がバイナリで一致する。
しかしこれは pdfTeX エンジンを使うことを前提としている。「(Knuth の)元祖 TeX」で同様のことはできないだろうか。もちろん、元祖 TeX が出力するのは DVI ファイルだから、Quine の要件は次のようになる。
元の TeX 文書ファイルと生成される DVI ファイルの内容がバイナリで一致する。
本記事では「DVI で Quine する」ことについて考察する。
DVI で Quine できない話
いきなり残念な話になるが、“普通の”TeX を使うのでは「DVI で Quine する」ことは不可能である。
DVI ファイルフォーマットの定義を読めば解るが、現状の TeX エンジンが出力する DVI ファイルの先頭 10 バイトは必ず次の値になっている。
F7 02 01 83 92 C0 1C 3B 00 00
だから「(先述の意味で)Quine である TeX 文書ファイル」があるとすると、その先頭は必然的にこの 10 バイトになる。これを TeX エンジンに入力するとどうなるか。
まずは LaTeX の場合を考えてみよう。LaTeX では 0xF7 のカテゴリコードは 12(通常の文字)、だから先頭の 0xF7 でいきなり段落を始めようとするが、\begin{document}
が現れる前なのでこれは当然エラーになる。従って、LaTeX 文書としては通らない。
plain TeX の場合はどうか。plain でも 0xF7 は通常文字であり、plain ではいきなり段落を始めることが許されるのでこれは大丈夫である。*1次の 0x02 も通常文字である。ところがその次の 0x01 のカテゴリコードはなんと 8(下添字)である。plain.tex でそう定められているのである。*2
\catcode`\_=8 \catcode`\^^A=8 % underline and downarrow are for subscripts
つまり、0x01 の文字は plain TeX では _
と同等ということである。周知の通り、_
が数式モードの外で現れるとエラーになる。だから“普通の”plain TeX に DVI ファイルを入力すると、この 0x01(^^A
)の箇所でエラーになって通らないのである。
! Missing $ inserted. <inserted text> $ <to be read again> ^^A l.1 ^^f7^^B^^A ^^83^^92^^c0^^\;^^@^^@^^@^^@^^C^^e8^^[ TeX output 2016.01.05:1...
つまり“普通の”plain TeX や LaTeX では「DVI で Quine する」ことは無理なのである。