以前の記事で \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
もそれに該当するのである((他には、\pdfmdfivesum
(MD5 ハッシュ値を計算する)、\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}")
}}