I know I believe in nothing but it is my sweet nothing.:2004年01月分

2004/01/03(Sat)

あけましておめでとうございます

@Citrusネタ

二日酔いの頭でごそごそ。
こんなん。

  • iconvがJISX0201カナの変換に失敗する件に対するfix
  • euc-tw@iconvをcns11643plane{1, 2}の範囲でサポート
  • iso-2022-cnおよびiso-2022-krのサポート(iconv, mb/wc共)

2004/01/04(Sun)

(ry

@Citrusネタ

パッチを分割

@Big5

zh_TWではBig5.eten Big-5+ Big-5E、zh_HKではBig5hkscsとか
いろいろ変種があるのでかなり厄介なのは有名だけれど、
変換で CNS - UCS - Big5 が一意にならない非漢字一覧。
上がCNS、下がBig5、右辺がUCS。

1-2137 = U+2015(HORIZONTAL BAR)
A156   = U+2013(EN DASH)

1-2223 = U+203E(OVERLINE)
A1C2   = U+00AF(MACRON)

1-2344 = U+2501(BOX DRAWINGS HEAVY HORIZONTAL)
A2A4   = U+2550(BOX DRAWINGS DOUBLE HORIZONTAL)

1-2345 = U+251D(BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY)
A2A5   = U+255E(BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE)

1-2346 = U+253F(BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY)
A2A6   = U+256A(BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE)

1-2347 = U+2525(BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY)
A2A7   = U+2561(BOX DRAWING VERTICAL SINGLE AND LEFT DOUBLE)

1-243E = U+5341(CJK)
A2CC   = U+3038(HANGZHOU NUMERAL TEN)

1-243F = U+5344(CJK)
A2CD   = U+3039(HANGZHOU NUMERAL TWENTY)

1-2440 = U+5345(CJK)
A2CE   = 0x303A(HANGZHOU NUMERAL THIRTY)

2004/01/17(Sat)

(tbs

@うにこーど

まだよく読んでないんだけれど、
http://anubis.dkuug.dk/JTC1/SC22/WG14/www/docs/n1040.pdf
UTF16 -> char16_t/mbrtoc16/c16rtomb に
UTF32 -> char32_t/mbrtoc32/c32rtomb だってさ。
2月に審議らしいけど、正式にISO-Cに入るのかねぇ。

ぱっと見mbrtowc/wcrtombと変わらないI/Fだけど
ちゃんとmbrtoc16/c16rtombでsurrogate pairを扱えるんだろか。

@char16_t/char32_t

surrogate pairの話、(size_t)-3なんて戻り値が追加されて、
mbrtowc/wcrtomb の場合、mbとwcの関係は n : 1 だけれども
mbrtoc{16,32}/c{16,32}rtomb の場合、mbとchar{16,32}_t の関係は m : n になった
ようで、扱うことは可能っぽい。
(ただし、mbstate_tはchar{16,32}_tの状態をも持つように拡張が必要)

char16_t c16[2];
const char *s = "UTF16だとsurrogateな UTF-8 multibyte";
mbstate_t st;
size_t len;

setlocale(LC_CTYPE, "en_US.UTF-8");
memset(&st, 0, sizeof(st));
if ((len = mbrtoc16(&c[0], s, strlen(s), &st)) == (size_t)-3) {
    /* st will be modified. */
    len = mbrtoc16(&c[1], s, strlen(s), &st);
    s += len;
    ...
}

みたいな使い方をするんだろうかね。

char16_t c16[2];
const char *s = "UTF16だとsurrogateな UTF-8 multibyte";
mbstate_t st;
size_t len;

setlocale(LC_CTYPE, "en_US.UTF-8");
memset(&st, 0, sizeof(st));
len = mbrtoc16(c16, s, strlen(s), &st);
s += len;
...

つー可能性もあるけど、それだとc16に何文字書き込まれたかを
知る方法が無いし、第一安全でない。

そりと訂正、wchar_tの__STDC_ISO10646__と同様で
__STDC_UTF_16__とか__STDC_UTF_32__を定義しない限り
char{16,32}_tも実装依存(=opaque)だそうです。

しかしopaqueならmultibyteが最大何文字のchar{16,32}_tになるかは
不明なはずなのに、C16_LEN_MAXとかC32_LEN_MAXなどの定数は無し。
char16_t = UTF-16 (C16_CUR_MAX=2)、char32_t = UTF-32 (C32_CUR_MAX=1)
を暗黙の了解としてんだろな。

そのうち #define __STDC__UTF_8__ でchar = utf-8 を強制される悪寒。

2004/01/18(Sun)

(tbs

@ungetwc

FILE *fp;
wchar_t wc;
int c;
...
ungetwc(wc, fp);
c = fgetc(fp);

とかやった場合の動作なんだけど、
Solaris、glibcなんかのバヤイ、cの値はfpに書き戻したwcの先頭バイトを返すけども、
NetBSDの場合、書き戻したwcのbufferは使われずfpの先頭バイトを返す。
なんでかってーと、ungetwcを呼んだときにfgetwcが内部的に使うmbstate_tまで
元に戻すのは難しいからで、known problem らしい。
(glibcはstateful encoding localeをサポートしないので特別問題にならない、Solarisも?)

真面目に実装しようとしたら、例えば、ISO2022-JPなんかで

wc = fgetwc(fp); /* wc = ASCII */
ungetwc(L'あ', fp); /* JISX0208 */

つーことをやったと考えた場合、fpには

ESC$B$"ESC(B

を書き戻してやればいいんだろか...
_citrus_${ENCODING}_put_state_reset()あたりを拡張すればなんとかなるか?

2004/01/20(Tue)

(tbs

@ungetwc

ungetwcのinternal mbstateに従ってwcをmbに逆変換する方法を模索中。

static int
_citrus_XXX_ungetwc_wctomb(
    _XXXEncodingInfo * __restrict ei, char *s, size_t n,
    const wchar_t wc, _XXXState * __restrict st, size_t * __restrict nresult)
{
    char *ptr;
    size_t mlen;
    _XXXState st0;
    char mb[MB_LEN_MAX];

    ptr = s;
    st0 = *st;
    if (_citrus_XXX_wcrtomb_priv(ei, mb, sizeof(mb), wc, &st0, &mlen) || n < mlen)
        return (EILSEQ);
    memcpy(ptr, mb, mlen);
    ptr += mlen;
    n -= mlen;
    if (memcmp(&st0, st, sizeof(st0)) /* XXX: FIXME */) {
        /* 状態 st0 が st へ 遷移 するのに必要な
           制御文字 を ptr に書き込む */
    }
    *nresult = ptr - s;
    return (0);
}

2004/01/23(Fri)

(tbs

@ungetwc

結論としてはstateful ecnodingの場合はまともな方法では無理ぽ。

HZ-GB2312 で考えた場合、

~{!!~}ABCD

つーmultibyte sequenceがあった場合、こいつをinitial stateでfgetwc() すると
wc = GB2312 0x2121で、先頭4byte ~{!! までが wide character に変換され、
fp には

~}ABCD

が残るわけ。ここで ASCII の文字 'Z' を ungetwc() すると
~}Z を fp に書き戻し、

~}Z~}ABCD

という multibye sequence になるのだけど、ASCII の ~} つー escape sequcence が
重複してしまい、 EILSEQ になるんよね。
fp が ~} の ASCII の escape sequence で 始まる場合は、
~}Z~{ をfpに書き戻せば

~}Z~{~}ABCD

になり正しい mutibyte sequence になるけども、
ungetwc() する時点では 無理矢理 fp を先読みしない限り、
そいつぁー判断できないのよね...

@x.org + XFree86

http://slashdot.jp/article.pl?sid=04/01/23/0354231&topic=84&mode=flat&threshold=-1
えーっと、樋浦氏が x.org は Xutf8* は 絶対に accept しないといってた件もチャラ?
いや、いまさら無理だってのは判るけど:-)

2004/01/26(Mon)

OpenBSD/Citrus

@作業1

漏れのpatchももうじき要らなくなるのかな?と期待しつつもメンテ中。
locale/iconvをloadable moduleとしないcompile optionを用意、かつデフォにする作業。
これはXFree86のlocale回りも非loadable moduleになってるOpenBSD事情を考慮して。
これは既に終わってる、そんなにlibcのサイズも気にはならないな。

@作業2

以前のstatic linked binaryが dlfcnのスタブ 呼び出して"Wrong dl symbols!"という
メッセージを垂れ流す件について、本格的に対応を開始。

そもそもNetBSDのコードでは、*.o(for libc.a) と *.so(for libc.so)は
CSHLIBFLAG(bsd.lib.mk参照)によって別オプション(-D_I18N_DYNAMIC)で
コンパイルされるので、そもそもdlopen()が呼ばれるはずがない(man setlocaleのBUG参照)。

で、OpenBSDではCSHLIBFLAGと同等のことをPICFLAGで実現しようとしてるんだけど、
失敗している模様。

@作業3

作業2が完了したら、/ 以下のstatic linked binaryがlocale/iconvを利用できるか否かの
ようにするcompile optionを用意する。/ 以下の容量を気にする人たち向け。

2004/01/27(Tue)

(tbs

@Citrus/OpenBSD

昨日の作業2の原因は漏れの大チョンボですた。
余計なCPPFLAGS+=-D_I18N_DYNAMICが指定されていたのが原因。

明日くらいにはpatchを更新する予定。
NetBSD由来の新機能は、gettext/libintlがiconvを使うようになったってとこくらい。