[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

editors/vim の文字化けについて



山城@OFUG です。

editors/vim ですが、NetBSD 環境で USE_GNU_ICONV=yes を設定しないで
コンパイルすると、ファイルの文字コード判定でバグが発生します。
原因を突き止めることはできたのですが、自分一人だけで完全に解決できる
ような問題ではないため、皆さんのご意見をお聞かせ下さい。


	再現手順

1. NetBSD 環境向けに editors/vim を普通にコンパイル/インストールする
(editors/vim-gtk2 等でも可)
# uname -a
NetBSD yamajun 6.99.23 NetBSD 6.99.23 (GENERIC) #100: Sat Jul 13 08:17:42 JST 2013  yamajun@yamajun:/usr/src/sys/arch/amd64/compile/GENERIC amd64
# cd /usr/pkgsrc/editors/vim
# make install

2. ~/.vimrc で以下の設定をする
====ここから
" 端末の文字コードに合わせて euc-jp か utf-8 に設定する
set encoding=euc-jp
" iso-2022-jp が含まれていること
set fileencodings=iso-2022-jp,utf-8,cp932,euc-jp
====ここまで

3. ISO-2022-JP 以外の日本語が書かれたファイルをvim で読み込むと文字化け発生


	回避策

* fileencodings から iso-2022-jp を排除する。
ただし、iso-2022-jp で書かれたファイルは文字化けする。

* USE_GNU_ICONV=yes を設定してコンパイルする
# cd /usr/pkgsrc/editors/vim
# make USE_GNU_ICONV install


	原因

Citrus iconv では、iconv_open("utf-8", "iso-2022-jp") で、入力データの
文字コードを iso-2022-jp と推測した後に、EUC-JP/UTF-8/CP932 のデータを
変換対象データに指定して iconv(3) を実行しても、GNU libiconv のように、
errno に EILSEQ (入力に無効なマルチバイト文字列有り)を設定して
エラーを出していません。

そのため、vim の入力ファイル文字コード判定処理で EUC-JP/UTF-8/CP932 な
ファイルの文字コードを ISO-2022-JP と誤認してしまい、文字化けが発生します。

参考: vim の文字コード判定処理
http://code.google.com/p/vim/source/browse/src/fileio.c の 1540 行あたり
ファイルの文字コードが正しくないならエラー処理を行うループに突入する

| while ((iconv(iconv_fd, (void *)&fromp, &from_size,
|                                                &top, &to_size)
|             == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
|                                   || from_size > CONV_RESTLEN)
| {
| 	if (can_retry)
|           goto rewind_retry;


	根本的な修正方法案

案1. Citrus iconv を修正する。
iconv(3) の入力文字コードが iconv_open(3) の指定と違うときに
エラーを出せるように iconv(3) を修正するのがベストだと思いますが、
それが「正しい」やりかたなのかは iconv(3) に詳しくないので分かりません。
とりあえず、テストケースを作って send-pr したほうがいいのかな...

案2. editors/vim-share/Makefile.common で USE_GNU_ICONV=yes を指定する。
http://code.google.com/p/vim/source/browse/src/configure.in にて、
| dnl Link with iconv for charset translation, if not found without library.
| dnl check for iconv() requires including iconv.h
| dnl Add "-liconv" when possible; Solaris has iconv but use GNU iconv when it
| dnl has been installed.
と書いてあるように、vim では優先的に GNU libiconv を使うようにしています。
「vim とは GNU libiconv を使うもの」と考えると、pkgsrc でも強制的に
GNU libiconv を使わせる方が正しいという考え方もあります。

自前の iconv(3) を持っている NetBSD 以外の OS でも同じような症状が出る場合には、
案2の修正方法しか選択できない可能性もあります。


-- 
Okinawa FreeBSD Users Group	山城 潤(Yamashiro, Jun)
E-mail: yamajun@ofug.net