「レジスタ 65536 個」
e-(u)pTeX 上の LaTeX を「レジスタ 65536 個」に対応させることについては、「あまり重要ではない」としたが、ここではそれを実現する際の課題について考える。ここで問題になるのは「\chardef
による整数定数定義の限界」である。
LaTeX で \newcount
で制御綴にレジスタを割り当てた場合、その制御綴は countdef トークンになる。
\newcount\mycountA \show\countA %==>「\mycount123」(例えば) % 以下の2つが同等になる \mycountA=42 \count123=42
\newdimen
や \newtoks
等にういても同様である。ところが、\newbox
に関しては事情が異なる。この場合、割当の対象となる制御綴は「ボックス型の変数」の代わりになるのではなく、常に \setbox
や \copy
等の「添字」として使われる。
\newbox\myboxA % 以下の2つが同等になる \setbox\myboxA\hbox{Hello}\copy\myboxA \setbox123\hbox{Hello}\copy123
すなわち、この \myboxA
は実は単なる整数定数なのである。\newbox
の他に、\newread
、\newwrite
、\newfam
、\newlanguage
で定義される制御綴も整数定数である。
ところで、TeX において整数定数を定義するには \chardef
が流用される。例えば、\newbox
マクロが \myboxA
を定義する時は次のコードを実行している。
\chardef\myboxA=123 % 整数定数を定義
(ちなみに、\newcount
の場合は \countdef
プリミティブが用いられる。)
ところが、「\chardef
で定数を定義する」というのは(よく利用されるが)「裏技」であるゆえ、少し不合理な制限をもつ。つまり、「本来の目的」を考えると \chardef
の定義式の右辺にとれる値の範囲、すなわち「\chardef
の定数が作れる範囲」は「有効な文字符号値の範囲」に限られることが判る。\newbox
等がちゃんと機能するためには、この範囲が「レジスタ番号の範囲」をカバーできていなければならない。
「定数を作る」問題
両者の具体的な範囲はエンジンによって異なり、以下のようになっている。
エンジン | 有効な符号値 | レジスタ番号 |
---|---|---|
TeX | 0〜255 | 0〜255 |
pdfTeX | 0〜255 | 0〜32767 |
Aleph | 0〜65535 | 0〜65535 |
XeTeX | 0〜1114111 | 0〜32767 |
LuaTeX | 0〜1114111 | 0〜65535 |
e-pTeX | 0〜255 + 和文 | 0〜65535 |
e-upTeX | 0〜231−1 | 0〜65535 |
e-pTeX の「有効な符号値の範囲」は少し複雑で、欧文の符号値(0〜255)と和文の符号値の両方が有効であり、後者の範囲は「現在の内部漢字コード(EUC または SJIS)の有効な“スカラー値”*1の集合」となっている。
これを見ると、pdfTeX では「\chardef
の範囲」でレジスタ番号の範囲をカバーできていないことが判る。また、e-pTeX の「和文符号値」は不連続で特に 256〜33087 の値を含まないため、e-pTeX も必要な範囲をカバーできていない。
このうち、pdfTeX に関しては問題を回避する方法がある。「整数定数」を作るのに \chardef
の代わりに \mathchardef
を使うこともできて、この場合は(エンジンに依らずに)0〜32767 の範囲の定数が作れるので、これを利用して必要なレジスタ番号の範囲をカバーできる。実際に、LaTeX の新カーネルでは pdfTeX のときは定数定義に \mathchardef
を使っている((t定数定義の命令として \e@alloc@chardef
を用意し、それがエンジンによって \chardef
か \mathchardef
に等値されるようになっている。))。(なお、割当の制御綴を整数定数でなく \def\myboxA{50000 }
)のような“整数値マクロ”で定義する、というのは、従来の方法と互換がないので無理である。((例えば、\the\myboxA
のように使われる可能性が絶対無いとはいえない。\protected\myboxA{\numexpr50000\relax}
とでもすれば失敗するか可能性は減らせるが、確実ではない。)))
では全く同じ方法が e-pTeX に使えるかというと、それは無理である。何故なら、こちらでは必要な「レジスタ番号の範囲」が 0〜65535 であり、\mathchardef
でもカバーできないからである。結局、e-pTeX の場合はどうしようもないのではないか……。
またアレなことを考えてみた
いや、実は解決方法は存在する。そもそも今考えている(レジスタが 65536 個ある)のは FAM256 適用の e-pTeX である。ということは、Omega 互換の「\mathchardef
の拡張版」である \omathchardef
というプリミティブが使用できる。この命令も整数定数定義に使用できて、しかも、Omega 拡張の omathcode は 27 ビット(クラス 3 + ファミリ 8 + 文字コード 16)の値をとる。ということは \omathchardef
を使うと、0〜65535 の範囲の整数定数が作れる!
ただ少し注意すべき点がある。FAM256 適用の e-pTeX では数式ファミリは 256 個(8 ビット)に拡張されているが、欧文符号空間は 8 ビットのままである(Omega は符号空間が 16 ビットである)。従って、omathcode の下位 16 ビット(文字コード)が 255 を超える場合(例えば 0x2021306)は e-pTeX にとっては「無意味な値」となってしまうはずである。
しかし実際に試してみた限りでは、そのような「無意味な」値をもつ \omathchardef
でエラーが生じることはなく、また定数定義としては想定通りの動作をするようである。
\omathchardef\foo="2021306 \show\foo %==>「\foo=\omathchar"2021306」 \showthe\foo %==>「33690374」(= 0x2021306)
というわけで、この現状の動作を仕様と定めてしまえばいい。すると、「FAM256 適用の e-pTeX では(あるいは e-upTeX を含めてしまってもよく、また『\omathchar
がある場合』でもよい)定数定義(\e@alloc@chardef
)に \omathchardef
を使う」ということで無事に問題を解決できる。