アレのことだけど。
zxjatype じゃなくて xeCJK を指定して同様の文書を作った場合にも同じエラーが発生するので、これは xeCJK の問題といえるだろう。で、きちんと調べたわけではないが、何となく原因と考えられるものを述べておく。これは XeTeX 特有の機能である「文字間トークン自動挿入」に関連する。
同様のエラーの再現例
次の(ToL の)コードは、「文字間トークン自動挿入」を利用して、文字〈3〉が自動的にアホなフォントになる仕掛けを作っている。(〈3〉の出力の前後で自動的に「\begingroup\ahofont
」および「\endgroup
」のトークン列が挿入される。)また、環境 hoge は単に中身のフォントをサンセリフにするものであるが、ここでは \newenvironment
命令を利用せずに、“原始的”に \hoge
と \endhoge
のマクロを定義している。
% XeLaTeX 文書; 文字コードは UTF-8 \documentclass[a4paper]{article} %% 環境 hoge を"原始的に"定義する \def\hoge{\sffamily} \let\endhoge\relax %% 文字〈3〉をアホなフォントにする \font\ahofont=cmfi10 at 15pt \XeTeXcharclass`3=9 \XeTeXinterchartoks 0 9 {\begingroup\ahofont} \XeTeXinterchartoks 255 9 {\begingroup\ahofont} \XeTeXinterchartoks 9 0 {\endgroup} \XeTeXinterchartoks 9 255 {\endgroup} \XeTeXinterchartokenstate=1 \begin{document} 12345 \begin{hoge}123\end{hoge}45 \end{document}
この文書のコンパイルは成功し、機体通りの結果が得られる。ところが、ここで上掲のソース中で、\endhoge
の定義文をコメントアウトして、\endhoge
を未定義の状態にしてみる。
%%\let\endhoge\relax % \endhoge は未定義
LaTeX の内部仕様としては、これでも環境の定義としては正当である。実際、例の TeX Forum の記事では、「宣言型命令は環境としても使用可能である」という LaTeX の規則に従って、文字サイズ命令 \Huge
を環境として使っているのであるが、このような“環境”に関しては、もちろん \endHuge
というマクロは定義されていない。
さて、この修正を加えた後で再び文書をコンパイルしてみると、今度は、\endhoge
が未定義だというエラーが出てしまう。
! Undefined control sequence. <recently read> \endhoge l.15 12345 \begin{hoge}123\end{hoge} 45 ?
何故だろうか? エラーが出る直前の“3\end{hoge}
”の箇所の処理を追いかけてみる。
- まず、(展開不能な)文字トークン〈3〉が実行対象になる。文字〈2〉を出力した直後なので、〈2〉‐〈3〉の組での文字間トークン列挿入が起こる。クラスの組は 0‐9 なので、「
\begingroup\ahofont
」が挿入される。 - 「
\begingroup\ahofont
」が実行される。(ここでグループに入ることに注意。) - 文字〈3〉の出力を行う。(フォントは cmfi10 になっている。)
- 次のトークン
\end
は展開可能(マクロ)なので、展開される。\end{hoge} → \csname endhoge\endcsname \@checkend {hoge}…(略)…
- 展開後の先頭トークン
\csname
は展開可能プリミティブなので、展開される。\csname endhoge\endcsname → \endhoge
ここで、TeX の仕様として、\csname
で制御綴を生成した場合に、それが未定義であった場合は暗黙的に\relax
に等置されるので、ここで\endhoge
が\relax
になる。((ちなみに、この「\relax
化」は TeX において「展開によって代入動作が引き起こされる」唯一の事例である。)) - 展開後の先頭トークン
\endhoge
は展開不能(\relax
だから)なので、ここで文字間トークン列挿入が起こる。クラスの組は 9‐255 なので*1、「\endgroup
」が挿入される。 \endgroup
が実行される。2 で開始したグループを脱出する。- 次のトークンは
\endhoge
である。さて、これの現在の意味は何だろうか? 5 において、\endhoge
は\relax
に等置されたが、これは 2 で開始したグループの中においてであり、そのグループはさっき抜けたので、\endhoge
は未定義に戻っている。 - 結果として、「
\endhoge
が未定義である」というエラーが発生する。
要約すると、\endhoge
という制御綴の生成とその実行の間でトークン列が割り込んできてそれでグループレベルが変わってしまうのが原因、ということになる。LaTeX の実装コードが XeTeX 特有の機能との絡みで問題が出るのは仕方がないことであろう。
確証は得られていないが、TeX Forum で報告されている xeCJK の事例でも同様の動作が起こっているものと思われる。\end
の直前に \relax\relax
の処理の時となって、\endhoge
の時ではなくなるからである。