マクロツイーター

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

TeX Live 2018 で日本語ファイル名するとアレ(1)

TeX Live 2018 において「入力エンコーディングの既定値を UTF-8 にする」という重要な変更が行われた(参考)。その副作用として、「LaTeX 起動時に、非 ASCII 文字を含む文書ファイル名を使うとエラーになる」という不具合が報告されている。

(不具合の例)
C>uplatex TeXはアレ.tex
This is e-upTeX, Version 3.14159265-p3.8.1-u1.23-180226-2.6 (utf8.uptex) (TeX Li
ve 2018/W32TeX) (preloaded format=uplatex)
 restricted \write18 enabled.
entering extended mode
! I can't find file `TeX'.
<to be read again>
                   \protect
<*> TeX
        ヘアレ.tex
(Press Enter to retry, or Control-Z to exit)
Please type another input file name: x
(c:/texlive/2018/texmf-dist/tex/latex/tools/x.tex
pLaTeX2e <2018-05-20u02> (based on LaTeX2e <2018-04-01> patch level 4)

本記事では、この不具合について、てきとーに書き流す。

※ソースファイル上での \input での読込については対象外。

アレは本当にソレのせいなのか

そもそも、(La)TeX における非 ASCII のファイル名の扱いはまだまだアドホックなところが多分に残っている。なので、この問題の対策に関しては、

  • UTF-8 既定化」が原因であるパターン
  • そもそも原理的に失敗するパターン

の見極めが必要である。例えば、WindowsTeX Live)上の XeLaTeX では非 ASCII のファイル名(例えば「xelatex TeXはアレ.tex」)は失敗するが、これは「UTF-8 既定化」とは無関係*1であり、最初から失敗するパターンに該当する。

アレの原因を調べる方法

非 ASCII のファイル名のエラーの原因が「UTF-8 既定化」であるかは以下の何れかの方法で調べられる。

  • TeX Live 2017 以前では同じコマンド起動が成功していたのであれば、「UTF-8 既定化」が原因である。
  • LaTeXlatex/platex/uplatex/pdflatex)の代わりに敢えて plain TeX(etex/eptex/euptex/pdftex)を起動してみる。例えば、「uplatex TeXはアレ.tex」の代わりに「euptex TeXはアレ.tex」を実行する。「UTF-8 既定化」が原因であるならば、plain TeX は指定のファイルを読み込むはず*2である。もちろん、“期待通り”読み込まれた場合は、先頭の「\documentclass」の箇所で「! Undefined control sequence.」のエラーになるだろう。((\documentclassLaTeX 専用の命令である。念のため。))

アレになるパターン

大雑把にいうと、「ファイル名のバイト列を inputenc が“欧文の UTF-8”として解釈しようとしたが、形式不正であった」という場合にエラーになる。

Windows な欧文 (pdf)LaTeX

※日本語版の Windows を仮定する。

pdflatex TeXはアレ.tex

Windows なので、ファイル名は SJIS で与えられる。*3inputenc の機構はこのバイト列を UTF-8 でデコードしようとするが、UTF-8 としては形式不正であるためエラーになる。

Windows な upLaTeX
uplatex TeXはアレ.tex

Windows なので、ファイル名は SJIS で与えられる。upLaTeX は非 ASCII 文字をまず UTF-8和文として解釈してみる((pTeX 系の場合は、まず「非 ASCII 文字を和文として解釈する」という過程が入る。例えば、Windows 上の「platex TeXはアレ」の場合は、まず SJIS和文として解釈してそれが成功するため、“欧文の UTF-8”として解釈される過程には進まないためエラーは発生しないのである。))が失敗し、次に、inputenc が欧文の UTF-8 としてデコードしようとして、形式不正であるためエラーになる。

コマンドラインの文字列については入力漢字コード(-kanji オプション)は適用されず、和文の解釈については、常に内部漢字コード(-kanji-internal オプション)が適用されるようである。TeX Live の upLaTeX の内部漢字コードは UTF-8 である。

Linux/macpLaTeX

※「ロケールUTF-8 である」と仮定する。

platex アレ

# または
platex -kanji=utf8 アレ

※先述の通り、入力漢字コード(-kanji)は無関係。

  • ロケールUTF-8 なので、ファイル名は UTF-8 のバイト列“E3 82 A2 E3 83 AC”で与えられる。
  • Linux/mac 上の TeX Live の pLaTeX の内部漢字コードは EUC である。従って、platex はこれを EUC和文として解釈してみる。
  • その結果、EUC として解釈できる“A2 E3”が和文“≪”と見なされ、残りは欧文のバイトとして扱われる。つまり“^^e3^^82≪^^83^^ac”となる。
  • これを inputenc が欧文の UTF-8 バイト列として解釈しようとする。
  • 元々は正当な UTF-8 のバイト列であったが、途中が和文に置き換わっているため不正であり、エラーになる。((具体的には、“^^e3^^82≪”の 3 トークンを(E3 が先頭の 3 バイトの列と見なして)“1 文字”として読んだ後、UTF-8 の非先頭バイトの^^83に引っかかる。))

ややこしい。

※なお、TeX Live 2017 以前の場合は、「inputenc が欧文 UTF-8 として解釈する」という過程は入らない。この場合、TeX エンジンは“^^e3^^82≪^^83^^ac”という名前のファイルを探索するが、その際に和文の“≪”は再び EUCエンコードされるため、結局「E3 82 A2 E3 83 AC」という元のバイト列に戻る。ロケールUTF-8 であるため、結果的に、OS が探すファイル名の文字列は期待通り「アレ」になる。

(続くはず)

*1:XeLaTeX・LuaLaTeX は当初から UTF-8 専用なので「UTF-8 既定化」の対象にならない。

*2:UTF-8 既定化」は LaTeX の方針なので、plain TeX は無関係である。

*3:正確にいうと、「コマンドラインの文字列を SJIS(CP932)でエンコードしたバイト列が argv に与えられる」ということ。