蝉は、やがて死ぬる午後に気づいた。ああ、私たち、もっと仕合せになってよかったのだ。:2008年03月03日分

2008/03/03(Mon)

週末

Hi-Maticのピント調整がイマイチだったのでバラして組み直したり。

最近買ったもの

[NetBSD] Citrus iconv

すっかり忘れてたのだが、 この問題も直さないとな。

前回の ISO-2022-JP問題の対応がいまいちいちイケてないわけですな。

もうちょいコード整理しないとアレだけどこんな感じ?

Index: citrus_iconv_std.c
===================================================================
RCS file: /cvs/cvsroot/src/lib/libc/citrus/modules/citrus_iconv_std.c,v
retrieving revision 1.15
diff -u -r1.15 citrus_iconv_std.c
--- citrus_iconv_std.c	13 Nov 2006 19:08:19 -0000	1.15
+++ citrus_iconv_std.c	3 Mar 2008 09:30:48 -0000
@@ -477,6 +477,57 @@
 	if (in==NULL || *in==NULL) {
 		/* special cases */
 		if (out!=NULL && *out!=NULL) {
+			for (;;) {
+				ret = get_state_desc_gen(
+				    &sc->sc_src_encoding, &state);
+				if (ret)
+					goto err;
+				if (state == _STDENC_SDGEN_INITIAL ||
+				    state == _STDENC_SDGEN_STABLE)
+					break;
+				save_encoding_state(&sc->sc_src_encoding);
+				save_encoding_state(&sc->sc_dst_encoding);
+
+				/* XXX FIXME, need to heavily rework. */
+				tmpin = "";
+				szrin = 0;
+				ret = mbtocsx(&sc->sc_src_encoding,
+				      &csid, &idx, &tmpin, 1, &szrin);
+
+				if (ret)
+					goto err;
+				if (szrin == (size_t)-2) {
+					ret = EINVAL;
+					goto err;
+				}
+				/* convert the character */
+				ret = do_conv(is, sc, &csid, &idx);
+				if (ret) {
+					if (ret != E_NO_CORRESPONDING_CHAR)
+						goto err;
+					++inval;
+					szrout = 0;
+					if ((flags & _CITRUS_ICONV_F_HIDE_INVALID) == 0 &&
+					    is->is_use_invalid) {
+						ret = wctombx(
+						    &sc->sc_dst_encoding,
+						    *out, *outbytes,
+						    is->is_invalid,
+						    &szrout);
+						if (ret)
+							goto err;
+					}
+				} else {
+					ret = cstombx(&sc->sc_dst_encoding,
+					      *out, *outbytes,
+					      csid, idx, &szrout);
+					if (ret)
+						goto err;
+				}
+				*outbytes -= szrout;
+				*out += szrout;
+			}
+
 			/* init output state and store the shift sequence */
 			save_encoding_state(&sc->sc_src_encoding);
 			save_encoding_state(&sc->sc_dst_encoding);
@@ -505,12 +556,8 @@
 
 	/* normal case */
 	for (;;) {
-		if (*inbytes==0) {
-			ret = get_state_desc_gen(&sc->sc_src_encoding, &state);
-			if (state == _STDENC_SDGEN_INITIAL ||
-			    state == _STDENC_SDGEN_STABLE)
-				break;
-		}
+		if (*inbytes == 0)
+			break;
 
 		/* save the encoding states for the error recovery */
 		save_encoding_state(&sc->sc_src_encoding);
@@ -524,22 +571,8 @@
 		if (ret)
 			goto err;
 
-		if (szrin == (size_t)-2) {
-			/* incompleted character */
-			ret = get_state_desc_gen(&sc->sc_src_encoding, &state);
-			if (ret) {
-				ret = EINVAL;
-				goto err;
-			}
-			switch (state) {
-			case _STDENC_SDGEN_INITIAL:
-			case _STDENC_SDGEN_STABLE:
-				/* fetch shift sequences only. */
-				goto next;
-			}
-			ret = EINVAL;
-			goto err;
-		}
+		if (szrin == (size_t)-2)
+			goto next;
 		/* convert the character */
 		ret = do_conv(is, sc, &csid, &idx);
 		if (ret) {

以前のエントリではdst(cs/idx -> wc -> mb)側のstate objectを初期化するput_state_reset()と同様に
src(mb -> wc -> cs/idx)側のstate objectも初期化する必要があるよね、と書いたのだけども
ここではmbtocsx()で代用してる(XXX FIXMEの部分)。

この部分どうしようかね、mbtocs()が内部で呼ぶmbrtowc_priv()は

mb = NULL;
mbrtowc_priv(ei, &wc, &mb, 0, ps, &nr);

という呼出をした場合、mbrtowc(3)の仕様である

If s is a null pointer, the mbrtowc() function shall be equivalent to the call:
mbrtowc(NULL, "", 1, ps)

通りの動作をするので、wcを無視してpsを初期化しちまうのだが
DR#288のケースをうまく扱おうとするとここは
「psの中にまだ変換可能なwchar_tがある場合、それを吐き出す」
という動作をして貰いたいよな。

今は緊急避難で"", 1を喰わせて回避してるのだが、ちとkludge過ぎる。
というのも、VIQRならこれでも解決するんだが、UTF-5のバヤイそもそも""はillegal byte sequenceだ罠。