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

2004/02/01(Sun)

(tbs

@OpenBSD/Citrus

20040201版
デフォでは dynamic loadable module を作って /usr/lib/i18n 以下にインストールしますが、
/etc/mk.conf に CITRUS_BUILD_LOADABLE_MODULE=no を追加すると builtin になります。

結局 作業3の static linked binary で multibyte locale を使用可能にする compile option は
用意しない事にしました。

  • bsd.lib.mk に手を入れるか、citrus_module.c だけ Makefile で
    特別扱いしてやる必要がある、あまり美しくなさげ
  • Solaris でも static linked binary では C/POSIX ロケールしか使えない

ってなところが理由ですかね。

2004/02/06(Fri)

(tbs

@widec.h

に定義されてる関数のうち、ws*系は殆どがwcs*と同じなんだけど、
ws(n)casecmpとかwsdupはwchar.hにはない機能なので実装するのもいいかもね。
glibcだとwcs(n)casecmpやwcsdupという拡張があるようですが。

でっちあげるとこんな感じか。
str(n)casecmpとstrdupのコードが元なので、それぞれのライセンスに準じまつ。

#include "namespace.h"
#include <assert.h>
#include <wctype.h>
#include <widec.h>

#include "runetype.h"

int
wscasecmp(s1, s2)
	const wchar_t *s1, *s2;
{
	_DIAGASSERT(s1 != NULL);
	_DIAGASSERT(s2 != NULL);

	while (towlower(*s1) == towlower(*s2++))
		if (*s1++ == L'\0')
			return (0);
	return ((int)((__nbrune_t)towlower(*s1) - (__nbrune_t)towlower(*--s2)));
}

int
wsncasecmp(s1, s2, n)
	const wchar_t *s1, *s2;
	size_t n;
{

	_DIAGASSERT(s1 != NULL);
	_DIAGASSERT(s2 != NULL);
	if (s1 == NULL || s2 == NULL)
		return (0);

	if (n != 0) {
		do {
			if (towlower(*s1) != towlower(*s2++))
				return ((int)((__nbrune_t)towlower(*s1) -
					      (__nbrune_t)towlower(*--s2)));
			if (*s1++ == L'\0')
				break;
		} while (--n != 0);
	}
	return (0);
}
#include "namespace.h"

#include <assert.h>
#include <wchar.h>
#include <widec.h>

wchar_t *
wsdup(str)
	const wchar_t *str;
{
	size_t len;
	wchar_t *copy;

	_DIAGASSERT(str != NULL);

	len = (wcslen(str) + 1) * sizeof(wchar_t);
	if (!(copy = malloc(len)))
		return (NULL);
	memcpy(copy, str, len);

	return (copy);
}

strtows/wstostrとかも実装するならこんな感じ↓にして
citrus_ctype_templete.h行きかね。

static int
_FUNCNAME(ctype_strtows)(_citrus_ctype_rec_t * __restrict cc,
			 wchar_t * __restrict ws,
			 char * __restrict s,
			 wchar_t ** __restrict ret)
{
	_ENCODING_INFO *ei;
	_ENCODING_STATE state;
	wchar_t *ws0;
	size_t mbcurmax, siz;
	int err;

	_DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
	_DIAGASSERT(ws != NULL);
	_DIAGASSERT(s != NULL);
	_DIAGASSERT(ret != NULL);

	ws0 = ws;
	ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
	_FUNCNAME(init_state)(ei, &state);
	mbcurmax = _ENCODING_MB_CUR_MAX(ei);

	for (;;) {
		err = _FUNCNAME(mbrtowc_priv)(ei,
			ws0, &s, mbcurmax, &state, &siz);
		_DIAGASSERT(siz != (size_t)-2)
		if (err) {
			err = EILSEQ;
			*ret = (wchar_t *)NULL;
			break;
		}
		if (siz == 0) {
			*ret = ws;
			break;
		}
		ws0++;
		s += siz;
	}

	return (err);
}

static int
_FUNCNAME(ctype_wstostr)(_citrus_ctype_rec_t * __restrict cc,
			 char * __restrict s,
			 wchar_t * __restrict ws,
			 char ** __restrict s)
{
	_ENCODING_INFO *ei;
	_ENCODING_STATE state;
	char *s0;
	size_t mbcurmax, siz;
	int err;

	_DIAGASSERT(cc != NULL & cc->cc_closure != NULL);
	_DIAGASSERT(s != NULL);
	_DIAGASSERT(ws != NULL);
	_DIAGASSERT(ret != NULL);

	s0 = s;
	ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
	_FUNCNAME(init_state)(ei, &state);
	mbcurmax = _ENCODING_MB_CUR_MAX(ei);

	for (;;) {
		err = _FUNCNAME(wcrtomb_priv)(ei,
			s0, mbcurmax, *ws, &state, &siz);
		if (err) {
			err = EILSEQ;
			*ret = NULL;
			break;
		}
		if (*ws == L'\0') {
			*ret = s;
			break;
		}
		s0 += siz;
		ws++;
	}

	return (err);
}

ただしこいつはlength checkのないヤバい関数だから__warn_reference要かも。

2004/02/16(Mon)

(tbs

@citrus UTF7 support

書き直した。 /distfiles/citrus/NetBSD/citrus_utf7-20040216.diff.gz
citrus_ctype_templete.hに手を加えてるのはwcsrtombsやiconvで冗長な変換を防ぐ為
(L"あい" が +MEI-+MEQ- でなく+MEIwRAと変換されるようにしている)。

UCS<->JISX0201の変換がコケるのは↓のpatchにて。
/distfiles/citrus/NetBSD/00_jisx0201-fix.patch

@その他放置中 module一覧

HZ/HZ+/EHZ support
/distfiles/citrus/NetBSD/citrus_HZ-20030821.patch.bz2
iconvdataは用意した、あとはコードの整理。
zW support
/distfiles/citrus/NetBSD/citrus_zW-20030813.tar.bz2
/diary/?20030808#08-1
/diary/?20030813#13-1
あたりの問題があるので、iconvをいじる必要ありだけどどうしたものか。