numaの日記: Linux での シフト JIS サポート 2
はてなダイアリーの hyoshiok さんの日記より, Red Hat Linux での シフト JIS サポート要望が拒否された一件.
なんとも低レベルの議論で,情けないというか何と言うか.
ところで,この手の議論では, 「シフトJIS」という用語の定義が曖昧なことが多くなるので,注意が必要である. ここでいう定義の曖昧さとは, 「1バイトの英数字の部分を JIS X 0201 ラテン文字と見なすか,それとも ASCII と見なすか」についてである. 「シフト JIS のロケールをサポートすると,POSIX ベースのプログラムの動作が保証できなくなる」という場合は前者の意味, 「既存の商用 UNIX システムでシフト JIS をサポートしたものがある」という場合は後者の意味で使っている.
これらの違いは次の通り.
- 0x5C のコードポイントにある文字が,ASCII の場合はバックスラッシュ,JIS X 0201 の場合は円記号
- 0x7E のコードポイントにある文字が,ASCII の場合はチルダ,JIS X 0201 の場合はオーバーライン
なお,ここで問題にしているのは「プログラムの中で,どちらの文字として扱われているか」であって,「フォントとしてどちらの文字で表示されるか」とは,一応別の問題である.(フォント絡みの話もまたまたいやらしい話題になるが,ここでは略.)
これが何故問題となるか.それは,次の事情があるからだ.
- ISO C 言語標準 (ISO/IEC 9899) では,C プログラムのソースを記述するのに必須の文字集合 (ASCII から $ や ~ など,一部の文字を除いたもの) について,「char 型変数1個 (1バイト)で表現できること」を前提としている.
- ISO POSIX 標準 (ISO/IEC 9945) では,Portable Character Set (移植可能な文字集合,以下 PCS と略す) という概念がある.PCS は ASCII のすべての図形文字と,一部の制御文字を含んでいる.そして,一つのシステムでサポートされるすべてのロケールで PCS のコードの値が不変であることを前提としている.
シフト JIS の1バイト英数字の部分が JIS X 0201 ラテン文字の場合,0x5C のコードポイントにあるのは円記号であって,バックスラッシュではない.この場合,バックスラッシュは2バイト文字の「\」になる.
まさか,C のソースを書くのに,シフト JIS の時だけバックスラッシュを「\」にして, printf("Hello world!\n"); なんて書くわけにはいかないし,これで正しく動作するコンパイラなどない. シェル等でエスケープ文字として使われる「\」が,ロケールをシフト JIS に変えた途端に「\」に切り替わるよう,作ってあるわけもない. Ulrich あたりが「SJIS ロケールは標準に反する」というのはこの意味である.
もちろん,1バイト英数字の範囲を ASCII と見なして シフト JIS ロケールを作ることは可能である.Microsoft が Windows でやっているのと同じやり方だ.シフト JIS 妥協派とでも呼ぼうか. この方法は「シフト JIS の1バイト英数字は JIS X 0201 ラテン文字でなければならない」とするシフト JIS 純粋派からは嫌われるだろうけれど,現実的ではある.
もっとも,その場合,「SJIS」あるいは「Shift_JIS」というエンコーディング名は使えない.iconv の実装がシフト JIS 純粋派の変換ルールになっているので,矛盾してしまうからだ.「CP932」のような,矛盾のないエンコーディング名を使う必要がある.
えっと (スコア:1)
コードの話と文字の話がごっちゃになってるような気がします。
OSF CHARACTER AND CODE SET REGISTRY INTRODUCTION [opengroup.org]に
とありますが,少なくとも 「Shift_JIS というエンコーディング」のみに限って話をした場合,「1バイトの英数字部分(i.e. \x20~\x7E)」が JIS X 0201 であろうが,ISO/IEC646 IRV であろうが,\x5C を yen-sign ではなく backslash として, \x7E を overline ではなく tilde として扱ってしまっても問題はないでしょう。
Shift_JIS で問題になるのは,まず backslash と yen-sign の違いなんかより,むしろ,2バイト文字の第2バイトに \x40~\x7E がくる場合があるということでしょう。第2バイトに \x5C や \x7C がくる文字を含んだ文字列を正しく処理できないといったことが起こりえますよね。
もうひとつの問題は,numa さんも指摘している文字との対応関係で,こちらは,他の(特に unicode 系の)エンコーディングと相互に変換する場合に問題が表面化することになると思います。ここは,確かに,非常に難しいところですね。
# 全然まとまってないや
Re:えっと (スコア:1)
コメントありがとうございます. お返事が遅れて済みません.
実は,Big5 など,外国の文字エンコーディングには2バイト目が 0x40~0x7E になるようなものが存在していて, Linux の glibc やコマンド類は,そういものにも対応できているのです. もちろん,ASCII しか考えていないようなプログラムも多いでしょうが,そういうプログラムには,euc-jp を使おうが utf-8 を使おうが通りません.
で,glibc の開発者の Ulrich Drepper とか, 分かっている人たちはそういうことも理解した上で, なお shift_jis は難しいと言っているのですよ.
まあ,本当のところ,何が問題で shift_jis を排除されているのかは本人に聞いてみないと分かりませんが,私はそんなにはずしていないと思っています.