2019年4月1日月曜日

Linux を新元号に対応させる方法

すっかり放置ブログになっていますが、元号が変った記念更新。

Linux (glibc)は設定ファイルにより元号に対応しており、設定ファイルを書き変えるだけで新元号に対応することができます。 待っていれば OS のアップデートで対応されると思いますが、一早く変更したい人のために手順を簡単に説明します。

1. 現在の状況を確認

$ export LANG=ja_JP.utf8 
$ date +%Ec -d '2019/05/01' 
平成31年05月01日 00時00分00秒
  ⇒ 変更前はもちろん 5/1 日は平成のままです。

2. 設定ファイルを書き換え

$ su # cd /usr/share/i18n/locales/

(念のため現在の設定ファイルをバックアップ) 
# cp ja_JP ja_JP.orig

(LC_TIME セクションにある era の先頭あたりを書き換え)
# vi ja_JP 

(変更前:1行削除)
era    "<U002B><U003A><U0032><U003A><U0031><U0039><U0039><U0030><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U002B><U002A><U003A><U5E73><U6210><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/
(変更後:3行追加)
era    "<U002B><U003A><U0032><U003A><U0032><U0030><U0032><U0030><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U002B><U002A><U003A><U4EE4><U548C><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/
       "<U002B><U003A><U0031><U003A><U0032><U0030><U0031><U0039><U002F><U0030><U0035><U002F><U0030><U0031><U003A><U0032><U0030><U0031><U0039><U002F><U0031><U0032><U002F><U0033><U0031><U003A><U4EE4><U548C><U003A><U0025><U0045><U0043><U5143><U5E74>";/
       "<U002B><U003A><U0032><U003A><U0031><U0039><U0039><U0030><U002F><U0030><U0031><U002F><U0030><U0031><U003A><U0032><U0030><U0031><U0039><U002F><U0030><U0034><U002F><U0033><U0030><U003A><U5E73><U6210><U003A><U0025><U0045><U0043><U0025><U0045><U0079><U5E74>";/

(書き換えのかわりに以下のパッチをダウンロードして当てると簡単です)
# patch -p0 < gengou.patch

3. 情報の更新

# localedef -f UTF-8 -i ja_JP ja_JP.utf8

(必要ならば SJIS と EUC-JP も更新)
# localedef -f SHIFT_JIS -i ja_JP ja_JP.shiftjis 
# localedef -f EUC-JP i ja_JP ja_JP.eucjp

# exit

4. 確認

(4月中の元号は平成のまま)
$ date +%Ec -d '2019/04/30'
平成31年04月30日 00時00分00秒 

(5月になったら新元号の令和元年)
$ date +%Ec -d '2019/05/01'
令和元年05月01日 00時00分00秒

(来年になったら新元号の令和2年)
$ date +%Ec -d '2020/01/01'
令和2年01月01日 00時00分00秒

以上です。

OS がアップデートされた時には、そちらの設定で上書きされるので特に何もしなくても大丈夫です。

2011年7月18日月曜日

xterm UTF-8文字幅

最近の xterm は UTF-8 に対応していて、-mk_width-cjk_width オプションで文字幅を切り換えることができます。実は xterm は特にオプションで指定しなかった場合には libc ロケールの文字幅を使用します。前回に GNU libc のロケール文字幅を変更する方法を紹介しました。

ということは、これで xterm での文字幅もバッチリということですね。
LANG環境変数に合わせてCJK文字幅や日本語互換文字幅も使えるはず。
・・・あれ?
・・・・使えるはず?!?
・・・・・何で?何で?
・・・・・・なぜか駄目でした。うーむ。

で source を確認したところ「罫線(line drawing)が全角の場合、そのロケールは信頼できないので、ロケールの文字幅は使用しない」という処理が入っていました。何ってこった。(Solaris のロケールが常に 2を返すので無効にするためらしいです。)

日本語処理系では伝統的に罫線は全角なんだよー。わかれよー。変なことすんなよー。

ということで余計な処理を無効にするために #ifdef でコメントアウトしてしまいました。以下のパッチを当てることで、フォント設定さえ適切なら xterm で ロケールの文字幅が使えるようになります。

--- xterm-269.orig/util.c 2011-02-17 09:28:45.000000000 +0900
+++ xterm-269/util.c 2011-06-17 10:59:16.922977037 +0900
@@ -3881,6 +3881,7 @@
     wchar_t n;
     int oops = 0;
 
+#ifdef __sun
     for (n = 21; n <= 25; ++n) {
  int code = (int) dec2ucs((unsigned) n);
  int system_code = wcwidth(code);
@@ -3899,6 +3900,7 @@
      break;
  }
     }
+#endif
 
     for (n = 0; n < (wchar_t) samplesize; ++n) {
  int system_code = wcwidth(n);

2011年7月15日金曜日

GNU libc UTF-8文字幅

最近は linux でもファイル名やディレクトリ名に日本語を使うことも多くなってきているようです。個人的にはファイル名にASCII文字以外を使用したくはないのですが、添附メールでもらったりとか、MS-Windows や Macintosh のファイル共有など色々と必要となる場面があります。

このような日本語の文字や記号をファイル名に使用している場合 ls などの表示桁がズレてしまうという経験をしている人も多いのではないかと思います。

これは UTF-8ロケール等で ls の認識している文字幅と、端末が認識している文字幅が異っていることが原因です。端末の文字幅設定の変更方法はそれぞれご存知かと思いますが、ls などの一般コマンド使用する文字幅が変更できることはあまり知られていないようです。

ls などの一般コマンドは libc のロケール機能を使って文字幅を決定しています。linux ならば GNU libc ということになります。この libc の文字幅は localedef コマンドを使用して定義することができます。標準の定義ファイルが /usr/share/i18n/charmap/UTF-8 にあるので、このファイルをコピーして編集して、localedef コマンドに与えることにより文字幅を変更できます。

以下サンプルとして、私の使用している文字定義ファイルを置いておきますのでダウンロードして試してみてください。

ダウンロード: glibc-UTF-8-width.tar.gz

使い方等は「もっと読むで」で

2011年7月10日日曜日

kterm, jless, screen パッチ更新

kterm, jless, screen の UTF-8/JIS X 0213 パッチに対して emacs-23 の旧JIS(JIS C 6226-1978)の扱いに対応させるための互換マッピングを追加しました。合わせて jless のバグの修正と、kterm の UTF-8 によるコピー&ペーストに対応させるためのパッチを入れておきました。

ダウンロード: kterm-6.2.0.ext06.patch.gz

ダウンロード: less-382-iso262.ext03.patch.gz

ダウンロード: screen-4.0.3.ext02.patch.gz

kterm/X11 における UTF-8 によるコピー&ペーストは色々と互換性の問題もあって敢えて外していたのですが、最近は内部がunicodeアプリケーションが多いので、利便性も考えて実験的に対応してみました。UTF-8といっても例によって日本語にのみ対応です。

2011年7月5日火曜日

emacs 23 jisx0213-2000マッピング問題

Emacs-23.3 では JIS X 0213 の 2000年版と2004年版の両方に対応しているのだが、ちょっとした問題があるようです。Emacs では JIS X 0213 の実装として以下の character-set が定義されています。

  • japanese-jisx0213-1 (2000年版の1面)
  • japanese-jisx0213-a (2004年で1面に追加された文字)
  • japanese-jisx0213.2004-1 (2004年版の1面)
  • japanese-jisx0213-2 (2000年版の2面、2004年と2面も同じ)

ということで jisx0213-1 + jisx0213-a = jisx0213.2004-1 という関係になっています。なっているはずです。なってないと困ります。 ....... でもなっていません(泣)。

emacs-23.3 では何故か jisx0213.1 = jisx0213.2004-1 になってしまっています。japanese-jisx0213-a が何のためにあるのかわからない状態です。

実際問題としては2004年で追加された文字はった11文字だし、EUC-JIS-2004 や Shift_JIS-2004 や UTF-8 で扱う時に差ははないので普通に使っていて問題になることは少ないと思いますが、、ISO-2022系の文字コードを使用した時に2004年版にしかないはずの文字が2000年版用のシケーンス ESC $ ( O で出力されてしまうという問題があって気付きました。

elisp の部分の実装は良い感じなのでバイナリに問題があるのだろうということで、ソースを確認したところ2000年版の変換表(JISX2131.map)に2004年の追加文字が誤って紛れ込んでいるようなので、取り除くことにしました。以下そのパッチです。

diff -urN emacs-23.3.orig/etc/charsets/JISX2131.map emacs-23.3/etc/charsets/JISX2131.map
--- emacs-23.3.orig/etc/charsets/JISX2131.map 2010-10-13 07:43:12.000000000 +0900
+++ emacs-23.3/etc/charsets/JISX2131.map 2011-06-14 10:19:22.143109803 +0900
@@ -1157,7 +1157,6 @@
 0x2d79 0x22BF
 0x2d7d 0x2756
 0x2d7e 0x261E
-0x2e21 0x4FF1
 0x2e22 0x0002000B
 0x2e23 0x3402
 0x2e24 0x4E28
@@ -1344,7 +1343,6 @@
 0x2f7b 0x000218BD
 0x2f7c 0x5B19
 0x2f7d 0x5B25
-0x2f7e 0x525D
 0x3021 0x4E9C
 0x3022 0x5516
 0x3023 0x5A03
@@ -4310,7 +4308,6 @@
 0x4f51 0x6E7E
 0x4f52 0x7897
 0x4f53 0x8155
-0x4f54 0x00020B9F
 0x4f55 0x5B41
 0x4f56 0x5B56
 0x4f57 0x5B7D
@@ -4352,7 +4349,6 @@
 0x4f7b 0x5DA7
 0x4f7c 0x5DB8
 0x4f7d 0x5DCB
-0x4f7e 0x541E
 0x5021 0x5F0C
 0x5022 0x4E10
 0x5023 0x4E15
@@ -7743,7 +7739,6 @@
 0x7424 0x7464
 0x7425 0x51DC
 0x7426 0x7199
-0x7427 0x5653
 0x7428 0x5DE2
 0x7429 0x5E14
 0x742a 0x5E18
@@ -8766,8 +8761,3 @@
 0x7e77 0x9F94
 0x7e78 0x9F97
 0x7e79 0x9FA2
-0x7e7a 0x59F8
-0x7e7b 0x5C5B
-0x7e7c 0x5E77
-0x7e7d 0x7626
-0x7e7e 0x7E6B

emacs 23 旧JIS (jisc6226)

今までのブログの記事は、過去に作成したパッチとかを引っぱり出してきて、まとめ直しているものが主なのですが、今回は最近に気付いた話です。

文字コード ISO-2022-JP で書かれた昔のメールを emacs23 を使って加工していて UTF-8 でセーブしようとした時に、うまく変換できない文字があってセーブできないことに気付いたのが事の発端です。少し調べてみるとJIS C 6226-1978 (いわゆる旧JIS)の文字の中に Unicode に変換できない文字があるらしいことがわかりました。

何でこんなことになってるんだということで、さらに調べたとこと emacs23 では JIS と Unicode の変換表で旧JIS(JIS C 6226-1978)と新JIS(JIS X 0208-1983/1990)では異なるマッピングを使っていることが判明しました。旧JISと新JISでは、かなり文字の字形が変更されているため厳密に扱おうとすれば異なるマッピングが必要となるのはその通りなのですが、互換性の問題から大抵のアプリケーションやライブラリでは旧JISと新JISは同じ文字として扱い、特殊な対応を入れているもので第一水準と第二水準を入れ換えられた二十数文字への対応を行うくらいだったのですが。

Emacs-23 は真面目に字形対応してしまったらしい。何てことをしてくれたんだ...
いや、誉めるべきか、貶すべきか悩ましい。漢字の字形の Unicode的な扱いとしては正しいと思うのだけど、また独自の JIS ⇔ Unicode 変換表が増えたことになるわけで。

で、話を元に戻して旧JISからUnicodeに変換できない文字だが、source を調べたところ旧JISからUnicodeへの対応表は昔に京大の安岡先生が作成された表を元にしているみたいなのだが、Unicodeの基本統合漢字だけが対象になっていて、拡張漢字A,Bなどが対象になっていないせいか変換先が未定義なままになっている文字があることが原因みたい。

とりあえず、旧JISでは異なる変換表を使うという主旨を尊重して抜けている部分を補完するとしたら以下のような感じだろうか。あと JIS 1区32点のバックスラッシュ(全角扱い)が ASCII の 0x5C (半角扱い)に変換されるのは文字幅的に嬉しくないのでついでに変更をしておこう。

diff -urN emacs-23.3.orig/etc/charsets/JISC6226.map emacs-23.3/etc/charsets/JISC6226.map
--- emacs-23.3.orig/etc/charsets/JISC6226.map 2010-10-13 07:43:12.000000000 +0900
+++ emacs-23.3/etc/charsets/JISC6226.map 2011-06-14 10:09:40.212292788 +0900
@@ -31,7 +31,7 @@
 0x213D 0x2014
 0x213E 0x2010
 0x213F 0xFF0F
-0x2140 0x005C
+0x2140 0xFF3C
 0x2141 0x301C
 0x2142 0x2016
 0x2143 0xFF5C
@@ -862,6 +862,7 @@
 0x343F 0x6B53
 0x3440 0x6C57
 0x3441 0x6F22
+0x3442 0x3D4E
 0x3443 0x704C
 0x3444 0x74B0
 0x3445 0x7518
@@ -1155,6 +1156,7 @@
 0x374B 0x6842
 0x374C 0x6E13
 0x374D 0x7566
+0x374E 0x25874
 0x374F 0x7CFB
 0x3750 0x7D4C
 0x3751 0x7D99
@@ -1176,6 +1178,7 @@
 0x3761 0x621F
 0x3762 0x6483
 0x3763 0x6FC0
+0x3764 0x28EF6
 0x3765 0x6841
 0x3766 0x5091
 0x3767 0x6B20
@@ -3537,6 +3540,7 @@
 0x513A 0x5140
 0x513B 0x5152
 0x513C 0x514C
+0x513D 0x5154
 0x513E 0x5162
 0x513F 0x7AF8
 0x5140 0x5169
@@ -6458,6 +6462,7 @@
 0x7042 0x970F
 0x7043 0x9716
 0x7044 0x9719
+0x7045 0x9724
 0x7046 0x972A
 0x7047 0x9730
 0x7048 0x9739

2011年7月4日月曜日

emacs 23.3 shift-jis-2004 自動認識問題

文字コードの設定はこれで完璧とか言いながら使っていたのだが、どうも shift-jis-2004 で第四水準の漢字を使用していると文字コードの自動認識に失敗する。elisp的には問題なさそうなので C のソースコードを追いかけてみました。

その結果、Cの文字コード認識の部分のバグらしいことが判明しました。SJISの文字認識の部分へ必要なコーディング・システム情報が渡されていない模様。

とりあえず簡単な一行パッチだけどこれで治ります。

diff -urN emacs-23.3.orig/src/coding.c emacs-23.3/src/coding.c
--- emacs-23.3.orig/src/coding.c 2011-01-09 02:45:14.000000000 +0900
+++ emacs-23.3/src/coding.c 2011-06-14 10:04:41.998645428 +0900
@@ -6501,6 +6501,7 @@
   {
     category = coding_priorities[i];
     this = coding_categories + category;
+    coding->id = this->id;
     if (this->id < 0)
       {
         /* No coding system of this category is defined.  */

2011年7月1日金曜日

emacs 23 (ja-compatible.el)

これまでの Emacs-23 用の日本語設定を一つにまとめて以下のファイルにしています。良ければダウンロードして試してみてください。

ダウンロード: ja-compatible.el

使い方ですが、このファイルを load-path の通った場所に置いて、UTF-8 メインの場合は ~/.emacs.el に以下のように書いてみてください。
;;      for japanese
(toggle-enable-multibyte-characters 1)
(set-language-environment "Japanese")
(load "ja-compatible")

;; set default coding system
(setq default-buffer-file-coding-system 'utf-8-ja)
(set-default-coding-systems 'utf-8-ja-unix)
(set-terminal-coding-system 'utf-8-ja-unix)
(set-keyboard-coding-system 'utf-8-ja-unix)
(set-file-name-coding-system 'utf-8-ja-unix)
(set-selection-coding-system 'ctext)
(setq sendmail-coding-system 'iso-2022-jp)
EUC-JP系をメインに使用している場合には、上記の utf-8-ja-unix の所を euc-jp-compatible-unix に変更します。

2011年6月30日木曜日

emacs 23 (その7)

EUC-JP系の文字コードには、EUC-JP と EUC-JIS-2004/EUC-JISX0213 があり、これらは本質的に異った文字集合ですので互換性がありません。 ASCII および JIS 第一水準、第二水準の範囲ではほぼ同じになっていますが、補助漢字の部分、と第三、第四水準の部分には互換性がありません。

個人的に EUC-JP で書かれたファイルと、EUC-JIS-2004 で書かれたファイルの両方ともに、それなりの数を保有しているため、その区別が問題になっています。酷いものになる一つのファイルの中に EUC-JP と EUC-JIS-2004 の文字が混在してしまっています。(そももかな漢字変換用の辞書の .skk-jisyo からして混在になちゃってたりして。) JIS X 0213 が補助漢字(JIS X 0212)を包含してくてれいれば良かったんですけどね。

補助漢字にしか存在しない文字もあるため、規格的に言えば正しくないのでしょうが、EUC-JP と EUC-JIS-2004 を同時に扱う互換エンコーディングを定義することにしました。

emacs 23 (その6)

次は Emacs-23 で UTF-8 を使う場合や、文字コードの変換をする場合のマッピングの問題について考えます。マッピング問題は主に Microsoft の CP932 環境と、それ以外の環境で Unicode と JIS の間のマッピングが異なることが原因になっています。(他にも OS ごとに細々とした違いがあるのですが)。

Emacs-23 にはこの問題に対応するために japanese-ucs-jis-to-cp932-map, japanese-ucs-cp932-to-jis-map という二つの変換テーブルが定義されています。これをうまく使えば CP932 との変換表の違いを吸収することができます。

ただこの表はあくまで JIS X 0208 と Microsoft CP932 の違い定義しているようで、JIS X 0213 については考慮されておらず、そのまま使用してしまうと、JIS 第三水準にある「チルダ」が第1水準の「波ダッシュ」に変換されてしまうなど、いくつかの文字で不具合がでます。

ということで、この表も自分用に再定義することにします。ついでに GNU libc や Apple MacOS などで(過去に?)使用されていた変換表の差分も吸収しておきます。