Acetaminophen’s diary

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

pLaTeX が本格的にやばいかもという話

最近(この1週間ほど)で LaTeX 周りで起きていることについて,声明を出しておきます。端的に言うと「pLaTeX,本格的にやばい」。

f:id:acetaminophen:20210618021851p:plain

pLaTeX hyperref error with pdfmanagement-testphase

LaTeX の世界で何が起きているのか,ざっと説明します。

 

ここ1年ほどの LaTeX は大きく変わっている

2020-02-02 以降,本家の LaTeX2e に多くの変更が入っています。2020 年の2回のリリースについては,Online.tex 2020 での私の講演資料「最近の LaTeX は〇〇」【PDF 直リンク】も参考になるでしょう。

さらに次のバージョンは LaTeX2e 2021-11-15 になる予定ですが,その版もしくはさらに次の版で pLaTeX/upLaTeX が「致命的に」動かなくなる恐れが出てきているのです。この原因に大きく関わるのが「カーネルへの expl3 読込」です。

 

将来壊れるかもしれない例

まずは1つ例を挙げます。

例1: hyperref でメタデータに日本語文字を含むソース(参考

\documentclass[dvipdfmx]{article}
\usepackage{hyperref}
\usepackage{pxjahyper}
\hypersetup{pdftitle={日本語}}
\begin{document}
\section{はじめに}
あいうえお。
\end{document}

hyperref は従来 LaTeX2e の機能だけで実装されていました。日本語を使うとしおりが文字化けするなどの不都合はありましたが,「pxjahyper を追加で読み込むことで文字化け防止」という方法が提供されるなどして,今までは比較的安定に利用できていたと思います。

近い将来,この hyperref 内部で「文字列を扱う」という機能が,LaTeX2e(ほぼ TeX 言語)の従来実装から expl3 という新言語の実装へと置き換えられようとしています。上記のソース冒頭に

\RequirePackage{pdfmanagement-testphase}
\DeclareDocumentMetadata
  {
    backend = dvipdfmx
  }

を足すことで,将来の状況を模したテストができるようです。しかし,実際にこれを pLaTeX または upLaTeX で処理してみると

! LaTeX3 Error: Invalid UTF-8 string: missing continuation byte (x3).

という LaTeX3 (expl3) の的外れなエラーが出ます。

 

何が起きている? expl3 の何が嬉しいの?

このように,LaTeX のコアを構成するコードを LaTeX3 (expl3) という新言語に置き換える方向性は,海外でどんどん進んでいます。これは

  • expl3 の方が TeX 言語よりも読みやすく,保守しやすい
  • expl3 がサポートする処理系 (e-pTeX, e-upTeX, pdfTeX, LuaTeX, XeTeX) どうしの差異を吸収し,クロス・エンジンなコード(共通化)ができる

といった,LaTeX パッケージの開発者側からするとありがたい側面がありますので,いわば当然の流れです。expl3 については wtsnjp さんによる素晴らしい解説がありますのでそちらに譲ります。

一方「expl3 がクロス・エンジンを実現する」ということは裏を返せば

expl3 自体の開発者がエンジンどうしの違いを全て知る必要がある

ということです。ここで日本ローカルの (u)pTeX が問題になります。

 

なぜ expl3 が (u)pTeX でうまくいかないか

hyperref の例で起きているエラーに立ち戻ってみましょう。エラーの根源をたどると,expl3 のモジュールの一つである l3str-convert から発せられています。詳細は述べませんが(というか正確に説明するのは私の理解レベルを超えるので),ソースファイルに書かれた文字列を PDF のメタデータに挿入するためには,通常のテキスト用文字コードUTF-8 など)ではなく PDF の仕様に即したコードに変換される必要があります。そこで文字コード変換が必要となり,それを担うのが l3str-convert というわけです。

ソースファイルによる入力は,l3str-convert によって最初に \tl_to_str:n (=\detokenize) による「文字列化」を受け,そこからコード変換されていきます。ところが,このコード変換が pdfTeX / LuaTeX / XeTeX のような欧文メインのエンジンでは大丈夫そうなのに,(u)pTeX の日本語文字が入った途端に破綻してしまっています。

さらに厄介なことに,そもそも「文字列化」に使われる \detokenize という e-TeX 由来のプリミティブが,pTeX において,入力ソースの 8-bit 欧文文字を勝手に和文文字に変身させてしまう現象も知られています(e-TeX 由来に限らず,素の TeX\meaning なども同様)。これでは,そもそも文字列自体が壊れてしまいます!

この欧文の 8-bit 文字が和文文字に化けてしまう「混同現象」は,8-bit 欧文を表すバイト列がたまたま日本語文字の EUC-JP / Shift-JIS でのコードパターンと合致した場合に起こります。これはマクロで頑張れば解決できる話ではなくなってしまいます。

 

expl3 の文字列関連エラーは他にも…

ここで気になるのは,expl3 への移行は hyperref に限ったことではなく,全体的な傾向として見られるということです。「文字コード変換が expl3 で出来る」となれば,今まで expl3 を使っていなかったパッケージが expl3 を使うようになって,結果的に「従来は (u)pLaTeX で使えたパッケージが突然動かなくなる」という可能性がないとは言えません。

上述の hyperref はまだ開発版扱いですが,すでに最近 expl3 に置き換わってエラーが発生している未解決例がありますので,ここで紹介します。それは「biblatex で参考文献一覧の置換テキストに日本語文字が入っているとエラーが出る」という現象です。

こちらも,biblatex のパッケージオプションに casechanger=latex2e を追加すると,expl3 のコードが使われず従来の LaTeX2e 方式となるため,不可解なエラーは出なくなるようです。

 

pTeX文字コード問題,欧文文字と和文文字の混同問題,そして…

さて,ここまでで2つの問題が露呈しました。

  • pTeX には「和文文字トークン」という概念が存在し,それは内部で複数バイトで1文字として格納されている。しかも,それが UTF-8 とは異なる文字コード (EUC-JP / Shift-JIS) の場合もある。従って,コード変換時に和文文字トークンの別扱いが必要であるが,この事実は海外の expl3 開発者に知られていない。
  • 現在の pTeX では,\detokenize, \meaning などの「文字列化」での和文と欧文が混同されてしまう。すなわち,上記の「和文文字トークンの別扱い」を実現するには pTeX 本体(バイナリプログラム)も修正が必要である。

後者は「今持っているバイト列がもともと欧文文字だったのか和文文字だったのか」という情報を pTeX に新たに記憶させるため,内部構造を大きく改造する大改修となります。テストを含めて多大な労力がかかり,もし運良く無事完了したとしても「バイナリの更新は年に一度」なので,早くとも pTeX が更新されるのは2022年4月頃…。つまり,例えば,2022年3月頃までに expl3 依存の文字列変換が増えてくると,pLaTeX は一巻の終わり…とまでは言えないまでも,よく分からないエラーや欧文→和文の混同文字化けが発生する可能性が高まります。

前者だけでも解決できれば,ある程度の挙動改善が可能だと踏んでいます(もともと日本で古くから pLaTeX を使っているユーザの中には,8-bit 欧文文字を直書きしていない方も多いでしょうから,そもそも混同されるものがないでしょうし)。ただ,和文と欧文の混同パターンは抜きにしても和文文字を別扱いにする」ために「和文文字かどうかを判定する方法」を expl3 開発者に教えてあげる必要があります。

 

(u)pTeX の英語ドキュメントの重要性

ドキュメントの重要性は,本ブログの前回記事でも指摘してきましたが,やはりここでも「海外向けの (u)pTeX の説明」がネックになってしまいました。

海外の LaTeX3 開発者が (u)pTeX を正しくサポートするためには,海外から見つかる場所に『(u)pTeX の実装・挙動を解説した英語ドキュメント』が必要です。ここで言う (u)pTeX の実装とは,たまに見かける*1ような「日本語の組版がどんなものか(和欧文間の xkanjiskip の話,約物の禁則やグルー挿入,縦組みがあること)」ではありません。expl3 は組版以前にプログラミング言語としての強い機能を提供するため,むしろ「和文文字トークンとは何か(入力ファイルのバイト列がどんな時に和文文字扱いされるか,その和文文字は内部でどう文字コード変換されるか)」という,より深いところを指します。これは日本語の文字コードの並立や,pTeX の長い歴史からくる複雑な問題をはらんでいて,海外の開発者には極めて理解されづらいところです。ここをどうやって伝えるか…。難しい課題です。

キーボード入力の障壁もあるのでしょうが,expl3 ではまだまだ「和文文字を入れた文字列」のテストは不十分なようです。過去(例: 2019年1月の regexpatch)にも expl3 のコードが和文文字でエラーになる例がありましたが,このようなケースは日本から報告して随時テストケースを増やしてもらう努力が必要だと感じています。

 

まとめ

以上のように,pLaTeX / upLaTeX は長年安定して使われてきましたが,この数年間の間に情勢は一変しています。特に「expl3 が (u)pTeX でうまく動かない影響で,(u)pLaTeX が壊れる/今まで使えたパッケージが動かなくなる」という可能性が,日に日に起きやすくなってきています。

  • LuaLaTeX への乗り換え … pLaTeX / upLaTeX のような「expl3 が (u)pTeX でうまく動かない影響で壊れる」というケースは避けられる。LuaTeX エンジン本体,luaotfload パッケージなどもある程度安定してきた印象。ただし,LuaTeX-ja のマクロの多くは pLaTeX / upLaTeX と類似しているので,そこが LaTeX の改修に追随する必要があることには変わりない。
  • 環境の保存(コンテナ化,古いバージョンのバックアップ) … 自分で管理する限り,挙動が変わらないことが保証される。ただし重要なバグ修正も含めて何も入ってこないことに注意は必要。

なども含め,それぞれの好みにあった対策を考え始める時期が来ていると思います。

*1:例えば,pTeX の初期の開発者である濱野さんの TUGboat 記事 "Vertical typesetting with TeX" や,Asian Journal of TeX の奥村先生の寄稿 "pTeX and Japanese Typesetting" などがあります。