マクロツイーター

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

TeX でもっともっと Quine する話(3)

前回の続き)

DVI で Quine できた話

というわけで、先述の方針に従って、実際に「DVI で Quine する」やつを作ってみた。

[teqgen.tex](Quine 生成器)
!
\catcode13=12!
\toks0{\output{\setbox0\box255 \shipout\hbox{%
\special{ps::(!
\catcode13=12!
\toks0{\the\toks0}%
\noexpand\the\toks0\end)pop}}}}%
\the\toks0\end
[teq.tcx](TCX ファイル)
0xf7 0x25

これらのファイルをカレントディレクトリに置いて、次のコマンドを実行して得られる DVI ファイル teqgen.dvi が Quine のファイルになっている。以下の説明ではこのファイルを teq.tex に改名したものとする。

tex -output-comment="" -translate-file=./teq teqgen

この Quine の TeX ソースファイル teq.tex は(DVI ファイルでもあるので)バイナリファイルであり、その 16 進ダンプは以下のようになっている。

[teq.tex](16 進ダンプ)
00000000  F7 02 01 83 92 C0 1C 3B-00 00 00 00 03 E8 00 8B   .......;........ 
00000010  00 00 00 01 00 00 00 00-00 00 00 00 00 00 00 00   ................ 
00000020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   ................ 
00000030  00 00 00 00 00 00 00 00-FF FF FF FF EF B8 70 73   ..............ps 
00000040  3A 3A 28 21 0D 5C 63 61-74 63 6F 64 65 20 31 33   ::(!.\catcode 13 
00000050  3D 31 32 21 0D 5C 74 6F-6B 73 20 30 7B 5C 6F 75   =12!.\toks 0{\ou 
00000060  74 70 75 74 20 7B 5C 73-65 74 62 6F 78 20 30 5C   tput {\setbox 0\ 
00000070  62 6F 78 20 32 35 35 20-5C 73 68 69 70 6F 75 74   box 255 \shipout 
00000080  20 5C 68 62 6F 78 20 7B-5C 73 70 65 63 69 61 6C    \hbox {\special 
00000090  20 7B 70 73 3A 3A 28 21-0D 5C 63 61 74 63 6F 64    {ps::(!.\catcod 
000000A0  65 20 31 33 3D 31 32 21-0D 5C 74 6F 6B 73 20 30   e 13=12!.\toks 0 
000000B0  7B 5C 74 68 65 20 5C 74-6F 6B 73 20 30 7D 5C 6E   {\the \toks 0}\n 
000000C0  6F 65 78 70 61 6E 64 20-5C 74 68 65 20 5C 74 6F   oexpand \the \to 
000000D0  6B 73 20 30 5C 65 6E 64-20 29 70 6F 70 7D 7D 7D   ks 0\end )pop}}} 
000000E0  7D 5C 74 68 65 20 5C 74-6F 6B 73 20 30 5C 65 6E   }\the \toks 0\en 
000000F0  64 20 29 70 6F 70 8C F8-00 00 00 0F 01 83 92 C0   d )pop.......... 
00000100  1C 3B 00 00 00 00 03 E8-00 00 00 00 00 00 00 00   .;.............. 
00000110  00 00 00 01 F9 00 00 00-F7 02 DF DF DF DF DF DF   ................ 

teq.tex(DVI ファイル)を dv2dt で逆アセンブルした結果は以下の通り。ここで special1 の引数の文字列は途中に改行が入っているが、この改行は全て CR(0x0D)である。

variety sequences-6
pre 2 25400000 473628672 1000 0 ''
bop 1 0 0 0 0 0 0 0 0 0 -1
special1 184 'ps::(!
\\catcode 13=12!
\\toks 0{\\output {\\setbox 0\\box 255 \\shipout \\hbox {\\special {ps::(!
\\catcode 13=12!
\\toks 0{\\the \\toks 0}\\noexpand \\the \\toks 0\\end )pop}}}}\\the \\toks 0\\end )pop'
eop
post 15 25400000 473628672 1000 0 0 0 1
post_post 247 2 223 223 223 223 223 223

それでは、この teq.tex を使って Quine してみよう。次のように、先と同じオプションを付けて tex コマンドでコンパイルする。

tex -output-comment="" -translate-file=./teq teqgen

この結果として生成された DVI ファイル teq.dvi は元の teq.tex と完全に(バイナリで)一致する。

[Unix 系のシェル]
# cmp teq.tex teq.dvi
# ←一致しているので何も表示されない
C>fc /B teq.tex teq.dvi
ファイル teq.tex と TEQ.DVI を比較しています
FC: 相違点は検出されませんでした

ちなみに、DVI の中に含まれる special 命令は正当な PostScript special 命令であるので、dvips や dvipdfmx の入力として通るようになっている(ただし結果は白紙であるが)。