マクロツイーター

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

例の BXbase の何かの話(1)

アレForum のアレについて。

アレのコードが何をするものなのか気になる、という人のための解説。

\bxInputJaEncoding の仕様の話

bxtoolbox パッケージは「便利マクロ集」なので提供される機能は雑多であるが、問題になっているのは次の機能の実装部分である。

  • \bxInputJaEncoding [暗黙文字トーク*1]: 現在の入力漢字コードを示す。
    • b: バイト入力(byte;8 ビット欧文LaTeX
    • u: UTF-8(utf8)*2
    • s: シフトJISsjis
    • e: EUC-JP(euc
    • a: (u)pLaTeX で自動判別が有効(auto)
    • ?: 不明(unknown;判定失敗)
  • \infojenc [一般]: 現在の入力および内部漢字コードの情報を端末に表示する。

例えば、BXbase と PXbase(の最新版)がある環境で以下のソースを(任意のエンジンの)LaTeXコンパイルすると……。

\documentclass{article}
\usepackage{bxtoolbox}
\infojenc
\stop % 強制終了

……端末に以下のような行が表示される。(以下の行は W32TeXpLaTeX の場合。)

Kanji encoding: input=auto; output=auto; internal=sjis

この出力の中の、“input”が入力漢字コード(auto=自動判定)、“internal”が内部漢字コード(sjisシフトJIS)を示している。*3

\bxInputJaEncoding の実装の話

\bxInputJaEncoding の実装は以下のようになっている。

[bxtoolbox-ja.def:117行目]
%%<+> \bxInputJaEncoding
\let\bxInputJaEncoding=?
\ifbxHasAlUcsChar % XeTeX/LuaTeXの場合
  \let\bxInputJaEncoding=u% utf8
\else\ifbxinpdfTeX % pdfTeXの場合
  \let\bxInputJaEncoding=b% bytes
\else\ifbxtb@pxbase@ok % PXbaseがインストール済の場合
  % 判定用ファイル(1)を用いて入力漢字コードを判定する
  \@@input pxbsjc.def\relax
  \def\bxtb@tmpb#1#2\@nil{%
    \ifnum `#1=\jis"723F \let\bxInputJaEncoding=s\else
    \ifnum `#1=\jis"693D \let\bxInputJaEncoding=e\else
    \ifnum `#1=\jis"7379 \let\bxInputJaEncoding=u\fi\fi\fi}
  \expandafter\bxtb@tmpb\bxtb@tmpa\@nil
  % 判定用ファイル(2)を用いて入力漢字コードを判定する
  % (自動判定(-guess-input-enc)の場合への対策)
  \ifx e\bxInputJaEncoding
    \@@input pxbsjc1.def\relax
    \def\bxtb@tmpb#1#2\@nil{%
      \ifnum `#1=\jis"723F \let\bxInputJaEncoding=a\fi}
    \expandafter\bxtb@tmpb\bxtb@tmpa\@nil
  \fi
\fi\fi\fi

つまり、エンジンが (u)pTeX の場合は、「入力漢字コードが何であるか」によって書いてある文字列が異なるようなファイルを読み込んで、その結果を解析することで入力漢字コードを判定しているのである。入力漢字コードは文字通り入力を行う際にしか関わってこないので、このような判定法を用いることはほぼ必須だと思われる。

[pxbsjc.def]
%
% pxbsjc.def
% Warning: Do not change encoding of this file!
\def\bxtb@tmpa{??????}% E9 BD B7 E9 BD B7
\endinput
% EOF

ここで「??????」の部分は実際には「E9 BD B7 E9 BD B7」というバイト列になっていて、これは入力漢字コードに応じて次のように解釈される。ここで仮に、“J-XXXX”で「2 バイト JIS コード*4が XXXX(16進) の文字」、“A-XX”で「1 バイト JIS コード*5が XX(16進) の文字」を表す。

  • utf8 の場合は〈U+9F77 U+9F77〉(齷齷)で、JIS コードに変換すると、〈J-7379 J-7379〉。
  • sjis の場合は〈J-723F A-B7 J-723F A-B7〉(鮨キ鮨キ)
  • euc の場合は〈J-693D J-3769 J-3D37〉(藹潔酬)

従って、この文字列の先頭文字の“JIS スカラー値”*6を調べればよい。すなわち、この文字列(を読み込んで得られるトークン列)の先頭の和文トークンをマクロの引数(#1)として拾った上で、以下のような if 文を書けばよいわけである。((なお、「`鮨」は文字〈鮨〉の“内部漢字コードでのスカラー値”(例えば sjis なら "E9BD で、euc なら "F2BF)であり、つまり内部漢字コードにも依存する値となる。ところが一方で「\jis"723F」は“JIS スカラー値が "723F である文字の内部漢字コードでのスカラー値”を指す。従って、この 2 つの値の一致を判定する限りでは内部漢字コードには依存しない。すなわち〈鮨〉の“JIS スカラー値”は "723F なので、「\ifnum`鮨=\jis"723F」という条件は内部漢字コードに関わらず真となる。))

\ifnum`#1=\jis"723F\relax (入力漢字コードがsjis)\fi
続く

*1:つまり、文字トークンに let されたトークン。

*2:現状の XeLaTeX・LuaLaTeX では(事実上)UTF-8 しかサポートされないので、これらの場合は無条件に UTF-8 と判定する。

*3:“output”は「出力漢字コード」の情報である“予定”であるが、今のところ未実装(実装の方法を思いつかない)で単に input と同じものを表示している。

*4:正確にいうと、JIS X 0208 の符号位置の GL 表現、いわゆる“JIS エンコーディング”。

*5:JIS X 0201 に相当するもの。実際には「ASCII + 半角カナ」。

*6:JIS エンコーディングでのバイト列を 16 ビット整数値とみなした値。