Open aminophen opened 6 years ago
私の経験上、 Windows上でminGWなどでコンパイルした場合、通常libtoolとやらが使われるらしく、その場合Unicodeファイル名をコマンドラインを通じて渡す方法が上手く動かないようです。 minGWでコンパイルする場合でもlibtoolを使わないように、直にリンクする形にしてバイナリを生成すると期待通りに動きます。 ソースコードの問題では無いと考えています。
e-pTeX 側で,関係しそうなチケットが作られたので貼っておきます:https://ja.osdn.net/projects/eptex/ticket/38246 (eptex #38246: 日本語ファイル名でエラー)
本質的な解決にはなりませんが,「名称未設定-1.tex」なる名前を付けているのは“統合環境”である可能性が高いです。多分新しいファイルを作るとデフォルトでそうなるんだと思いますが,そこは日本語化しなくていいと思います。改修してもらうことはできないでしょうか?
TeXworks は untitled-1.tex ですが,TeXShop とか,TeXstudio とかはよく知りません。
標準的なmacOSのマルチドキュメントアプリは,英語環境で起動すれば Untitled-1
,日本語環境で起動すれば 名称未設定-1
というように,各言語環境に応じた既定のファイル名が割り当てられます。これは,意識的にそのようにローカライズしているというより,新規ドキュメントウィンドウを作成する際にOSの側から勝手に割り当てられます。
コマンドライン引数のエンコーディングと処理されるファイルのエンコーディングが違う場合に困ったことになるということでしょうか? そうだとすれば,単純にそれぞれのエンコーディングを個別に指定する方法があればよいのではないでしょうか? 見当違いでしたらすみません.
手元にmacOSは無いので、現象から想像してコメントします。
コマンドライン引数のエンコーディングと処理されるファイルのエンコーディングが違う場合に困ったことになる
おそらくこの理解で合っていると思います。
macOSの場合、コマンドラインはUTF-8前提になっていると思います。
pTeX の (utf8.euc)
の場合、内部コードはEUCです。
macOSかつpTeXの場合、コマンドライン引数は特段の手当てをしておらず文字コード変換もしていないので、文字化けで処理が止まっても不思議ではありません。
WindowsかつpTeXの場合、コマンドライン引数は Shift_JIS 決め打ち、内部コードも Shift_JIS 決め打ち、テキスト入力は (utf8.sjis)
ならコード変換して内部処理に回ります。
Unix/Linux系でも同様の機構を入れれば、本質的な解決になると思います。
ロケールを見て自動的に切り替えられると美しいかもしれません。
あるいは、Windows のように texmf.cnf
の command_line_encoding
で変換するコードを決めてもいいかもしれません。
あるいは、pTeXの (utf8.euc)
の場合にはコマンドライン引数も UTF-8 → EUC-JP の変換をするようにしてもいいかもしれません。
「アレ.tex」がカレントにある時に: ・「ptex アレ」はそのファイルを見つける (←チョット意外)
これは、Unix系では、kpsewitch のファイル検索とオープンはただのバイト列と見做して行うので pTeXの内部コードにかかわらず、バイト列の照合・オープンが成功するためだと思います。
私なぞがここに書き込んでいいのか悩みましたが解決の糸口になればと… Linux Mint 上で TeX Live 2018 を使っています(apt ではなく install-tl-unx.tar.gz を用いてのインストール) 名称未設定-1.tex を platex で処理した場合にエラーとなるのは
区 点 jis sjis euc utf-8 utf-16 30 46 3E4E 8FCC BECE E7A7B0 79F0 称 という文字が原因のようです 周辺の漢字を調べてみると
30 40 3E48 8FC6 BEC8 E785A7 7167 照 30 41 3E49 8FC7 BEC9 E79787 75C7 症 30 42 3E4A 8FC8 BECA E79C81 7701 省 ---------↑エラー出ず----↓エラー------ 30 43 3E4B 8FC9 BECB E7A19D 785D 硝 30 44 3E4C 8FCA BECC E7A481 7901 礁 30 45 3E4D 8FCB BECD E7A5A5 7965 祥
という結果になりました
@t-tk 「texmf.cnf の command_line_encoding」は,この記事のことでしょうか? https://oku.edu.mie-u.ac.jp/tex/mod/forum/discuss.php?d=397&parent=6867
@t-tk 「texmf.cnf の command_line_encoding」は,この記事のことでしょうか?
そうです。 それと似たような方法で実現可能だと思います。 コードの修正案があれば、ここにプルリクエストを出していただいてもよいと思います。
ロケールを見て文字コードを判別するやり方について、↓のような記事を見つけました。 ファイル名の文字コード
個々のプロセスがどういうlocaleで動くかは自由です。プロセスがオンメモリでファイル名をどんな文字コードで持つか(LC_CTYPE)や、どんな順序で見せるか(LC_COLLATE)などは、ファイルシステム上のファイル名がutf-8であることとは独立です。
そうすると、ファイルシステム上のファイル名がどの文字コードであるか、自動的に判定する方法は無いという事になります。うーむ。 似たような要求がある場合他のソフトではどうしているのでしょうか?
以前私の書いた
あるいは、pTeXの
(utf8.euc)
の場合にはコマンドライン引数も UTF-8 → EUC-JP の変換をするようにしてもいいかもしれません。
も問題で、「入出力ファイルの中身がUTF-8であること」と「ファイルシステム上のファイル名の文字コード」とは必ずしも同じではないので、良い方法ではなかったです。
「正しい仕様」についてご意見ありましたらお願いします。
最近 TeX Live ML で pdfTeX, Windows でnon-asciiのファイル名の話題が出ています。 角藤さんがupTeX, XeTeXと同じ方法で対応してくれたそうです。 [tex-live] TL2018: Problems with filenames 欧文(La)TeXの場合、今後 「ソースはUTF-8で書く。TeX独自の8bitエンコーディングは従来通りの扱い。」という方向でしょうから好ましい方向だと思います。 ソースファイル内で8bitの一部がアクティヴ文字化されている場合なども上手く動くのかなど、興味があります。動向を見守りたいと思います。
p(La)TeX + ptexencの場合、ソース上はUTF-8でもpTeXエンジンに渡るときにはSJIS/EUCに変換済みなので、そっくり同じには出来ないと思います。
pTeX + ロケールが utf8 で日本語ファイル名の対応について、手元でソースをいじりつつ実験しています。 大体動くところまでは来ましたが、所詮弥縫策の感は拭えません。 仕様について以下のように考えています。ソースはもう少し整理したらご紹介します。
terminal_enc
と一致していることを仮定する。
設定用のスイッチは今回の改造のためには用意しない。
大多数の通常のケースでは通用するはず。結局、Unicode→JIS→Unicodeの変換をすることになるので、変換表のゆらぎ問題の影響がもろに出ます。
完璧な仕様を作ること自体難しく、それなりの仕様にしたとしても実装はややこしくなりそうです。
Windowsで採用しているcommand_line_encoding
の機能では Windowsが持っている関数を用いてkpathseachの奥深くでコード変換しています。
kpathseachは文字コード変換にかかわるコードは含んでおらず、今回同じ手は使えません。
何となくですが、
がゴッチャになっている気がします。
https://ja.osdn.net/projects/eptex/ticket/38246 (eptex #38246: 日本語ファイル名でエラー)
ここで挙げられているのは純粋に 2 の問題であるような気がしますが、それで合ってるでしょうか?
つまり、macOS/Linuxにおいて、以下の言明は成り立つでしょうか?
TL2017で、platex 名称未設定-1.tex
は期待通りの動作をする。
TL2018でも、アクティブ化を回避すれば期待通りの動作をする。
platex "\UseRawInputEncoding\input 名称未設定-1"
platex "\input\detokenize{名称未設定-1}"
https://ja.osdn.net/projects/eptex/ticket/38246 (eptex #38246: 日本語ファイル名でエラー)でもコメントしていますが,そこでの元々の話は
TL2018で導入された「UTF-8既定化」の副作用
によるものだと思います.手元の Linux で調べてみました:
$ platex "名称未設定-1.tex"
This is e-pTeX, Version 3.14159265-p3.8.1-180226-2.6 (utf8.euc) (TeX Live 2018) (preloaded format=platex)
restricted \write18 enabled.
entering extended mode
! I can't find file `�^^90^^8d腱井'.
<to be read again>
\protect
<*> �^^90^^8d腱井^^9c
┃絎^^9a-1.tex
(Press Enter to retry, or Control-D to exit)
Please type another input file name: x
(/opt/texlive/2018/texmf-dist/tex/latex/tools/x.tex
pLaTeX2e <2018-05-20> (based on LaTeX2e <2018-04-01> patch level 4)
$ platex "\UseRawInputEncoding\input 名称未設定-1"
This is e-pTeX, Version 3.14159265-p3.8.1-180226-2.6 (utf8.euc) (TeX Live 2018) (preloaded format=platex)
restricted \write18 enabled.
entering extended mode
pLaTeX2e <2018-05-20> (based on LaTeX2e <2018-04-01> patch level 4)
(./�^^90^^8d腱井^^9c┃絎^^9a-1.tex
(/opt/texlive/2018/texmf-dist/tex/platex/base/jarticle.cls
Document Class: jarticle 2018/02/04 v1.7h Standard pLaTeX class
(/opt/texlive/2018/texmf-dist/tex/platex/base/jsize10.clo))
(./�^^90^^8d腱井^^9c┃絎^^9a-1.aux) [1] (./�^^90^^8d腱井^^9c┃絎^^9a-1.aux)
)
Output written on �^^90^^8d腱井^^9c┃絎^^9a-1.dvi (1 page, 292 bytes).
Transcript written on �^^90^^8d腱井^^9c┃絎^^9a-1.log.
$ platex "\input\detokenize{名称未設定-1}"
This is e-pTeX, Version 3.14159265-p3.8.1-180226-2.6 (utf8.euc) (TeX Live 2018) (preloaded format=platex)
restricted \write18 enabled.
entering extended mode
pLaTeX2e <2018-05-20> (based on LaTeX2e <2018-04-01> patch level 4)
(./�^^90^^8d腱井^^9c┃絎^^9a-1.tex
(/opt/texlive/2018/texmf-dist/tex/platex/base/jarticle.cls
Document Class: jarticle 2018/02/04 v1.7h Standard pLaTeX class
(/opt/texlive/2018/texmf-dist/tex/platex/base/jsize10.clo))
(./�^^90^^8d腱井^^9c┃絎^^9a-1.aux) [1] (./�^^90^^8d腱井^^9c┃絎^^9a-1.aux)
)
Output written on �^^90^^8d腱井^^9c┃絎^^9a-1.dvi (1 page, 292 bytes).
Transcript written on �^^90^^8d腱井^^9c┃絎^^9a-1.log.
(pTeX の内部コードが EUC なので「名称未設定-1」が「�^^90^^8d腱井^^9c┃絎^^9a-1」に化けるのは仕方がないことだとは分かっていますが,この文字列はバイト列としてそのまま端末に出力する」みたいなフラグを導入すれば良い??)
なるほど。今まで 1 がさほど問題にならなかったのは 2 がなければ顕在化しないケースが多かったからでしょうね。 しかし、
platex "\UseRawInputEncoding\input 名称未設定-1"
platex "\input\detokenize{名称未設定-1}"
は、出来れば
platex 名称未設定-1.tex
の方が分かりやすいでしょうし、platexのソースコード内で \input{日本語ファイル名.tex}
が使えたほうが良いでしょうし、 1 の改良をすれば自然と 2 が解決するはずなのでその方が良いでしょう。
ブランチ https://github.com/texjporg/tex-jp-build/tree/ptex-filename に試作品を示します。
ptexenc の中で terminal_enc
がUTF-8の時に以下を実行します。
nameoffile+1
) をコード変換
nameoffile+1
に再格納する前にUTF-8変換→内部コード変換メッセージやログなどに文字化けが残っていますが、見掛けだけの話で動作に支障は無いと思います。
画像ファイル名は対策できていません。
コマンドライン変数の乗っ取りは-kanji-internal
の切り替えに対応していません。(順序の問題)
いかがでしょうか。
>h-kitagawa さん
手元の Linux で調べてみました:
ありがとうございます。
>t-tk さん
platexのソースコード内で \input{日本語ファイル名.tex} が使えたほうが良いでしょうし、 1 の改良をすれば自然と 2 が解決するはずなのでその方が良いでしょう。
これはその通りだと思います。
あと、2 の方の問題はpTeX系に限った話ではなくて、世界中のWindows(コマンドラインがUTF-8でない)で同様の問題が起こる(参考)ので、そちらはLaTeXチームにより対処が行われることが期待されます。
2の問題に関して、気になっているのは次のようなケースです。
% pdflatex; Linux; UTF-8
%\UseRawInputEncoding %←これがないとエラー
\documentclass{article}
\begin{document}
\input{Begrüßung}
\end{document}
% uplatex; Linux; UTF-8
%\UseRawInputEncoding %←これがないとエラー
\documentclass{article}
\begin{document}
% <ü><ß>は欧文扱い
\input{ドイツ語-Begrüßung}
\end{document}
これも、pTeX系に限らない話であるため、近いうちにLaTeXチームによって対処される可能性が高そうです。
欧文LaTeX と UTF-8規定化問題でも、問題点がごっちゃに語られているように思います。
世界中のWindows(コマンドラインがUTF-8でない)で同様の問題が起こる
これは、1の方の問題で、pdfTeX に角藤さんが command_line_encoding
の機能を導入してくださったので、解決済みと思います。
(command_line_encoding=utf-8
でコードページにかかわらずファイル操作でUnicodeの関数を直接使うようになる)
レガシーエンコーディング志向の人がロケールUTF-8のLinux/MacOS上でpdfTeXを使ったら依然解決していないと思います。
2 の問題は、upLaTeX + ロケールUTF-8のLinux/MacOS でも発生するのですね。「近いうちにLaTeXチームによって対処される」のに期待したいと思います。
「pLaTeXで画像ファイル名」の方はどうしましょう。 W32TeX では角藤さんが最近 pdvipdfmx, pdvips などを追加したり、dviwareの改造を試みたりされているようです。 別解として、pLaTeXがdviに書き込むファイル名自体を UTF-8 にすることは出来ないのでしょうか。
別解として、pLaTeXがdviに書き込むファイル名自体を UTF-8 にすることは出来ないのでしょうか。
specialの中のファイル名がUTF-8だったら、「command_line_encoding=utf8
なWindows」でも「UTF-8ロケールのLinux/macOS」でも、dvps/dvipdfmxがファイルを見つけられる、ということでしょうか。
だとすれば、「ソースをUTF-8で書く場合の欧文(pdf)LaTeX」と解決を共有できそうなんで好ましそうです。
(今更ですが)
このIssueの発端となっている
W32TeX では成功しているのに,TeX Live では upTeX で失敗するケースがあるという報告があります。
という現象の原因は、単に
command_line_encoding
の設定が両者で異なる。W32TeXはutf8
が設定されていて、TeX Liveは未設定。TeX Lvieでもutf8
を設定するとW32TeXと同じ挙動になる。ということでした。
自分が調べた限りだと、「command_line_encoding=utf8
を設定していて害になる」パターンは、「欧文(pdf)LaTeXでソースをレガシー8ビットな文字コードで書いている」場合しかなさそうです。TeX Liveも「UTF-8既定化」に踏み切ったくらいなんだから、command_line_encoding=utf8
を既定にしてもよいのかも知れません。
W32TeX では成功しているのに,TeX Live では upTeX で失敗するケース
command_line_encoding
の設定の差異によると判明したのこと、了解しました。
想定通りの動作で安心しました。
「
command_line_encoding=utf8
を設定していて害になる」パターン
「Windows, ShitJISでp(La)TeXを使う人がdvips, dvipdfmxにcommand_line_encoding=utf8
を与えると、8bitの画像ファイル名が読み込めなくなる」
というのがあったと思います。
command_line_encoding=utf8
を既定にしてもよいのかも知れません。
角藤さんが最近 pdvipdfmx, pdvips などを追加したり、dviwareの改造を試みたりされているのは、command_line_encoding=utf8
を既定にする方向を考えておられると想像しています。
というか、もうすでになっている?
specialの中のファイル名がUTF-8だったら、「command_line_encoding=utf8なWindows」でも「UTF-8ロケールのLinux/macOS」でも、dvps/dvipdfmxがファイルを見つけられる、ということでしょうか。
私の予想ですが、そういう意図です。
欧文TeX の場合、レガシーエンコーディングの時代の多数派は「エンジンの内部コードはT1などのTeX独自8bitエンコーディング、入出力ファイルはLatin-1、コマンド行など外部はLatin-1、specialの文字列はTeX 8bitエンコーディング」だったと思います。 従来でも「TeX 8bit→Latin-1」のコード変換が必要な場面はあったし、最近の環境向けには「TeX 8bit→UTF-8」のコード変換が必要な場面がありそうに思えるのですが、どうなっているのでしょうか? pTeXの場合は、そこが「EUC/SJIS→UTF-8」に置き換わるのだと予想しています。
「ソースをUTF-8で書く場合の欧文(pdf)LaTeX」と解決を共有できそう
似ている点とpTeX独自な点がありそうで、調べた方が良さそうです。(ややこしそう…)
LANG=ja_JP.utf8のLinuxで簡単なテストをしました。
弌丐丕.eps
("弌丐丕"はEUCで D0 A1 D0 A2 D0 A3) と
СТУ.eps
("СТУ"はUTF-8で D0 A1 D0 A2 D0 A3) をカレントディレクトリに置き
下記のplatexソースを先日の改造版 https://github.com/texjporg/tex-jp-build/tree/ptex-filename で試してみました。
% platex (utf8.euc), Linux, LANG=ja_JP.utf8 でテスト
\documentclass{article}
\usepackage{graphics}
\begin{document}
\includegraphics{弌丐丕.eps}
\end{document}
結果はこうなりました。
弌丐丕.eps
を読みに行く弌丐丕.eps
ではなくСТУ.eps
を取り込もうとする1は先日の改造の効果が現れています。
Master/texmf-dist/source/latex/graphics のソースをざざっと眺めた感じでは
drivers.dtx の中の \Ginclude@eps
を改造しファイル名の EUC→UTF-8のコード変換をした後\special
に渡すようにすれば直感的な動作になるような気がします。
ファイル名のみを選択的にコード変換することが出来るのでpTeXエンジンやdviware側を改造するよりも筋が良さそうに思います。
Windows, dvipdfmxでのダメ字問題も同時に回避できるはずです。
「\special
を受けてからdviに書き込むまでの間で pTeX エンジンがコード変換する」という案もありそうですが、\special
の文字コードを決め打ちすると副作用が出るような気がします。あるいは、逆に好都合なことも起きたりするのでしょうか?
WindowsのpdfTeX への command_line_encoding
の導入は、角藤さんから撤回するとの連絡をいただきました。
以前の議論の続き。 問題の切り分けについて、2個ではなく3個に分けて考えた方が分かりやすいと考え直しました。
1は、LaTeXチームの対策待ちです。
2は、「ロケールutf8のLinux/MacOS」とWindowsで共通の課題のはずです。
3は、command_line_encoding
で解決しようとしている点です。
2は、pdfTeXとpTeXで仕様上似ている点とそうでない点があり、 pdfTeXで過去どこまで出来て今何が出来ないのかなどよくよく理解しないと先に進めそうにありません。さてどうするか。
pdfLaTeXで色々テストしてみました。 まずは、かなり旧いlinuxのpdfLaTeX(This is pdfTeX, Version 3.1415926-1.40.10 (Web2C 2009), LaTeX2e <2009/09/24>)です。 下記のようなLatin-1 (ISO-8859-1)で書かれたfileA.tex, UTF-8で書かれたfileB.texを用意し、 ロケールがISO-8859-1のもと、UTF-8のもとでpdfLaTeXを起動しました。 結果は以下のとおりでした。
schön.tex
, schön.jpg
, schön.png
, schön.pdf
に見えるファイルを読み込み、正常終了した。schön.tex
, schön.jpg
, schön.png
, schön.pdf
に見えるファイルを読み込み、正常終了した。schön.tex
, schön.jpg
, schön.png
, schön.pdf
に見えるファイルを正常に読み込ませるためには、Latin-1のソース上でschön.tex
, schön.jpg
,schön.png
,schön.pdf
と指定する必要があった。\detokenize
はいずれの場合も必要。\str
の文字列を与えようとすると、\str
はLatin-1でもUTF-8でもなく T1 エンコーディングの8bit文字列となって版面に現れた。1は、レガシーエンコーディング時代の標準的な使い方、2は最近の標準的な使い方で、直感的に期待通りの動作になっています。 3は、ロケールがUTF-8だがソースコードはLatin-1で書きたいと考える人にとっては直感的ではないかもしれませんが、「Linuxではファイル名はただのバイト列である」という観点からすれば予想通りの動作です。逆に、ソースコードはUTF-8だがロケールはISO-8859-1で実行する場合にも同様の見掛け上の不整合が出ます。しかし、そういう状況はサポートする立場としては考慮しなくてよいでしょう。 LinuxのpdfLaTeXは、かなり昔から「ファイル内の文字コード、ファイル名の文字コード、ロケールの文字コードが全て一致している場合に直感的に期待通りの動作をする」状態だったと言えます。
次に、UTF-8で書かれたfileB.tex を日本語Windows (CP932), W32TeXの2018/06/01の版(command-line-encoding
がない状態、LaTeX2e <2018-04-01> patch level 5)で試しました。
結果は次のようになりました。
schön.jpg
, schön.png
, schön.pdf
の代わりにschテカn.jpg
, schテカn.png
, schテカn.pdf
にアクセスしようとする。そういうファイル名が用意されていれば正常終了する。\input
のファイル名は、一度目のコンパイルではschテカn.tex
が読み込まれ一見成功したように見えるが、二度目のコンパイルを行うとエラーで落ちる。"ö"のUTF-8のバイト列はC3 B6であり、CP932の"テカ"のバイト列はC3 B6 なので、Windowsでは、ソースで与えたファイル名が8ビット文字列として渡り、さらに各国語Windowsのコードページで解釈されているようです。欧州版WindowsのCP1252の場合はschön.*
を読みに行くと思われます。
おそらく、現状は「ソースコードをLatin-1で書きWindowsはCP1252」というレガシーエンコーディング時代の標準的な使い方では8bitの画像ファイル名は正常に扱えるが、\input
のファイル名の扱いは完全では無い」という状況と思われます。
今後の標準として期待されるのは「ソースコードをUTF-8で書きWindowsのCPに依存しない」だと思うので、enhanceが期待されるところだと思います。
pdf取り込み時に使われるpopplarのソースも眺め始めましたが、「Windows上では稼働中のCPとUnicodeの文字コード変換を行う」という感じの機能はまだ実装されていないようです。
解決策はいくつか考えていますが、行き当りばったりの開発にならないようもうちょっと考えてみます。
fileA.tex:
% -*- coding: latin-1 -*-
\makeatletter
\ifx\str\@undefined
\def\str{undefined}
\fi
\documentclass{article}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphics}
\begin{document}
Happy \TeX-ing!!
str: \str
\typeout{str: \str}
\typeout{Schön}
%%%
%%% locale: ISO-8859-1
%%% ö : 0xF6
\input{\detokenize{schön.tex}}
\includegraphics{\detokenize{schön.jpg}}
\includegraphics{\detokenize{schön.png}}
\includegraphics{\detokenize{schön.pdf}}
%%%
%%% locale: UTF-8
%%% ö : U+00F6, UTF-8 0xC3 0xB6
%%% Ã:0xC3, ¶:0xB6 in Latin-1
%%%\input{\detokenize{schön.tex}}
%%%\includegraphics{\detokenize{schön.jpg}}
%%%\includegraphics{\detokenize{schön.png}}
%%%\includegraphics{\detokenize{schön.pdf}}
\end{document}
fileB.tex:
% -*- coding: utf-8 -*-
\makeatletter
\ifx\str\@undefined
\def\str{undefined}
\fi
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphics}
\begin{document}
Happy \TeX-ing!!
str: \str
\typeout{str: \str}
\typeout{Schön}
%%%
%%% locale: UTF-8
%%% ö : U+00F6, UTF-8 0xC3 0xB6
\input{\detokenize{schön.tex}}
\includegraphics{\detokenize{schön.jpg}}
\includegraphics{\detokenize{schön.png}}
\includegraphics{\detokenize{schön.pdf}}
\end{document}
ファイル名の問題で pdfTeX と pTeX の場合の障害となっているところを検討してみましたが、 似て非なる部分が多く対策を共通化できる部分はあまり無い、という結論になりました。 https://github.com/texjporg/tex-jp-build/tree/ptex-filename は TeX Live svn にコミットr47967しました。
ロケールUTF-8のUnix系プラットフォームにおけるpLaTeXの画像ファイル名については、今回のコミットにより次の状態になります。
この問題の解決策として、W32TeX で 2018/05/26 に導入された allow5c.exe
と似た方法が良いと今は考えています。すなわち dvispc
で dvi をテキスト形式に変換し special の文字列を適切に変更した後再度 dvi に書き戻す方法により、不整合な部分を書きなおしてしまうというやり方です。
dviファイルと可読テキストファイルの相互変換が出来るソフトウェアは
dv2dt/dt2dv
がありTeX Liveに含まれているがpTeXに未対応dvispc
はpTeXに対応しているがTeX Liveに含まれていないという状況にあります。
dvispc
は今回の目的以外にも有益な場面はあるようですし @aminophen さんがパッチをMLに投稿 されたりしているので管理元 texjp-org として TeX Liveへの導入を進めるのがいいんじゃないかと思います。
原作者の大島先生のところにお伺い、コンパイラーの警告のチェック、autoconf/automake 対応、それなりに作業は発生します。一度出来てしまえばメンテナンスは重くないと予想します。
あるいはdv2dt/dt2dv
をpTeX対応にする方向もあっさり行けるかもしれません。
いかがでしょうか。
多忙につき一ヶ月近く全く反応できていなくてすみません。
TeX Live svn にコミットr47967しました。
ありがとうございます。後日になりますがテストしてみます。
dvispc は今回の目的以外にも有益な場面はあるようですし @aminophen さんがパッチをMLに投稿 されたりしているので管理元 texjp-org として TeX Liveへの導入を進めるのがいいんじゃないかと思います。
私も,許諾されるならその方向がいいと思っていました。dvispc の開発版(2003 年のものから比べると色々な special に対応)は https://github.com/aminophen/dviout-util にあります。allow5c.exe のソースも,具体的に何をやっているのかもまだ確認できていないのですが,dvispc 自体にそういうモードを組み込んでもいいかもしれません。
dv2dt/dt2dvがありTeX Liveに含まれているがpTeXに未対応
dvispc は大島先生のドキュメントによると dv2dt/dt2dv より高速だそうです(私自身では確認していませんが)。個人的には,dv2dt/dt2dv よりも dvispc の方がテキスト形式の可読性が高く気に入っています。
なわち dvispc で dvi をテキスト形式に変換し special の文字列を適切に変更した後再度 dvi に書き戻す方法により、不整合な部分を書きなおしてしまうというやり方です。
ワークフローが変わってしまうのは、当然ながら、(u)pTeXの周辺ツールに対する影響が非常に大きいためできる限り避けるべき事態でしょう。このような結論に(残念ながら)なってしまった経緯をもう少し知りたいところです。
結論に(残念ながら)なってしまった経緯
うーん、私としては上に書いた以上の根拠があるわけではありません。 現状「pLaTeX、Unix系のUTF-8ロケール、non-asciiの画像ファイル名」は使えない状況なので、 ワークフローを変更するという意識はなく「使えないものを使えるようにするためにワークフローを作る」という感覚で考えていました。
思いついた案を並べると、
\Ginclude@eps
を改造しファイル名の EUC→UTF-8のコード変換をした後\special
に渡すようにするdvispc
で dvi をテキスト形式に変換し special の文字列を適切に変更した後再度 dvi に書き戻す3は、ソースを眺めてみましたが相当難しいと感じました。
4は、可能でしょうがpTeXだけのための変更でdviwareの開発元に負荷を掛けてしまうのが懸念で気が乗りません。それをやるくらいなら私は5を推します。
2は、dvispc
そのものやそれを使うフローが今回の件以外にも利用可能なような気がして道を作っておく価値があるかなと思いました。
1は、マクロのスペシャリストの手に掛かれば2よりも簡単なような気もします。pTeXは\ucs
相当のプリミティヴが無いので、例えばe-pTeXにupTeXの\ucs
を移植するとか、shell-escapeを使うとか、いくらでも道はあると思います。
「使えないものを使えるようにするためにワークフローを作る」という感覚で考えていました。
「選択肢を与える」という考え、了解です。「texmf.cnfのパラメタを変えれば、勝手に上手くいくようになる」という方が望ましいのは当然ですが、それは理想を求めすぎたようです。
(“オレの理想”の話)
自分としては、
「ファイル名をバイト列として扱うのが問題の根源であり、代わりに、(論理的な仕様として)ファイル名をUnicode文字列として扱う(と考えた上で内部実装を決める)べきである」
と考えています。最近のTeXエンジン側の改修はこの方針に沿うものだと思っています。そうすると、今度はDVIウェアもそうなってほしいわけです。もちろん、DVIファイル(special命令)はバイト列なので、「環境に依存せずに文字列を一意にバイト列で表す方式」が必要になる。で、その方式として最も相応しいのは「UTF-8にすること」かな、と考えています。
※PDF文書情報を表すPDF文字列リテラル形式の中ではUTF-16BEが使われるが、special中のファイル名の表現は必ずしもPDF文字列リテラル形式ではないので、UTF-16BEの使用は難しい。
改めて考えると、今示されている方針は(Unix的OSに限ると)「DVIウェアの動作は買えずに、special命令の中のファイル名をUTF-8に変える方策を考える」ということなので、結局“オレの理想”とも一致しているといえそうです。
今回と似た課題で「(u)pLaTeXエンジンの処理後、dviwareを経由してpdfのしおりを作成する際、文字コードを整合させる」というものがありました。
upLaTeX では、*.out
にUTF-8で書き込まれるのでdvipdfmxの中でUTF-8からUTF-16BEに変換する動作があると便利です。XeTeX→xdvipdfmxにはその動作があります。
そこで、upLaTeX向けにそのルーチンをxdvipdfmxからdvipdfmxへ移植させてもらおうとしましたが、2011年にupTeXをTeX Liveに取り込んでもらう作業中にrejectされました。その理由は、8bit欧文の動作に影響が出るのとCMapを使う方法で代替出来るためと聞いた記憶があります。
代わりに、convbkmk.rb の開発を推進し、upLaTeXが吐いた*.out
を書き換えるフローを推奨することになりました。
さらにその後dvipdfmxとxdvipdfmxが統合されたので、現在該当のルーチンは dvipdfmx のバイナリーには含まれているが dvipdfmx のコマンド名のときは機能が無効の状態になっています。
dvipdfmxにオプションをつけて機能させることは今なら簡単ですし、オプション付きならrejectされないような気もします。
得た教訓は次の通りです。
pdfTeXのWindows版のUTF-8対応については、
command_line_encoding=utf8
を復活させ、TeX Live svn への一連のコミット(r48000まで)でUnix系のUTF-8ロケールの動作とほぼ同等になるようになったようです。
下記のfileC.tex とほぼ同等の例でW32TeXの2018/06/16の版でテストしました。
LaTeX2e <2018-04-01> patch level 5, command_line_encoding=utf8
指定ありです。
\typeout{}
は \detokenize{}
を伴えばnon-asciiのUTF-8の文字列が正しくコンソールに出力される\input{}
は \detokenize{}
を伴えばnon-asciiのUTF-8のファイル名が正しく処理される\include{}
はnon-ascii.tex, non-ascii.aux を読み込むことを期待するが、\detokenize{}
を付加してもauxの読み込みに失敗する。これはWindowsに限らず、Windows, Unix系共通\detokenize{}
を伴えばnon-asciiのUTF-8のファイル名が正しく処理される
ただし、Windowsではpdfファイル名は一度レガシーエンコーディングに再変換した後xpdfに渡すため各国語版Windowsのコードページの範囲内の文字に限定される。jpg, pngはその制限が無い。試していませんが、西欧版Windows (CP1252) でcommand_line_encoding=none
指定ありでソースを\usepackage[latin1]{inputenc}
あり、latin-1で記述した場合も同様の結果が得られるはずです。
pdf(La)TeXの方は完璧でない部分もまだありますがここで一段落と思います。
fileC.tex:
% -*- coding: utf-8 -*-
\makeatletter
\ifx\str\@undefined
\def\str{undefined}
\fi
\makeatother
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\begin{document}
Happy \TeX-ing!!
str: \str
\typeout{str: \str}
\typeout{\detokenize{Schön}}
%%%
%%% locale: UTF-8
%%% ö : U+00F6, UTF-8 0xC3 0xB6
\input{\detokenize{schön.tex}}
%\include{\detokenize{schön}}% schön.tex, schön.aux を読み込むことを期待
\includegraphics[width=30mm,bb=0 0 550 568]{\detokenize{schön.jpg}}
\includegraphics[width=30mm,bb=0 0 550 568]{\detokenize{schön.png}}
\includegraphics[width=30mm,bb=0 0 550 568]{\detokenize{schön.pdf}}
\end{document}
TeX WikiのW32TeXの漢字入力対応状況を更新しました。 allow5c.exe, pdvipdfmx, pdvips についても書くべきだと思うのですが、動作の理解があやふやなので今回見送りました。
上記で述べた「 dvispc
で dvi をテキスト形式に変換し special の文字列を適切に変更した後再度 dvi に書き戻す」について、convbkmk に機能を追加する方向で試しています。
convbkmk の --dvi-special オプション追加 https://github.com/t-tk/convbkmk/issues/1
https://github.com/t-tk/convbkmk/tree/develop
ご意見などありましたらお願いします。
convbkmkへの --dvi-special オプション追加の件、リリースしました。 https://github.com/t-tk/convbkmk/releases/tag/v0.30 CTANへは明日か明後日には反映されるでしょう。
Unix系環境では、これをもってpLaTeXの日本語ファイル名問題は解決したはずです。
(ただし波ダッシュ問題は対応しない。)
また、今回の追加機能はWindowsでも allow5c.exe
と似た狙いなので allow5c.exe
の代用として役立つかもしれません。(未検証)
別解として、同様の機能を dvispc側で持つことも可能だと思います。
一応今回の開発項目は完了と思いますので、そろそろここを閉じようと思います。 ただし、pLaTeXでの日本語ファイル名の文字コード不整合問題は、開発サイドの労が多い割には得るものが少ないので、以下の立場を再確認しておきたいと思います。 convbkmkの新機能も実験的機能として積極的な宣伝はしないことにします。
https://twitter.com/cloudlatex/status/1253910060972912646
pTeX / e-pTeX で ASCII / JIS X 0208 以外の文字を含むファイル名をコンパイルするのは動作未定義だとは思いますが,一応現象だけ共有しておきます。(non-Windows です。)
! I can't find file `a?^^91^^a0.tex'.
前者の挙動は不穏な気がします。
ほんとだ,こちらの TeX Live 2020 でも確認.
ファイル名 "a①.tex" TeX Live 2019 / 2020: ! I can't find file `a?^^91^^a0.tex'.
参考までに,ここの ?
は単独の 0xE2 です.
また,実際には a.tex を探しにいっているようです(4/25 20:48 edit).
pTeX ではファイルを開く際に,内部コードでファイル名が格納されている nameoffile+1
(+1
は先頭バイトを無視するため)を UTF-8 に変換しています.
しかし a①.tex
のケースでは,その nameoffile+1
の中身が a[e2][91][a0].tex
と,①
を UTF-8 で表したバイト列 [e2][91][a0]
がそのまま残ってしまっています.これを UTF-8 に変換する際に,EUC にない [e2][91]
はヌル文字に変換されてしまうので,「変換後」のファイル名は a
のみ(拡張子も消える)になってしまいます.
https://github.com/h-kitagawa/tex-jp-build/commit/7e3eff73b543fb7b8e8ddb9313004b283667891 で対応してみました.
https://twitter.com/cloudlatex/status/1253910060972912646 で、
症状としては Cloud LaTeX 内で、Windows 10 Chrome 最新版にて確認しております。
とあるのですが、(u)pTeX エンジンが動いているのはWindowsでは無いのですね。分かりにくい。 おそらく くUnix/Linux系でロケールがUTF-8なのでしょう。 であれば、ファイル名 "①.tex" が TeX Live 2018 で動いていたが TeX Live 2019 で動かなくなったとは、まさにここの Issue で変更した部分に当たっていると思います。 TeX Live 2019以降で意図していた「Unix/Linux系でロケールがUTF-8の場合、pTeXはJIS X 0208の範囲内では動く」という方針自体はよいと思っています。 今回の件では、その範囲を外れた場合のエラー処理をきちんとしていなかったのが顕在化した、という認識です。
https://github.com/h-kitagawa/tex-jp-build/commit/7e3eff73b543fb7b8e8ddb9313004b283667891 のご提案有難うございます。これは、UTF-8→EUC変換が出来ない場合にゴミを残したままにする、という方針と理解しました。ptexenc はライブラリーなので、同じルーチンを使っている他の所の動作にどんな影響が出るのかが分かりません。もっと明示的にエラーを起こした方が事故は減るのかもしれないという気もしますし、「UTF-8→EUCの変換には失敗するが、ゴミがEUCでの正規の文字列になり、結果として文字化けしたまま気付かずに処理が進行してしまう」という可能性は心配しなくてもよいのか不安はあります。
ptexencのどこかで「「UTF-8→EUCの変換に失敗する場合は^^ab化する」というルーチンを持っていた記憶があります。今回の該当箇所はそれとは別なのか、よく分かりません。(ソースを読むべきですね。)
「UTF-8→EUCの変換に失敗する場合は^^ab化する」
今回の場合とは逆方向の ptenc_from_utf8_string_to_internal_enc や input_line2 ですね.
ゴミがEUCでの正規の文字列になり、結果として文字化けしたまま気付かずに処理が進行してしまう
例えば,ptex 俲俲.tex
(「俲」は UTF-8 で [e4][bf][b2])では 篆俄寝.tex
を読みに行きますが,篆俄寝.tex
を作ってみたときのログは
ptex 俲俲.tex
This is pTeX, Version 3.14159265-p3.8.3 (utf8.euc) (TeX Live 2020) (preloaded format=ptex)
restricted \write18 enabled.
(./膀^^86篆^^84絲^^9d.tex)
となり,もうぐちゃぐちゃです.
(edit: ……膀^^86篆^^84絲^^9d
は UTF-8 での 篆俄寝
([e7][af][86][e4][bf][84][e5][af][9d]) をEUC-JP で解釈したものですね)
あきらめて「明示的にエラーを起こした方が」良いのかもしれません.
確認ですけど、内部漢字コード=eucのpTeXでaあ①.tex
というファイルを開く場合、件のnameoffilee+1
の中身はどうなるのでしょうか? これが
61 a4 a2 e2 91 a0
(※a4a2はあ
のeuc、e291a0は①
のutf8)
みたいに「eucとutf8が混在」した状態になってると、もうどうしようもないですよね。
aあ①.texというファイルを開く場合、件のnameoffilee+1の中身はどうなるのでしょうか? これが 61 a4 a2 e2 91 a0
まさしくそのようになっています. (https://github.com/texjporg/tex-jp-build/issues/81 で EUC 由来と EUC に変換されなかった部分が区別されればなんとかなるかもしれませんが,そこまでやる気力は今はありません)
UTF-8→EUCに変換できない場合にどうするのか、ブレインストーミングを兼ねて仕様案です。
1 は気乗りしません。ptexenc がライブラリーという立場なので、fallbackして進める方針の方がよいと思います。
2 は慣習としてやっていいような気もします。本当に下駄記号を意図して使おうとしている場合と区別が困難なのをどう考えるか。 下駄記号 Wikipedia
3 は本当にその文字列を意図して使おうとしている場合は稀で、一番安全かもしれません。それに、変換できなかったバイト列の情報が保存されるのでデバッグしやすい利点、ptexencの内部動作を知らないユーザーもエラーに気づきやすい利点もあると思います。文字列が長くなるのが実装上面倒かも知れません。
私としては、2 か 3 を支持します。
個人的には \input{①}
と ptex ①.tex
が同じファイルを探して欲しいです。(edit: 探されるファイルが「システム上で "①.tex" と表示されるファイル」かどうかは問いません。)
TL2018 以前では文字コード変換していなかったのを TL2019 で変換するようになったのは,「ソース中に書かれた \input{日本語ファイル名}
から 日本語ファイル名.tex
を探すために 内部コード→UTF-8 への逆変換が必要だから」だと理解しています。その結果,TL2019 では \input{日本語}
と ptex 日本語.tex
が同じファイルを探すのですから,同様であればいいなと思います。「\jobname が何になるのか」という観点でも。
\input{文字列ほげ}
と hogetex 文字列ほげ.tex
が同じファイルを探すという仕様に対しおそらく現状(TL 2019,2020)では「Unix/Linux系 かつ ロケールUTF-8 」でもWindowsでも
と思います。私としては充分だと思います。 pTeX では「文字列ほげ」がUnicodeの範囲で実現できるようにする、というのは新規の開発項目になりますが、そこに開発資源を投資する価値は無いと思います。
non-windows での仕様を理解したいので,お手数ですが確認させてください。
\input{文字列ほげ}
とhogetex 文字列ほげ.tex
が同じファイルを探すという仕様
を実現するために ptexenc が行なっているのは,
各「変換」がどの関数に対応しているか,また … の部分が TL2019/2020 でどう扱われているのか埋めて頂けると有り難いです。
記憶を元に書くと non-windows かつロケール UTF-8かつ pTeX かつソースコードが UTF-8 では
\input{文字列ほげ}
をptexencが入力バッファに取り込む際にUTF-8→EUC変換
変換できなかったバイト列は ^^ab に変換文字列ほげ.tex
にアクセスしようとする際、lib/openclose.c のopen_input()
かどこかで16bit JIS→UTF-8変換そして
3 は TeX Live svn r47967, r47972 あたりで触った場所です。 バイト列と和文文字の区別 #81 とも関連が有ったはず。間違っていたら訂正お願いします。
Windows ではこのようなヤヤコシイことが起きないように対処されているはずなのですが,この“対処”が W32TeX では成功しているのに,TeX Live では upTeX で失敗するケースがあるという報告があります。私もまだ試せていないのですが,Windows で再現する方はいらっしゃいますか?