The Man Who Fell From The Wrong Side Of The Sky:2009年3月5日分

2009/3/5(Thu)

[NetBSD] 続 New I18N API?

昨日の話の続き。
joerg氏はiconv(3)についてエラーハンドリング以外は悪くないAPIだとゆうてて(えー)
iconv_open("WCHAR_T")的なもので行きたい模様で、↓なのを提案してきてる。

ic = iconv_open(wchar_charset("de_DE.UTF-8"), "ISO-8859-1");

wchar_charset(localename)というのはCSIなwchar_tのformを取得する関数らしい。
ただでさえGNU libiconvのlocale_charset() vs nl_langinfo(CODESET)で混乱してるし
ここは触らんほうがいいっす、地雷原。

あとエラーハンドリングは、そもそも文字コード変換に失敗した場合アプリは処理継続しちゃダメ、絶対なのよな。
処理継続しようとがっつくと、つまらない セキュリティホールを生むわけでして。
つかそもそも文字コード変換した時点で、耳の穴に蜂蜜たらして蟻を放って脳ミソ噛み噛みされるのは覚悟。
ってそれなんて勇午パキスタン編じゃ。

それに世の中のアプリがどれだけ間違ったiconv(3)の使い方をしているか
( 入出力buffer管理とか 文字列 != バイト列とかね…)を考えると、余計な拡張なんて触らぬ神に祟りなしですわ。
ただでさえ「GNU libiconv + 死んでください」とか検索リファラ残っててgkbrしてるのに。

んで↑がダメなら文字コード指定可能なmbrtowc(3)、つまりmbrtowc_enc()的なものが欲しいと。
Thread Aware Locale Extensionにあるmbrtowc_l()だとUTF-16/32のような
locale_tすなわちPOSIX localeで扱うことのできない符号化手法は扱えないので
そんなものを実装しても無駄なんで、新しいAPIが欲しいと。

まぁこっちはダメでしょ、mb/wc変換はMB_CUR_MAXによる縛りがあるので。

     mbstate_t st;
     wchar_t wc;
     const char s[] = { "the Artist Formerly Known As Prince" };
     size_t len;

     setlocale(LC_CTYPE, "en_US.UTF-8@NFC");
     mbstate_set_enc(&st, "UTF-8@NFD");
     len = mbrtowc_enc(&wc, s, sizeof(s), &st);

のようなUnicode正規化の結果M:N変換が発生した場合、MB_CUR_MAXの制限にひっかかるのよな。

なのでコード変換をせざるを得ないのであれば、iconv(3)をstdioのバックエンドに隠して
fgetwc(3)使う方が楽だとゆうとるのだけど、fopen(3)のccs=<encoding> flag拡張
については「いいけどこれ暫定的なものだよねー」とかゆわれてしもた、おれ涙目。
fmemopen(3)とopen_memstream(3)については何が嬉しいのか判らんそうだ。

singlebyte圏でCodeSet Independentとかちゃんと理解してるすばらしー人材なのだが
やっぱり若者(26歳だっけか?)らしくアイデアは鼻息が荒々しいやね。
それとも俺が枯れ過ぎなだけ?

いまいち説得できる自信がない…

[Cygwin] 1.7入れてみた

Cygwin 1.7のMB_LEN_MAXが8になっとる、なにこの「なくてもいいけどちょっとはあったほうが…」。

これISO/IEC 2022の最長エスケープ(ESC & V ESC $ ( F) + 1byteちゅう計算?
それなら96x96だから + 2byteになるので9だよな、しかも冗長なescape sequenceの出現を考慮しとらん。
そんでnewlibに実装のあるC-JIS(=ISO-2022-JP)は冗長なしだと最長6byteありゃ充分だし。
あいかわらず不思議な実装だ…

まぁMB_LEN_MAXが8あっても、newlibのことを全く考慮せずにglibc2からmbstate_tを
コピペしてきたせいで、どっちみちstateless encodingかつ最大4byteまでしか扱えないんだけど。
/usr/include/sys/_types.h参照、これですっかりやる気なくしたと某スレpart4の336は以下略
まぁ他にもnewlibのstruct _reentのアレさに嫌気が差したんだけど。

まぁ4byteありゃDBCSとGB18030とUTF-8(RFC 3629で5~6byte禁止)が扱えるので
ごく一部の「LANG=ja_JP.ISO-2022-JPはご褒美です」な人以外には十分か。

あとmingwだとtypedef int mbstate_tふいた、なんだcygwinとmingwはバイナリ互換無いのか。
だったらcygwinもwchar_tはshortでなくintにしちまえばいいのにねぇ。

んで最も血の気が引いたのは、MB_LEN_MAXを増やしたのに
cygwin2.dllとかにDLLNAMEを変更してないのよな、もはやバイナリ互換性とか
そんなチャチなもんじゃあ断じてねえ、もっと恐ろしいものの(以下略

まぁでもMB_LEN_MAXが増えたので今こそまともなmb/wc変換つっこむチャンスではある。
以前ちょこっとネタで書いた fake wcharをベースにLC_CTYPEを実装する時間がホシス。
すっかりNetBSDすら弄る時間が確保できん生活で困る。

ファイルシステム操作まわりはWin32APIのW系API(=UTF-16)使うようになったのね。
日本語ディレクトリが作成できたり移動できたりするもより。