(簡易版)pTeX を UTF-8 入力に対応させる試み(3) †UTF-8対応(2) から小さな拡張を行います。 UTF-8 の処理には直接は影響しませんが、 文字コードを切替えやすくして、使い勝手をよくします。 ロケール対応 (libkanji-0.85) †"--kanji=" オプションでの文字コード指定は、 入出力ファイルにとどまらず、メッセージ出力にも影響しました。 そのため、platex-euc と platex-sjis の両方とも文字化けしない ターミナルの設定は存在しませんでした。 Unix の作法では、ターミナル出力の文字コードは、 環境変数 LANG などの設定に従って切替えることになっていますので、 ptex などもこれに従って切替えるようにしてみました。 改造は libkanji のみで行い、 個々のツールには全く手を加える必要はありませんでした。 出力ファイルの文字コードについて †結論から書くと、出力ファイルは、 以前とまったく同じものになるようにしました。 ptex が出力する *.aux などのファイルは、 再び入力としても用いられるので、 出力ファイルの文字コードもよく考えないといけません。
この二つの方法が考えられます。 以前から 1. を採用してきて、今回も引き継ぎました。 2. でもそれほど問題はないと思いますが、 "*.log" などをエディタで眺める人がいるかもしれないので、 JIS 決め打ちよりかは入力ファイルと同じ方が安全であろうという気がします。 参照する環境変数 †どの環境変数を見ればよいのか、よくわからなかったのですが、 man のソースを見てまねしてみました。 LC_ALL LC_MESSAGES LANG LANGUAGE この順番で最初に見つかった設定を採用します。 見つかった環境変数は、次のように処理します。
環境変数がどれも設定されてなかったり、 設定されてても比較した文字列のどれとも一致しなければ、 これまでのように "--kanji" オプションの設定に従います。 プログラム開始後、putc2()/fputs2() 経由で 最初に stdout または stderr に出力しようとしたときに、 以上の処理で文字コードを決定し、その結果を記憶します。 プログラム実行中に環境変数が変更されることは想定していません。 文字コードの独立 (libkanji-0.86) †以前は、内部バッファの文字コードが EUC であれば、 SJIS に変換して出力することはありませんでしたが、 ターミナルには SJIS に変換して出力する必要が生じました。 そこで、処理は少し冗長になるのですが、 内部バッファ、ターミナル出力、入出力ファイルの 3つの文字コードをすべてばらばらに設定しても 大丈夫なように改めました。 SJIS と EUC の場合分けが対称になり、 ソースが読みやすくなったと思います。 更にこれを利用して、各ツールでの文字コードの扱いを以下のようにしました。 platex も含めて --kanji オプションで切替えられます。 また、W32TeX と同様に環境変数 PTEX_KANJI_ENC も使えるようにしてみました。
ヘルプメッセージでの漢字コードを示す文字列は、 ファイル入出力と内部バッファが一致してれば、 これまでのように "(sjis)" のように表示します。 一致しない場合は "(utf8.euc)" と、 ファイルと内部のコードを両方出力するようにしました。 なお、PTEX_KANJI_ENC は環境変数だけが有効で、 $TEXMF/web2c/texmf.cnf は参照しません。 というのも、ptex の内部処理の順序に束縛されて、 version メッセージを出力する段階でプログラム名が決定されておらず、 texmf.cnf を参照できないからです。 ちなみに、PTEX_KANJI_ENC に設定できるものは --kanji オプションと同じく、 JIS, EUC, UTF8, SJIS の文字列です。 文字コード指定関数について †普通のユーザには関係ない話ですが、 内部で利用している関数について解説しておきます。 今回は各ツールにも小さな修正が必要でした。 libkanji の set_kanji_enc_string() を拡張し、 入出力ファイル用と、内部バッファ用の引数を2つとるようにしました。 コードを変更したくないものには NULL を、 ./configure 時に指定したものを指すには "default" を指定します。 多くのツールは、これまでファイルも内部も同じものを使ってましたので、 今回の変更では、同じ引数を2回重複して与えればよいことになります。 内部用に "JIS" や "UTF8" を指定した場合は "EUC" に読み替えてくれます。 jbibtex と mendex は、内部バッファが EUC に固定されていますので、 まずは (NULL, "EUC") を引数に与え、--kanji オプションがあれば (opt, NULL) を与えればよいことになります。 ptex は、fmt ファイルを生成する必要から、 そう簡単に内部コードを変更するわけにいきません。 ですから、環境変数の影響を排除するため、まずは (NULL, "default") を実行します。 その後に --kanji オプションには (opt, NULL) として、ファイルだけを変更します。 一応 --kanji-internal オプションを新設してまして、 当然こちらは (NULL, opt) と処理しますが、 ユーザが使う必要はまったくないでしょう。 ptex-sjis は、内部コードと同時にファイルも切替えたいですから、 まずは ("sjis", "sjis") を引数に与えます。 この後に --kanji オプションを処理します。 ptex-euc も同様です。 文字コードの自動判別 (libkanji-0.87) †TeX ファイルの文字コードを自動判別し、 EUC でも SJIS でも区別することなく platex で処理できるようにしてみました。 当然ながら 100% の精度で文字コードを判別することなど、元々無理な話ですが、 世の中では nkf というソフトが実用上十分な精度を持っていることが知られています。 このコマンドをそのまま利用することにしてみました。 fopen() の代わりに popen() を用いて、 フィルタプログラムの出力を読み込むことにしました。 用いるフィルタプログラムは、環境変数 PTEX_IN_FILTER にフルパスで登録します。 フィルタの出力は JIS にしておくのが安全ですが、 PTEX_KANJI_ENC や --kanji と整合性がとれていれば動きます。
libkanji に関数を新設し、Web2c から利用するようにしました。 多くのツールには変更の必要がありません。 mendex のみ Web2c アプリでないので、libkanji を直接使うようにしました。 さて、こういう拡張を行うと、従来との互換性が問題になります。 一応大丈夫だと思っています。
別実装案 †フィルタプログラムを登録できることは、 自由度が増す半面、悪いことにも使えそうで、若干心配ではあります。 そこで、代替案を書いておきます。 やはり nkf を利用するものの、フィルタとしては動かさずに、 文字コードの判定だけをさせるというものです。 近頃の nkf は --guess オプションが新設されて、 文字コードの判定結果だけを出力できるようになりました。 これを利用して、ptex 側は入力ファイルの文字コードを 動的に切替えればよさそうです。 文字コード変換ルーチンは ptex (libkanji) 内蔵のものを使うことになります。 こうすると自由度が下がって、Utf82TeX を登録するようなことはできなくなります。 そのほうが変な使い方をする人が現れずに、安心といえば安心かもしれません。 nkf は相当新しい必要があるので、ptetex3 に同梱することになるでしょう。 例えば /etc/passwd を外部に送り出すプログラムを nkf の名前で仕込んでみるとして、どちらが動かしやすいかを考えてみると、 ...、どちらもあまり変わらない気がしてきました。(^_^;) 今後の展開 †nkf をフィルタとして使うか、文字コード判定にとどめておくか、 どちらにするか方針を定める必要があるでしょう。 私はセキュリティの専門家ではないので、どちらが安全かよくわかりません。 必要なら nkf を(外部コマンドとしてではなく) ライブラリとして ptex/libkanji にリンクすることも考えます。 もっとも jmpost は環境変数 TEX に登録されたコマンドを内部から実行するので、 現在でも同程度に安全なのかもしれません。 自動判定機構のような再現性の難しいものを入れてくれるな、 という声もあるかもしれません。 他人に TeX ソースを渡す場合は、 判定機構抜きで動くように文字コードを揃えるべきだという 啓蒙活動を行う必要も感じています。 platex-sjis のようなコマンドは、すべて廃止してもよい気がしてきました。 内部コードを EUC と SJIS で切替える必要はあるでしょうか? href 関連で微妙に動作が違うこと、 120区の SJIS の処理くらいしか差がないと思っています。 謝辞 †今回の機能拡張は、岡山氏のリクエストに端を発して、 ttk 氏の活動を見据えてすり合わせを行いました。 開発のモチベーションを与えていただいた両氏に感謝します。 ご意見をどうぞ。 †
|