Acetaminophen’s diary

化学に関すること,TeXに関すること,ゆきだるまに関すること。

etex パッケージの \extrafloats が少し優しくなった話

この記事は、サブブログの 2016-08-02 投稿記事を移転してきたものです。

LaTeX\extrafloats の小噺を。

 

(復習)\extraflots を etex パッケージの後に使うとエラー

id:doraTeX さんの約11ヶ月前の記事

で、新 LaTeX カーネルに追加された \extrafloats という命令*1を etex パッケージの後で使うと非常にわかりづらいエラーが出ることが指摘されている。

\documentclass{article}
\usepackage{etex}
\extrafloats{10}
Missing = inserted for \ifnum.
<to be read again>
                   \relax
l.3 \extrafloats{10}

?

エラーが出る原因も当該記事で解説されているとおり、\ch@ck の引数書式が etex.sty で再定義されるため、\extrafloats が壊されてしまうのである。

例の記事では、ふたとおりの回避策が書かれている。

対策1:\extrafloats の使用はできるだけ前に!」
TeX Live 2015 で浮動体の個数を増やしたい場合,他のパッケージが etex パッケージを呼び出す前に,できるだけ早い段階で \extrafloats を使うように心がけるとよいでしょう。そうすればこの問題を回避できます。

対策2:\extrafloats の定義を書き換える
\extrafloats の定義において,後に etex パッケージで書き換えられる可能性のある \ch@ck という命令を使っていることが本件の原因です。そこで,その名前を書き換えてしまいましょう。

たしかに、エラーを回避することはできるようだ。

 

上の「対策」は妥当なのか?

ZR さんの LaTeX が新しくなった話(補足2)では、カーネルと etex パッケージは互換性がないことが書かれている。そして、実はこれは \extrafloats にもあてはまる。

まず \extrafloats は、source2e にも記述があるとおり、e-TeX では拡張レジスタ領域の高位からフロート用のボックスを確保する*2。一方、etex.sty はローカルなレジスタを確保するために、従来から高位のレジスタを利用していた*3。比べると分かるとおり、\extrafloats と etex.sty は既に衝突しているのだ。

ではなぜ doraTeX さんの場合は ok なように見えるかというと

  • etex.sty を利用したが、運良く「etex.sty の仕組みに則った高位レジスタ確保」が実際には行われなかった
  • etex.sty を利用して「etex.sty の仕組みに則った高位レジスタ確保」が行われたが、「ローカルなレジスタはローカル」なので、運良く偶然 \extrafloats が効く範囲とかぶっていなかった

のいずれかであろう*4。ZR さんの記事には

単純に考慮漏れのために起きた不具合(つまりバグ)という可能性も考えられる。だがしかし、etex と新カーネルで異なるロジックを使っている以上、衝突が起こってしまうのはかなり自明なように思える。なんとなく、「実害がほとんどないので放置された」のではないかと疑っている。(中略)ただし、このようなケースが起こりにくいのも確かである。そもそもユーザが etex を読み込むのであれば普通はできるだけ早い段階で読み込もうとするだろう。実際には滅多に発生しないのかも知れない。

と書かれているのと同様で、上のどちらでもない“運が悪い状況”は滅多に発生しないのかもしれない。問題が起きる例がでてくれば話は別かもしれないが、それよりも今は 0.01% くらいの「ほんとうに etex パッケージ特有のルーチンや機能を必要としている人」がいる可能性のほうを優先している、ということのようだ。

 

新しい etex.sty (2016/08/01 v2.7) では

従来の \ifnum の parse に失敗した解りにくいエラーではなく、もっと明解なエラーを出すようになった。エラーであることに変わりはない:

! Package etex Error: \extrafloats is incompatible with etex.sty allocation.
(etex)                Try using \extrafloats before loading etex.

See the etex package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              
                                                  
l.3 \extrafloats{10}
                    
?

上で述べたとおり、\extrafloats を etex.sty と同時に使うことは完璧に安全とはいえない。もちろん etex.sty 側で \extrafloats を doraTeX さんの対策 2 のように再定義してしまうこともできなくはないが、「安全でない可能性があるのにサポートする」のはある意味で罪かもしれない。そこで「どうせエラーなら分かりやすいエラーを」ということで、新仕様が確定した。Try using \extrafloats before loading etex. と書かれているのは、doraTeX さんの対策 1 のことであり、「完璧に安全ではないが機能するかもしれない」ことを示唆するものである。

 

(付録)linegoal パッケージなどはなぜ etex パッケージを使っているのか

doraTeX さんの記事で、linegoal パッケージが etex パッケージを読み込んでいることが指摘されている。ではなぜ読み込んでいるのだろうか? 実は、linegoal は etex の機能を何も使ってなどいない。つまり無駄に読み込んでいるということになる。なぜなのかはわからないが、「なんとなく良さそうだから」のようだ*5

*1:未処理の浮動体の個数の許容上限を指定の数だけ増加させる。

*2:具体的には In e-tex take float boxes from the top of the extended range. の辺りで、\extrafloats は \float@count を最大値 \e@alloc@top に設定し、そこから順次 1 引きながらレジスタを割り当てるという定義がなされている。

*3:具体的には We also define \loccount, etc., but these register definitions are local to the current group. の辺りで、\count レジスタを 32767, 32766, ... と割り当てていくことが記されている。

*4:LaTeX team の一員であり、かつ etex.sty の現在のメンテナである David Carlislie 氏は、本件について僕とメールでやりとりする中で以下のように述べている:there is not a completely safe definition (without a lot of extra complication) as the "high" range of registers that are used by \extrafloats clashes with the same range used by etex.sty's local allocation system. Often it (accidentally) works as the locally allocated registers are (presumably) just used in a local group so if that is in a box or otherwise protected from float handling in the page breaker the fact that the same registers are being used does not matter.

*5:etex.sty のメンテナである David Carlisle 氏によると、約1年前 (2015-07-07) に linegoal の著者 Florent Chervet 氏に etex.sty を読み込まないように依頼するメールを送ったがまだ返事がないそうだ。