マクロツイーター

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

\pdfstrcmp プリミティブのお話 (1/3)

以前の記事\pdfstrcmp について言及した。

名前から容易に想像されるように、\pdfstrcmp 命令は C 言語標準ライブラリの strcmp() (あるいは Perl の cmp 演算子Java の String.compareTo() メソッド)と同じように、2 つの文字列を受け取り、その(内部文字コードの辞書順での)大小を整数値の符号として返す。正確にいうと、\pdfstrcmp{<テキストA>l}{<テキストB>} はまず 2 つのテキスト A と B を完全展開して非トークン化した(\write の出力結果と同じ)後、辞書順で文字列比較し、A < B、A = B、A > B の各々が成立するときにそれぞれ「-1」「0」「1」に展開される(つまり完全展開可能である)。

この命令は pdfTeX 拡張の 1 つなので、pdfTeX 拡張をもたない Aleph/XeTeX/e-pTeX((ちなみに e-TeX のエンジンは既に廃止されていて、plain e-TeX のコマンド etex で起動されるのは pdfTeX の DVI モードである。LaTeX のコマンド latex も実際は pdfTeX エンジンを使う。超本家の TeX エンジンは今も健在で、plain TeX のコマンド tex ではそれが使われている。多分、「それを必要とする人間が一人以上存在することが判明している」からであろう。))では本来使えないはずである。ところが、XeTeX では \pdfstrcmp と全く同じ仕様のプリミティブをなぜか \strcmp という別の名前で用意している((例えば \pdfsavepos のようにそのままの名前で XeTeX が採用している pdfTeX 拡張プリミティブもある。なぜ扱いが異なるのかは不明。))。expl3 バンドルはどちらの名前でも認識するようになっているので XeLaTeX でも使用可能になっている(fontspec パッケージは実際に expl3 を使っている)。

expl3 バンドルを e-pLaTeX でも使えるようにする目的で、最近になって、\pdfstrcmp は e-pTeX エンジンにも取り入れられたが、現状では名前について複雑なことになっている。まず 2010 年 12 月下旬に角藤氏が W32TeX の e-pTeX エンジンにおいて拡張を行いそこでは XeTeX と同じ \strcmp となっている。その数日後に e-pTeX の作者である北川氏の方でも拡張が行われたが、そこでは pdfTeX と同じ \pdfstrcmp という名前を用いている。もちろん expl3 を使う目的ではどちらでも構わないが、パッケージ開発者は注意を要する。

では LuaTeX ではどうなっているか。LuaTeX は pdfTeX の後継であるので、\pdfstrcmp という名前で存在する……のではなく、実は LuaTeX にはこのプリミティブは存在しない。LuaTeX では pdfTeX 拡張機能のうち「Lua コード呼出を用いれば容易に実現できる」ものを意図的に省いていて、\pdfstrcmp もそれに該当するのである((他には、\pdfmdfivesumMD5 ハッシュ値を計算する)、\pdfmatch正規表現検索)、\pdfescapegex(PDF 16 進文字列表現に変換)等がある。))。expl3 バンドルでは次のようなマクロ(と同等のもの)を用いている((このコードを LuaLaTeX で実際に用いる場合は \luaescapestring\luatexluaescapestring に変更する必要がある。この理由は「日本語しない件」で述べた。))。


\directlua{
function strcmp (A, B)
if A == B then tex.write("0")
elseif A < B then tex.write("-1")
else tex.write("1")
end
end}
\long\def\pdfstrcmp#1#2{\directlua{
strcmp("\luaescapestring{#1}", "\luaescapestring{#2}")
}}

(続き)