寿司失敗
実際に、次の「🍣を \string
する」ソースファイルを、Windows 上の TeX Live 2014 の xetex コマンドでコンパイルしてみると……。
\def\pick#1{#1.} \message{\expandafter\pick\string 🍣}\bye
以下の表示が出たところで凍り付いてしまう。
This is XeTeX, Version 3.14159265-2.6-0.99991 (TeX Live 2014/W32TeX) (preloaded format=xetex) restricted \write18 enabled. entering extended mode (./test.tex
恐らくこの不具合は以前に取り上げたコレと同じ原因によるものだろう。
つまり、🍣(U+1F363)等の BMP 外の文字のトークンに対して、\string
・\meaning
・\detokenize
・\scantokens
等の“文字列化”を行うプリミティブが適用されると、そのトークンがサロゲートペアの符号値の文字トークンに分解されてしまうのである。例えば、🍣の場合は 0xD83C と 0xDF63 の 2 つの文字トークンに変わってしまう。従って、
\expandafter\pick\string 🍣
を一回展開した結果は
(D83Cのトークン).(DF63のトークン)
となり、この「不正な符号値の列」を端末に出力しようとして何か不味いことが起こっているのだと推測される。((Windows 上の TeX エンジンは「端末に出力」するときに結構複雑な処理を行っているようである。端末(\message
)でなくログ(\immediate\write-1
)に同じ文字列を出力した場合は凍り付くことはない。))
寿司成功
もちろん、本来は🍣を \string
しても(カテゴリコードは変わるかも知れないが)単一の🍣のトークンのままなので、「\expandafter\pick\string 🍣
」の一回展開は「🍣.
」となるべきである。
そして、最新の TeX Live の xetex で先のソースファイルをコンパイルすると……。
This is XeTeX, Version 3.14159265-2.6-0.99992 (TeX Live 2015/W32TeX) (preloaded format=xetex) restricted \write18 enabled. entering extended mode (./test.tex ・坤. ) No pages of output. Transcript written on test.log.
今度は“凍り付く”こともなく無事処理が完了する。端末での \message
の出力は化けている(端末の文字コードが CP932 なので)がログを見ると、“想定通り”の結果になっていることが判る。
**./test.tex (./test.tex 🍣. ) No pages of output.
そういうわけで「🍣が壊れるバグ」は最新の環境では直っていることが判った。しかし TeX 言語で複雑な文字列処理を実装することのある開発者は、当面の間はこのバグの存在を気に留めておく必要があるだろう。