例のクイズの話。
まずは LaTeX で適当に試してみる
当然であるが、ページ上に何か文字を書くと、当然それを記録するために DVI ファイルの大きさは増えるはずである。だから最小の DVI ファイルは「白紙」であるはずである。そこで本文が空の LaTeX 文書を作ってみる。
\documentclass{article} \begin{document}\end{document}% 本体が空
これを quiz.tex として latex でコンパイルすると……。
No pages of output. Transcript written on quiz.log.
これではそもそも DVI が出力されず問題の条件を満たさない。なので、取りあえず、空の箱を置いてみる。
\documentclass{article} \begin{document}\mbox{}\end{document}% 空の箱を置く
Output written on quiz.dvi (1 page, 208 bytes). Transcript written on quiz.log.
残念ながら 208 バイトもの巨大な DVI ファイルができてしまった。実はこの DVI ファイルは「白紙」ではない。実際に表示させてみると、紙面下部に「1」というノンブルがしっかりと出力されている。というわけで、これを消してみる。
\documentclass{article}\pagestyle{empty}% ノンブル無し \begin{document}\mbox{}\end{document}
Output written on quiz.dvi (1 page, 152 bytes). Transcript written on quiz.log.
56 バイトもの大幅なサイズ削減に成功した。しかしもっと減らせないだろうか。
plain TeX で試してみる
何となく LaTeX よりも plain TeX の方が“単純”で自由度が高そうがから、ここからは plain TeX(tex コマンド)で頑張ってみる。
\nopagenumbers % ノンブル無し \leavevmode\bye % 空の段落を置いて終了
Output written on quiz.dvi (1 page, 152 bytes). Transcript written on quiz.log.
さっきと同じ結果になった。今度は水平モードに移行せずに垂直モードのまま空の箱を置いてみる。
\nopagenumbers \null \bye % \null は \hbox{} に展開されるマクロ
Output written on quiz.dvi (1 page, 144 bytes). Transcript written on quiz.log.
さらに小さくなった。しかし、そもそも「最小」の出力を得たいのであれば、それが何バイトであるのかを知る必要があるだろう。
最小の DVI ファイルとは何か
これを調べるため、DVI の中身を“解読”するツール dv2dt を利用してみる。*1直近の quiz.dvi(144 バイト)に対して
dv2dt quiz.dvi quiz.dtl
を実行すると、次のような“ダンプファイル”(DTL形式)quiz.dtl が得られる。(#
以降のコメントは私が補足したもの。)
variety sequences-6 # dv2dtの出力形式(DTL)のヘッダ pre 2 25400000 473628672 1000 27 ' TeX output 2015.05.22:2222' # DVIのプレアンブル部 bop 1 0 0 0 0 0 0 0 0 0 -1 # ページ開始 [ # 以下ページ記述命令が並ぶ d3 -917504 ] d4 42152922 d3 1572864 eop # ページ終了 post 42 25400000 473628672 1000 43725786 30785863 2 1 # DVIのポストアンブル部開始 post_post 103 2 223 223 223 223 223 223 # DVIのポストアンブル部終了
なお、DVI の書式についての情報は CTAN に dvistd パッケージとして公開されている。(日本語の資料としてアスキーによる解説がある。)
DVI の仕様に依ると、プレアンブル部(pre)とポストアンブル部(post、post_post*2)は必須の要素である。DVI ファイルは少なくとも一つのページを必ず持っている*3ので、1 組の bop と eop も必須である。従って、現状の quiz.dvi から削減できる要素は次の 2 つに限られる。
- bop と eop の間にあるページ記述命令群。*4
- プレアンブル(pre)に含まれる“DVI コメント”の文字列。上記の DTL の中の ' TeX output 2015.05.22:2222' のことである(その前の 27 はバイト数を表す)。
以上のことより、「最小の正常な DVI」は以下のようになるはずである。
variety sequences-6 pre 2 25400000 473628672 1000 0 '' # DVIコメントを空文字列にした bop 1 0 0 0 0 0 0 0 0 0 -1 # ページ描画命令列を空にした eop post XX 25400000 473628672 1000 43725786 30785863 2 1 # 'XX'はbopのオフセット post_post YY 2 223... # 'YY'はpostのオフセット
ここで “XX” と “YY” にはファイル中の特定の命令の存在位置(先頭からのオフセット値)を示す整数値が入る。また DVI ファイルの末尾については「ファイルサイズが 4 の倍数になるように 4〜7 個のバイト値 223 の列を置く」という規則がある。これを考慮して上記のものを正常な DTL に書き換えると以下のようになる。((この結果を容易に得るには、dv2dt の逆変換ツールである dt2dv の自動補正機能を利用する。当該のソース中の XX
と YY
を 0
に変えて、またコメントと「223...
」を除去して、“DTL の文法に適う”ファイル quiz.dtl を作り、それを「dt2dv quiz.dtl quiz.dvi
」で変換すると、「値が間違っている」という警告メッセージとともに、正しい値に修正された DVI ファイル quiz.dvi が得られる。あとはそれを再び dv2dt で変換すればよい。))
variety sequences-6 pre 2 25400000 473628672 1000 0 '' bop 1 0 0 0 0 0 0 0 0 0 -1 eop post 15 25400000 473628672 1000 43725786 30785863 2 1 post_post 61 2 223 223 223 223
そして、これに相当する DVI ファイルは以下の HEX ダンプで表される 100 バイトのファイルである。
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 8C F8 00 00 00000040 00 0F 01 83 92 C0 1C 3B-00 00 00 00 03 E8 02 9B 00000050 33 DA 01 D5 C1 47 00 02-00 01 F9 00 00 00 3D 02 00000060 DF DF DF DF
というわけで、目標とすべきは、この 100 バイトの quiz.dvi を TeX エンジンに出力させることである。
*1:DVI を解読する他のツールとして dvitype や DVIasm 等がある。
*2:なお、post と post_post の間には当該の DVI ファイルが使用するフォントの情報が列挙される。quiz.dvi は文字(フォント)を一切含まないのでこの部分が空になっている。
*3:dvistd 資料の A.1 節: A DVI file consists of a “preamble,” followed by a sequence of one or more “pages,” followed by a “postamble.”
*4:現状では、参照点の移動だけを行っていて結局何も出力していない。