2007-01-23 (Tue) [長年日記]

_ [obsd][mutt]どのようにしてlibcは後方互換を保つのか(その2) (めもがき:2007年1月23日分)

libcはld(1)によって暗黙的にリンクされます、この場合リンク順は一番最後になります。

お、そうだったのか。それで上書きしてもリンカが文句言わないのか。

ここ数日の「めもがき」のおかげで、やっとこの問題の意味がわかってきました。 感謝感激。もう一度よく読み直そうっと。

_ w3m と UTF-8

Unicode では「>>」みたいな文字が二種類あるようで(「≫」226b と「》」300b だったかな)、 w3m を UTF-8 環境で動かすと、(フォントによって違うとは思うけど)、 226b が幅 1 で問題なく使えるのに対して、300b も幅 1 になって、 セキュmemo などが少し気持ち悪くなる。 最初の表示は大丈夫っぽいんだけど、カーソルを合わせると誤差が出てくる。

ほんとはうちのフォントとか mlterm がおかしくて w3m が正しいのかもしれないけど、 これを追ってみる。

最初これは mlterm の問題だろうと思って ChangeLog を見てみたんだけど、 xterm との互換性のために ambiguous 幅じゃなくて wide にした、とかいう記録があった。

それに vim では UTF-8 でも EUC-JP でも問題なく扱える。

だから w3m の問題だと思って、こっちを調べる。

まず addstr とか addch のあたりから追って、wtf_width というものがアヤシイと思った。 これは WTF_WIDTH_MAP という配列を見るだけのもの。 そして WTF_WIDTH_MAP は最初の 1 バイトだけで幅を判断するというものだった。

gdb で見ると、300b は 88 80 e0 8b (0210 0200 0340 0213) というバイト列のようで、この 88 (0210) の部分だけってことだ。 でも 226b も最初は 88 (0210) なので、困っちゃうなあ。 そもそもどうして 300b がこんな 4 バイトになるのか。 UTF-8 のファイルを hexdump してみると e3 80 8b (0343 0200 0213) みたいだぞ。

で、とりあえず wtf_width マクロの時点で 88 80 e0 8b (0210 0200 0340 0213) に 2 を返すように細工してみたら、うまくいった。

だからあとはちゃんと 88 80 e0 8b (0210 0200 0340 0213) の意味を解析しなくては。 おそらく 1 バイトがフラグのようなもの、次が UTF-8 と共通、また 1 バイトフラグ、UTF-8 共通、ということだろう。88 (0210, 0b010001000) とか e0 (0340, 0b011100000) ね。

と思ってたら libwc/wtf.h に

#define WTF_C_WCS16     0x88

って書いてあるじゃん。

そして wcs16_to_wtf(0x300b) を見てみると……おお、確かに 80 e0 8b になる。 だから最初の 88 (WTF_C_WCS16) に、もうちょっとフラグを足せないか考えればいいんだな。

と、ここまで来て、libwc/map/ucs_wide.map をいじったらすぐに直ってしまった。 あれ〜? 最初にやったときは駄目だったのになあ。

あ、でも最初に ucs_wide.map をいじったときは libwc だけ作り直したっけ。そうか。

--- libwc/map/ucs_wide.map~	Tue Jan 23 21:34:35 2007
+++ libwc/map/ucs_wide.map	Tue Jan 23 22:46:26 2007
@@ -1,10 +1,9 @@

-#define N_ucs_wide_map 10
+#define N_ucs_wide_map 9

 static wc_map ucs_wide_map[ N_ucs_wide_map ] = {
   { 0x1100, 0x115F },
-  { 0x2E80, 0x3009 },
-  { 0x300C, 0x3019 },
+  { 0x2E80, 0x3019 },
   { 0x301C, 0x303E },
   { 0x3040, 0xA4CF },
   { 0xAC00, 0xD7A3 },
[]

«前の日記(2006-12-31 (Sun)) 最新 次の日記(2007-02-01 (Thu))»