Not only is the Internet dead, it's starting to smell really bad.:2007年09月上旬

2007/09/06(Thu)

[NetBSD] pkgsrc/print/acroread7

acroread7でもフォントが変ですか。
うちでは 何もしなくてもちゃんと表示できてるんだよなぁ。
一応以下の設定方法で変更できると思います。

acroread5まではMotifアプリだったのでUIのフォントは~/.Xdefaultsで指定できました。
詳しくは${LOCALBASE}/Acroread5/Reader/intellinux/app-defaults/AcroRead参照してください。

acroread7からはGTK2アプリになったので~/.gtkrc-2.0で指定します。

style "hoge" {
    font_name="Gothic"
}
widget_class "*" style "hoge"

font_nameの右辺にfirefoxと同じくmonafontを指定してます。

もうちょい細かい指定をしたい場合、pangorcとかpango*.aliasの設定なんかも必要ですが
それは又の機会に(まだちゃんと調べてないともいう)。

2007/09/07(Fri)

[C言語] iconv(3)によるコード変換

http://code.nanigac.com/source/view/20 ネタ。

戻り値(size_t)-1の場合、errnoがEINVALあるいはE2BIGの場合にはリスタート可能なんだけど
そこんとこの処理を端折って一律エラー終了してるからあんまりいい例じゃない罠。

それとiconvの場合、変換前/後のバイト列を固定長で確保するのは正直お薦めしない。
↓ readerから読込んだバイト列をiconv(3)で変換してwriterに書き込む「悪い」サンプル。

	FILE *reader, *writer;
	const char *from, *to;
	iconv_t cd;
	char inbuf[BUFSIZ], outbuf[BUFSIZ], *in, *out;
	size_t inbytes, outbytes, irreversible, ret, nconv;

	irreversible = (size_t)0;
	cd = iconv_open(to, from);
	if (cd == (iconv_t)-1)
		errx(1, "can't iconv");
	while ((inbytes = fread(inbuf, 1, sizeof(inbuf), reader)) > 0) {
		in = &inbuf[0];
		while (inbytes > 0) {
			out = &outbuf[0];
			outbytes = sizeof(outbuf);
			ret = iconv(cd, &in, &inbytes, &out, &outbytes);
			nconv = sizeof(outbuf) - outbytes;
			if (ret == (size_t)-1) {
				switch (errno) {
				case EINVAL:
					… (A)
					break;
				case E2BIG:
					… (B)
					break;
				default:
					errx(1, "can't iconv");
				}
			} else {
				irreversible += ret;
			}
			if (nconv > 0)
				fwrite(outbuf, 1, nconv, writer);
		}
	}
	…

inbuf/outbuf を固定長で確保してるんだけど、これだと (A) (B) の2個所で困ることになる。

つーわけでちゃんと残らず余さず文字コード変換したいなら、動的確保すべし。
この コードを参考にしてみてください。

(追記)
コメントへの返答は 9/8のメモに書いたのでそっちもどうぞ。

*1:厳密には stateful encoding で冗長な escape sequence が続く場合、MB_CUR_MAX は無限大になるんだけどね。
*2:fromのワイド文字数 : toのワイド文字数ね、バイト数の比じゃないです。
*3:んでも mbstate_t と違って iconv_t はコンストラクタ/デストラクタあるんだし動的確保しても良かったと思うんだけどね。

Sony α-700

α-10という噂だったけど、伝統の7ナンバー復活、そつなくまとまってていい感じ。

まあ俺は銀塩であと10年は戦う予定(フィルムがあれば、ね)なので、デジには興味ないんだけど。
α-100になかった シンクロターミナルがついたので
紛失しやすいこれのキャップがまた入手可能になるのはいいことだ。

しかし肝心のレンズの方はDT(APS-C専用設計)3本しかもOEMしか発表ないんか。
マスター…バーボン(以下略
噂の 24mm/F1.4 と 24-70mm/F2.8G には期待してたんだけどなぁ。

2007/09/08(Sat)

続 iconv(3)によるコード変換

shiroさんからコメントもらったので。

EINVALになったら残った入力をシフトして、出来たすき間に新しい入力を

読めば良い(状態遷移を起こす入力は消費されるから、すき間が出来ない
ということはない、と思う)

状態遷移 = escape sequence は必ず出現はしませんし。
Unicode Normarization Form Composition/Decompositionによる変換
JIS2004の丸付き数字とUnicodeとの変換の際のように
N:1変換が行われる場合、隙間が無くなる可能性があります。

E2BIGの場合も、出力バッファをフラッシュしてから処理を続行することを念頭に置いている。

これも同様ですね、1:1ならoutbufに最低でもMB_LEN_MAX保証すれば良さそうですが
1:N変換の時にはinは完全に変換できるバイト列であっても
outbufには1バイトも書き込めない可能性があり、無限ループに陥ります。
以下、GNU libiconvの//TRANSLITの挙動。

#include <iconv.h>
#include <errno.h>

int
main(void)
{
	iconv_t cd;
	char *in = "\\u3231", *out, outbuf[3];
	size_t nin, nout;
	cd = iconv_open("EUC-JP//TRANSLIT", "C99");
	if (cd == (iconv_t)-1)
		exit(1);
	nin = strlen(in);
	out = &outbuf[0];
	nout = sizeof(outbuf);
	printf("%d\n", iconv(cd, &in, &nin, &out, &nout));
	printf("%s\n", strerror(errno));
	printf("%.*s\n", sizeof(outbuf) - nout, outbuf);
}

\\u3231は//TRANSLITで

(株)

に転写されて変換されますが、outbufのサイズがEUC-JPのMB_CUR_MAX=3なら

(株

までは書き込めるはずなんだけど、1バイトもoutに書き込まれないんですよ。
(これは転写した文字は不可逆変換とカウントしてiconvの戻り値として返す仕様との整合を取る為ですな)

このあたりの事情を考慮して入出力バッファですらdynamic allocationが必要ですってのが私の主張。
まあ元々の仕様は固定長バッファを想定して策定されたんだとは思いますが。

"実用上は" と "理論上は" の温度差もあるかも。
固定長であってもある程度のサイズがあれば実用上問題無いからねぇ。
100%問題無いコードを書くとこうなりますよ、ってことで。