--- src.orig/sys/sys/kiconv.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/sys/kiconv.h	2011-07-12 09:36:01.000000000 +0900
@@ -0,0 +1,129 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by NONAKA Kimihiro.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef	_SYS_KICONV_H_
+#define	_SYS_KICONV_H_
+
+#if defined(_BSD_WCHAR_T_) && !defined(__cplusplus)
+typedef _BSD_WCHAR_T_   wchar_t;
+#undef  _BSD_WCHAR_T_
+#endif
+
+#ifdef _BSD_MBSTATE_T_
+typedef _BSD_MBSTATE_T_ mbstate_t;
+#undef _BSD_MBSTATE_T_
+#endif
+
+#ifdef  _BSD_WINT_T_
+typedef _BSD_WINT_T_    wint_t;
+#undef  _BSD_WINT_T_
+#endif
+
+#ifdef  _BSD_WCTRANS_T_
+typedef _BSD_WCTRANS_T_ wctrans_t;
+#undef  _BSD_WCTRANS_T_
+#endif
+
+#ifdef  _BSD_WCTYPE_T_
+typedef _BSD_WCTYPE_T_  wctype_t;
+#undef  _BSD_WCTYPE_T_
+#endif
+
+#ifndef WEOF
+#define WEOF    ((wint_t)-1)
+#endif
+
+#ifndef EOF
+#define EOF    (-1)
+#endif
+
+#define	MB_LEN_MAX	32	/* Allow ISO/IEC 2022 */
+
+/* wchar_t PATH_MAX pool and cache */
+extern pool_cache_t kiconv_wchar_pathbuf_cache;
+#define WPNBUF_GET() \
+	pool_cache_get(kiconv_wchar_pathbuf_cache, PR_WAITOK)
+#define WPNBUF_PUT(wpnb) \
+	pool_cache_put(kiconv_wchar_pathbuf_cache, (wpnb))
+
+typedef struct _kiconv_impl_t	*kiconv_t;
+typedef struct _klocale_impl_t	*klocale_t;
+
+void		kiconv_init(void);
+
+kiconv_t	kiconv_open(const char *, const char *, int *);
+int		kiconv_close(kiconv_t, int *);
+size_t		kiconv_conv(kiconv_t, const char **, size_t *, char **,
+		    size_t *, int *);
+size_t		__kiconv_conv(kiconv_t, const char **, size_t *, char **,
+		    size_t *, uint32_t, size_t *, int *);
+
+klocale_t	kiconv_newlocale(const char *, int *);
+int		kiconv_freelocale(klocale_t, int *);
+
+int		kiconv_mbsinit_l(const mbstate_t *, klocale_t, int *);
+size_t		kiconv_mbrlen_l(const char * __restrict, size_t,
+		    mbstate_t * __restrict, klocale_t, int *);
+size_t		kiconv_mbrtowc_l(wchar_t * __restrict, const char * __restrict,
+		    size_t, mbstate_t *, klocale_t, int *);
+size_t		kiconv_mbsrtowcs_l(wchar_t * __restrict,
+		    const char ** __restrict, size_t, mbstate_t * __restrict,
+		    klocale_t, int *);
+size_t		kiconv_wcrtomb_l(char * __restrict, wchar_t wc,
+		    mbstate_t * __restrict, klocale_t, int *);
+size_t		kiconv_wcsrtombs_l(char * __restrict,
+		    const wchar_t ** __restrict, size_t,
+		    mbstate_t * __restrict, klocale_t, int *);
+wint_t		kiconv_btowc_l(int, klocale_t, int *);
+int		kiconv_wctob_l(wint_t, klocale_t, int *);
+int		kiconv_wcwidth_l(wchar_t, klocale_t);
+int		kiconv_wcswidth_l(const wchar_t *, size_t, klocale_t);
+
+int		kiconv_iswalnum_l(wint_t, klocale_t);
+int		kiconv_iswalpha_l(wint_t, klocale_t);
+int		kiconv_iswblank_l(wint_t, klocale_t);
+int		kiconv_iswcntrl_l(wint_t, klocale_t);
+int		kiconv_iswdigit_l(wint_t, klocale_t);
+int		kiconv_iswgraph_l(wint_t, klocale_t);
+int		kiconv_iswlower_l(wint_t, klocale_t);
+int		kiconv_iswprint_l(wint_t, klocale_t);
+int		kiconv_iswpunct_l(wint_t, klocale_t);
+int		kiconv_iswspace_l(wint_t, klocale_t);
+int		kiconv_iswupper_l(wint_t, klocale_t);
+int		kiconv_iswxdigit_l(wint_t, klocale_t);
+wint_t		kiconv_towupper_l(wint_t, klocale_t);
+wint_t		kiconv_towlower_l(wint_t, klocale_t);
+wctype_t	kiconv_wctype_l(const char *, klocale_t);
+wctrans_t	kiconv_wctrans_l(const char *, klocale_t);
+int		kiconv_iswctype_l(wint_t, wctype_t, klocale_t);
+wint_t		kiconv_towctrans_l(wint_t, wctrans_t, klocale_t);
+
+#endif	/* _SYS_KICONV_H_ */
--- src.orig/sys/conf/files	2011-09-29 23:04:00.000000000 +0900
+++ src/sys/conf/files	2011-09-29 23:15:21.000000000 +0900
@@ -1475,6 +1475,7 @@
 file	kern/kern_fork.c
 file	kern/kern_idle.c
 file	kern/kern_hook.c
+file	kern/kern_kiconv.c
 file	kern/kern_kthread.c
 file	kern/kern_ktrace.c		ktrace
 file	kern/kern_ksyms.c		ksyms | ddb | modular needs-flag
@@ -1737,3 +1738,8 @@
 # NOR subsytem
 #
 include "dev/nor/files.nor"
+
+#
+# in-kernel iconv
+#
+include "kiconv/files.kiconv"
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kern/init_main.c src/sys/kern/init_main.c
--- src.orig/sys/kern/init_main.c	2011-09-29 23:04:34.000000000 +0900
+++ src/sys/kern/init_main.c	2011-09-29 23:15:23.000000000 +0900
@@ -172,6 +172,7 @@
 #include <sys/ksyms.h>
 #include <sys/uidinfo.h>
 #include <sys/kprintf.h>
+#include <sys/kiconv.h>
 #ifdef FAST_IPSEC
 #include <netipsec/ipsec.h>
 #endif
@@ -599,6 +600,9 @@
 
 	procinit_sysctl();
 
+	/* Initialize in-kernel iconv. */
+	kiconv_init();
+
 	/*
 	 * Create process 1 (init(8)).  We do this now, as Unix has
 	 * historically had init be process 1, and changing this would
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kern/kern_kiconv.c src/sys/kern/kern_kiconv.c
--- src.orig/sys/kern/kern_kiconv.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kern/kern_kiconv.c	2011-07-12 09:44:53.000000000 +0900
@@ -0,0 +1,997 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by NONAKA Kimihiro.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_kiconv.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/pool.h>
+#include <sys/rwlock.h>
+
+#define	_KICONV_LOCAL
+#include <kiconv/kiconv.h>
+
+#define	MODNAME	"kiconv"
+
+int kiconv_debug = 0;
+
+MALLOC_DEFINE(M_KICONV, "kiconv", "in-kernel iconv buffer");
+pool_cache_t kiconv_wchar_pathbuf_cache;
+pool_cache_t kiconv_linebuf_cache;
+
+TAILQ_HEAD(kglist, kiconv_getops);
+static struct kglist allkg = TAILQ_HEAD_INITIALIZER(allkg);
+static struct kiconv_ops *ops;
+static kmutex_t getops_lock __cacheline_aligned;
+static krwlock_t ops_lock __cacheline_aligned;
+static bool kiconv_inited;
+
+static __inline void kiconv_attach_getops1(struct kiconv_getops *);
+
+void
+kiconv_init(void)
+{
+
+	if (kiconv_inited)
+		return;
+
+	mutex_init(&getops_lock, MUTEX_DEFAULT, IPL_NONE);
+	rw_init(&ops_lock);
+
+	kiconv_wchar_pathbuf_cache = pool_cache_init(PATH_MAX * sizeof(wchar_t),
+	    0, 0, 0, "wpnbuf", NULL, IPL_NONE, NULL, NULL, NULL);
+	KASSERT(kiconv_wchar_pathbuf_cache != NULL);
+	kiconv_linebuf_cache = pool_cache_init(LINE_MAX, 0, 0, 0, "linebufpl",
+	    NULL, IPL_NONE, NULL, NULL, NULL);
+	KASSERT(kiconv_linebuf_cache != NULL);
+
+	kiconv_inited = true;
+}
+
+/*
+ * kiconv ops
+ */
+void
+kiconv_attach_ops(struct kiconv_ops *ko)
+{
+
+	KASSERT(kiconv_inited);
+
+	rw_enter(&ops_lock, RW_WRITER);
+	ops = ko;
+	rw_exit(&ops_lock);
+}
+
+void
+kiconv_detach_ops(struct kiconv_ops *ko)
+{
+
+	KASSERT(kiconv_inited);
+
+	rw_enter(&ops_lock, RW_WRITER);
+	if (ops == ko)
+		ops = NULL;
+	rw_exit(&ops_lock);
+}
+
+/*
+ * module/iconv/mapper getops
+ */
+static __inline void
+kiconv_attach_getops1(struct kiconv_getops *kg)
+{
+
+	mutex_enter(&getops_lock);
+	TAILQ_INSERT_TAIL(&allkg, kg, kg_list);
+	mutex_exit(&getops_lock);
+}
+
+void
+kiconv_attach_getops(struct kiconv_getops *kg)
+{
+
+	KASSERT(kiconv_inited);
+
+	kiconv_attach_getops1(kg);
+}
+
+void
+kiconv_detach_getops(struct kiconv_getops *kg)
+{
+
+	KASSERT(kiconv_inited);
+
+	mutex_enter(&getops_lock);
+	TAILQ_REMOVE(&allkg, kg, kg_list);
+	mutex_exit(&getops_lock);
+}
+
+struct kiconv_getops *
+kiconv_find_getops(const char *name)
+{
+	struct kiconv_getops *kg;
+
+	KASSERT(kiconv_inited);
+
+	mutex_enter(&getops_lock);
+	TAILQ_FOREACH(kg, &allkg, kg_list) {
+		if (strcmp(name, kg->kg_name) == 0) {
+			mutex_exit(&getops_lock);
+			return kg;
+		}
+	}
+	mutex_exit(&getops_lock);
+	return NULL;
+}
+
+#if !defined(KICONV) || (KICONV == 0)
+/*
+ * modular version
+ */
+kiconv_t
+kiconv_open(const char *out, const char *in, int *errnop)
+{
+	bool retried = false;
+	kiconv_t handle;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		module_hold(MODNAME);
+		handle = (*ops->iconv_open)(out, in, errnop);
+		if (handle == (kiconv_t)-1)
+			module_rele(MODNAME);
+		rw_exit(&ops_lock);
+		return handle;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (kiconv_t)-1;
+}
+
+int
+kiconv_close(kiconv_t handle, int *errnop)
+{
+	bool retried = false;
+	int result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->iconv_close)(handle, errnop);
+		if (result == 0)
+			module_rele(MODNAME);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return -1;
+}
+
+size_t
+kiconv_conv(kiconv_t handle, const char **in, size_t *szin, char **out,
+    size_t *szout, int *errnop)
+{
+	bool retried = false;
+	size_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->iconv)(handle, in, szin, out, szout, 0,
+		    NULL, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (size_t)-1;
+}
+
+size_t
+__kiconv_conv(kiconv_t handle, const char **in, size_t *szin, char **out,
+    size_t *szout, uint32_t flags, size_t *invalids, int *errnop)
+{
+	bool retried = false;
+	size_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->iconv)(handle, in, szin, out, szout,
+		    flags, invalids, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (size_t)-1;
+}
+
+klocale_t
+kiconv_newlocale(const char *locale, int *errnop)
+{
+	bool retried = false;
+	klocale_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		module_hold(MODNAME);
+		result = (*ops->newlocale)(locale, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (klocale_t)NULL;
+}
+
+int
+kiconv_freelocale(klocale_t locale, int *errnop)
+{
+	bool retried = false;
+	int result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->freelocale)(locale, errnop);
+		if (result == 0)
+			module_rele(MODNAME);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return -1;
+}
+
+size_t
+kiconv_mbrlen_l(const char *s, size_t n, mbstate_t *ps, klocale_t locale,
+    int *errnop)
+{
+	bool retried = false;
+	size_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->mbrlen)(s, n, ps, locale, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (size_t)-1;
+}
+
+int
+kiconv_mbsinit_l(const mbstate_t *ps, klocale_t locale, int *errnop)
+{
+	bool retried = false;
+	int result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->mbsinit)(ps, locale, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return -1;
+}
+
+size_t
+kiconv_mbrtowc_l(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps,
+    klocale_t locale, int *errnop)
+{
+	bool retried = false;
+	size_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->mbrtowc)(pwc, s, n, ps, locale, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (size_t)-1;
+}
+
+size_t
+kiconv_mbsrtowcs_l(wchar_t *pwcs, const char **s, size_t n, mbstate_t *ps,
+    klocale_t locale, int *errnop)
+{
+	bool retried = false;
+	size_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->mbsrtowcs)(pwcs, s, n, ps, locale, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (size_t)-1;
+}
+
+size_t
+kiconv_wcrtomb_l(char *s, wchar_t wc, mbstate_t *ps, klocale_t locale,
+    int *errnop)
+{
+	bool retried = false;
+	size_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->wcrtomb)(s, wc, ps, locale, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (size_t)-1;
+}
+
+size_t
+kiconv_wcsrtombs_l(char *s, const wchar_t **ppwcs, size_t n, mbstate_t *ps,
+    klocale_t locale, int *errnop)
+{
+	bool retried = false;
+	size_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->wcsrtombs)(s, ppwcs, n, ps, locale, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (size_t)-1;
+}
+
+wint_t
+kiconv_btowc_l(int c, klocale_t locale, int *errnop)
+{
+	bool retried = false;
+	wint_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->btowc)(c, locale, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return (wint_t)-1;
+}
+
+int
+kiconv_wctob_l(wint_t wc, klocale_t locale, int *errnop)
+{
+	bool retried = false;
+	int result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->wctob)(wc, locale, errnop);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	if (errnop)
+		*errnop = ENOENT;
+	return -1;
+}
+
+int
+kiconv_wcwidth_l(wchar_t wc, klocale_t locale)
+{
+	bool retried = false;
+	int result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->wcwidth)(wc, locale);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	return -1;
+}
+
+int
+kiconv_wcswidth_l(const wchar_t *wcs, size_t wn, klocale_t locale)
+{
+	bool retried = false;
+	int result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->wcswidth)(wcs, wn, locale);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	return -1;
+}
+
+#define	_KICONV_ISWCTYPE_FUNC(name)					\
+int									\
+kiconv_isw##name##_l(wint_t wc, klocale_t locale)			\
+{									\
+	bool retried = false;						\
+	int result;							\
+									\
+	KASSERT(kiconv_inited);						\
+									\
+retry:									\
+	rw_enter(&ops_lock, RW_READER);					\
+	if (ops) {							\
+		result = (*ops->isw##name)(wc, locale);			\
+		rw_exit(&ops_lock);					\
+		return result;						\
+	}								\
+	rw_exit(&ops_lock);						\
+	if (!retried) {							\
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);	\
+		retried = true;						\
+		goto retry;						\
+	}								\
+									\
+	printf("%s: kiconv module couldn't load.", __func__);		\
+	return -1;							\
+}
+_KICONV_ISWCTYPE_FUNC(alnum)
+_KICONV_ISWCTYPE_FUNC(alpha)
+_KICONV_ISWCTYPE_FUNC(blank)
+_KICONV_ISWCTYPE_FUNC(cntrl)
+_KICONV_ISWCTYPE_FUNC(graph)
+_KICONV_ISWCTYPE_FUNC(lower)
+_KICONV_ISWCTYPE_FUNC(print)
+_KICONV_ISWCTYPE_FUNC(punct)
+_KICONV_ISWCTYPE_FUNC(space)
+_KICONV_ISWCTYPE_FUNC(upper)
+_KICONV_ISWCTYPE_FUNC(xdigit)
+
+#define	_KICONV_TOWCTYPE_FUNC(name)					\
+wint_t									\
+kiconv_tow##name##_l(wint_t wc, klocale_t locale)			\
+{									\
+	bool retried = false;						\
+	wint_t result;							\
+									\
+	KASSERT(kiconv_inited);						\
+									\
+retry:									\
+	rw_enter(&ops_lock, RW_READER);					\
+	if (ops) {							\
+		result = (*ops->tow##name)(wc, locale);			\
+		rw_exit(&ops_lock);					\
+		return result;						\
+	}								\
+	rw_exit(&ops_lock);						\
+	if (!retried) {							\
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);	\
+		retried = true;						\
+		goto retry;						\
+	}								\
+									\
+	printf("%s: kiconv module couldn't load.", __func__);		\
+	return (wint_t)-1;						\
+}
+_KICONV_TOWCTYPE_FUNC(upper)
+_KICONV_TOWCTYPE_FUNC(lower)
+
+wctype_t
+kiconv_wctype_l(const char *property, klocale_t locale)
+{
+	bool retried = false;
+	wctype_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->wctype)(property, locale);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	return (wctype_t)0;
+}
+
+wctrans_t
+kiconv_wctrans_l(const char *property, klocale_t locale)
+{
+	bool retried = false;
+	wctrans_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->wctrans)(property, locale);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	return (wctrans_t)0;
+}
+
+int
+kiconv_iswctype_l(wint_t wc, wctype_t desc, klocale_t locale)
+{
+	bool retried = false;
+	int result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->iswctype)(wc, desc, locale);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	return 0;
+}
+
+wint_t
+kiconv_towctrans_l(wint_t wc, wctrans_t desc, klocale_t locale)
+{
+	bool retried = false;
+	wint_t result;
+
+	KASSERT(kiconv_inited);
+
+retry:
+	rw_enter(&ops_lock, RW_READER);
+	if (ops) {
+		result = (*ops->towctrans)(wc, desc, locale);
+		rw_exit(&ops_lock);
+		return result;
+	}
+	rw_exit(&ops_lock);
+	if (!retried) {
+		(void)module_autoload(MODNAME, MODULE_CLASS_MISC);
+		retried = true;
+		goto retry;
+	}
+
+	printf("%s: kiconv module couldn't load.", __func__);
+	return (wint_t)WEOF;	/* XXX */
+}
+#else	/* KICONV && (KICONV > 0) */
+/*
+ * static link version
+ */
+kiconv_t
+kiconv_open(const char *out, const char *in, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_open(out, in, errnop);
+}
+
+int
+kiconv_close(kiconv_t handle, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_close(handle, errnop);
+}
+
+size_t
+kiconv_conv(kiconv_t handle, const char **in, size_t *szin, char **out,
+    size_t *szout, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_conv(handle, in, szin, out, szout, 0, NULL, errnop);
+}
+
+size_t
+__kiconv_conv(kiconv_t handle, const char **in, size_t *szin, char **out,
+    size_t *szout, uint32_t flags, size_t *invalids, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_conv(handle, in, szin, out, szout, flags, invalids,
+	    errnop);
+}
+
+klocale_t
+kiconv_newlocale(const char *locale, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_newlocale(locale, errnop);
+}
+
+int
+kiconv_freelocale(klocale_t locale, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_freelocale(locale, errnop);
+}
+
+size_t
+kiconv_mbrlen_l(const char *s, size_t n, mbstate_t *ps, klocale_t locale,
+    int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_mbrlen(s, n, ps, locale, errnop);
+}
+
+int
+kiconv_mbsinit_l(const mbstate_t *ps, klocale_t locale, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_mbsinit(ps, locale, errnop);
+}
+
+size_t
+kiconv_mbrtowc_l(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps,
+    klocale_t locale, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_mbrtowc(pwc, s, n, ps, locale, errnop);
+}
+
+size_t
+kiconv_mbsrtowcs_l(wchar_t *pwcs, const char **s, size_t n, mbstate_t *ps,
+    klocale_t locale, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_mbsrtowcs(pwcs, s, n, ps, locale, errnop);
+}
+
+size_t
+kiconv_wcrtomb_l(char *s, wchar_t wc, mbstate_t *ps, klocale_t locale,
+    int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_wcrtomb(s, wc, ps, locale, errnop);
+}
+
+size_t
+kiconv_wcsrtombs_l(char *s, const wchar_t **ppwcs, size_t n, mbstate_t *ps,
+    klocale_t locale, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_wcsrtombs(s, ppwcs, n, ps, locale, errnop);
+}
+
+wint_t
+kiconv_btowc_l(int c, klocale_t locale, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_btowc(c, locale, errnop);
+}
+
+int
+kiconv_wctob_l(wint_t wc, klocale_t locale, int *errnop)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_wctob(wc, locale, errnop);
+}
+
+int
+kiconv_wcwidth_l(wchar_t wc, klocale_t locale)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_wcwidth(wc, locale);
+}
+
+int
+kiconv_wcswidth_l(const wchar_t *wcs, size_t wn, klocale_t locale)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_wcswidth(wsc, wn, locale);
+}
+
+#define	_KICONV_ISWCTYPE_FUNC(name)					\
+int									\
+kiconv_isw##name##_l(wint_t wc, klocale_t locale)			\
+{									\
+									\
+	KASSERT(kiconv_inited);						\
+	return _kiconv_isw##name(wc, locale);				\
+}
+_KICONV_ISWCTYPE_FUNC(alnum)
+_KICONV_ISWCTYPE_FUNC(alpha)
+_KICONV_ISWCTYPE_FUNC(blank)
+_KICONV_ISWCTYPE_FUNC(cntrl)
+_KICONV_ISWCTYPE_FUNC(graph)
+_KICONV_ISWCTYPE_FUNC(lower)
+_KICONV_ISWCTYPE_FUNC(print)
+_KICONV_ISWCTYPE_FUNC(punct)
+_KICONV_ISWCTYPE_FUNC(space)
+_KICONV_ISWCTYPE_FUNC(upper)
+_KICONV_ISWCTYPE_FUNC(xdigit)
+
+#define	_KICONV_TOWCTYPE_FUNC(name)					\
+wint_t									\
+kiconv_tow##name##_l(wint_t wc, klocale_t locale)			\
+{									\
+									\
+	KASSERT(kiconv_inited);						\
+	return _kiconv_tow##name(wc, locale);				\
+}
+_KICONV_TOWCTYPE_FUNC(upper)
+_KICONV_TOWCTYPE_FUNC(lower)
+
+wctype_t
+kiconv_wctype_l(const char *property, klocale_t locale)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_wctype(property, locale);
+}
+
+wctrans_t
+kiconv_wctrans_l(const char *property, klocale_t locale)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_wctrans(property, locale);
+}
+
+int
+kiconv_iswctype_l(wint_t wc, wctype_t desc, klocale_t locale)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_iswctype(wc, desc, locale);
+}
+
+wint_t
+kiconv_towctrans_l(wint_t wc, wctrans_t desc, klocale_t locale)
+{
+
+	KASSERT(kiconv_inited);
+	return _kiconv_towctrans(wc, desc, locale);
+}
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/Makefile.inc src/sys/kiconv/Makefile.inc
--- src.orig/sys/kiconv/Makefile.inc	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/Makefile.inc	2011-06-04 22:14:49.000000000 +0900
@@ -0,0 +1,5 @@
+# $NetBSD$
+
+.PATH:	${S}/kiconv
+
+CPPFLAGS+= -I${S}/kiconv
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/_wctrans.c src/sys/kiconv/_wctrans.c
--- src.orig/sys/kiconv/_wctrans.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/_wctrans.c	2011-06-03 16:58:51.000000000 +0900
@@ -0,0 +1,115 @@
+/*	$NetBSD$	*/
+/*	NetBSD: _wctrans.c,v 1.17 2010/06/13 04:14:57 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: _wctrans.c,v 1.17 2010/06/13 04:14:57 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <assert.h>
+#include <wctype.h>
+#endif
+
+#include "runetype_local.h"
+#include "_wctrans_local.h"
+
+/*
+ * _towctrans_ext:
+ *	translate a character (extended part)
+ */
+wint_t
+_towctrans_ext(wint_t c, struct _WCTransEntry const *te)
+{
+	__nbrune_t c0;
+	uint32_t x;
+	_RuneRange *rr;
+	_RuneEntry *base, *re;
+
+	_DIAGASSERT(te != NULL);
+
+	if (c == WEOF)
+		return (c);
+
+	c0 = (__nbrune_t)c; /* XXX assumes wchar_t = int */
+	rr = te->te_extmap;
+	base = rr->rr_rune_ranges;
+	for (x = rr->rr_nranges; x != 0; x >>= 1) {
+		re = base + (x >> 1);
+		if (re->re_min <= c0 && re->re_max >= c0)
+			return (re->re_map + c0 - re->re_min);
+		else if (c0 >= re->re_max) {
+			base = re + 1;
+			x--;
+		}
+	}
+
+	return (c);
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/_wctrans_local.h src/sys/kiconv/_wctrans_local.h
--- src.orig/sys/kiconv/_wctrans_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/_wctrans_local.h	2011-06-04 12:45:39.000000000 +0900
@@ -0,0 +1,60 @@
+/*	$NetBSD: _wctrans_local.h,v 1.9 2010/06/02 15:47:25 tnozaki Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _WCTRANS_LOCAL_H_
+#define _WCTRANS_LOCAL_H_
+
+__BEGIN_DECLS
+wint_t	_towctrans_ext(wint_t, _WCTransEntry const *);
+__END_DECLS
+
+static __inline wint_t
+_towctrans_priv(_RuneLocale const *rl, wint_t c, _WCTransEntry const *te)
+{
+	return (_RUNE_ISCACHED(c)
+		? (wint_t)te->te_cached[(size_t)c]
+		: _towctrans_ext(c, te));
+}
+
+static __inline struct _WCTransEntry *
+_wctrans_lower(_RuneLocale *rl)
+{
+	_DIAGASSERT(rl->rl_wctrans[_WCTRANS_INDEX_LOWER].te_name != NULL);
+
+	return (&rl->rl_wctrans[_WCTRANS_INDEX_LOWER]);
+}
+
+static __inline struct _WCTransEntry *
+_wctrans_upper(_RuneLocale *rl)
+{
+	_DIAGASSERT(rl->rl_wctrans[_WCTRANS_INDEX_UPPER].te_name != NULL);
+
+	return (&rl->rl_wctrans[_WCTRANS_INDEX_UPPER]);
+}
+
+#endif /*_WCTRANS_LOCAL_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/_wctype.c src/sys/kiconv/_wctype.c
--- src.orig/sys/kiconv/_wctype.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/_wctype.c	2011-06-03 16:56:44.000000000 +0900
@@ -0,0 +1,121 @@
+/* $NetBSD$ */
+/* NetBSD: _wctype.c,v 1.9 2010/06/13 04:14:57 tnozaki Exp */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: _wctype.c,v 1.9 2010/06/13 04:14:57 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <sys/types.h>
+#include <assert.h>
+#include <wctype.h>
+#endif
+
+#include "runetype_local.h"
+#include "_wctrans_local.h"
+#include "_wctype_local.h"
+
+_RuneType
+_runetype_priv(_RuneLocale const *rl, wint_t wc)
+{
+	__nbrune_t wc0;
+	_RuneRange const *rr;
+	_RuneEntry *base, *re;
+	uint32_t x;
+
+	_DIAGASSERT(rl != NULL);
+
+	if (wc == WEOF)
+		return 0U;
+	if (_RUNE_ISCACHED(wc))
+		return rl->rl_runetype[(size_t)wc];
+	wc0 = (__nbrune_t)wc;
+	rr = &rl->rl_runetype_ext;
+	_DIAGASSERT(rr != NULL);
+	base = rr->rr_rune_ranges;
+	for (x = rr->rr_nranges; x != (uint32_t)0; x >>= 1) {
+		re = base + (x >> 1);
+		if (re->re_min <= wc0 && re->re_max >= wc0) {
+			if (re->re_rune_types)
+				return re->re_rune_types[wc0 - re->re_min];
+			else
+				return re->re_map;
+		} else if (wc0 > re->re_max) {
+			base = re + 1;
+			--x;
+		}
+	}
+	return (_RuneType)0U;
+}
+
+int
+_iswctype_priv(_RuneLocale const *rl,
+    wint_t wc, _WCTypeEntry const *te)
+{
+	return !!(_runetype_priv(rl, wc) & te->te_mask);
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/_wctype_local.h src/sys/kiconv/_wctype_local.h
--- src.orig/sys/kiconv/_wctype_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/_wctype_local.h	2011-06-03 16:54:01.000000000 +0900
@@ -0,0 +1,37 @@
+/* $NetBSD: _wctype_local.h,v 1.3 2010/06/02 15:47:25 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _WCTYPE_LOCAL_H_
+#define _WCTYPE_LOCAL_H_
+
+__BEGIN_DECLS
+_RuneType	_runetype_priv(_RuneLocale const *, wint_t);
+int		_iswctype_priv(_RuneLocale const *, wint_t, _WCTypeEntry const *);
+__END_DECLS
+
+#endif /*_WCTYPE_LOCAL_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_aliasname_local.h src/sys/kiconv/citrus_aliasname_local.h
--- src.orig/sys/kiconv/citrus_aliasname_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_aliasname_local.h	2011-06-03 16:27:25.000000000 +0900
@@ -0,0 +1,48 @@
+/* $NetBSD: citrus_aliasname_local.h,v 1.2 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ALIASNAME_LOCAL_H_
+#define _CITRUS_ALIASNAME_LOCAL_H_
+
+static __inline const char *
+__unaliasname(const char *dbname, const char *alias,
+    void *buf, size_t bufsize)
+{
+	return _lookup_simple(dbname, alias,
+	    buf, bufsize, _LOOKUP_CASE_SENSITIVE);
+}
+
+static __inline int
+__isforcemapping(const char *name)
+{
+	_DIAGASSERT(name != NULL);
+
+	return _bcs_strcasecmp("/force", name);
+}
+
+#endif /*_CITRUS_ALIASNAME_LOCAL_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_bcs.c src/sys/kiconv/citrus_bcs.c
--- src.orig/sys/kiconv/citrus_bcs.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_bcs.c	2011-06-04 22:26:02.000000000 +0900
@@ -0,0 +1,180 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_bcs.c,v 1.5 2005/05/14 17:55:42 tshiozak Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_bcs.c,v 1.5 2005/05/14 17:55:42 tshiozak Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#ifndef HOSTPROG
+#include "namespace.h"
+#endif
+#include <assert.h>
+#include <stdlib.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+/*
+ * case insensitive comparison between two C strings.
+ */
+int
+_citrus_bcs_strcasecmp(const char * __restrict str1,
+		       const char * __restrict str2)
+{
+	int c1 = 1, c2 = 1;
+
+	while (c1 && c2 && c1 == c2) {
+		c1 = _bcs_toupper(*str1++);
+		c2 = _bcs_toupper(*str2++);
+	}
+
+	return ((c1 == c2) ? 0 : ((c1 > c2) ? 1 : -1));
+}
+
+/*
+ * case insensitive comparison between two C strings with limitation of length.
+ */
+int
+_citrus_bcs_strncasecmp(const char * __restrict str1,
+			const char * __restrict str2, size_t sz)
+{
+	int c1 = 1, c2 = 1;
+
+	while (c1 && c2 && c1 == c2 && sz != 0) {
+		c1 = _bcs_toupper(*str1++);
+		c2 = _bcs_toupper(*str2++);
+		sz--;
+	}
+
+	return ((c1 == c2) ? 0 : ((c1 > c2) ? 1 : -1));
+}
+
+/*
+ * skip white space characters.
+ */
+const char *
+_citrus_bcs_skip_ws(const char *p)
+{
+
+	while (*p && _bcs_isspace(*p))
+		p++;
+
+	return (p);
+}
+
+/*
+ * skip non white space characters.
+ */
+const char *
+_citrus_bcs_skip_nonws(const char *p)
+{
+
+	while (*p && !_bcs_isspace(*p))
+		p++;
+
+	return (p);
+}
+
+/*
+ * skip white space characters with limitation of length.
+ */
+const char *
+_citrus_bcs_skip_ws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+	while (*p && *len > 0 && _bcs_isspace(*p)) {
+		p++;
+		(*len)--;
+	}
+
+	return (p);
+}
+
+/*
+ * skip non white space characters with limitation of length.
+ */
+const char *
+_citrus_bcs_skip_nonws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+	while (*p && *len > 0 && !_bcs_isspace(*p)) {
+		p++;
+		(*len)--;
+	}
+
+	return (p);
+}
+
+/*
+ * truncate trailing white space characters.
+ */
+void
+_citrus_bcs_trunc_rws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+	while (*len > 0 && _bcs_isspace(p[*len - 1]))
+		(*len)--;
+}
+
+/*
+ * destructive transliterate to lowercase.
+ */
+void
+_citrus_bcs_convert_to_lower(char *s)
+{
+	while (*s) {
+		*s = _bcs_tolower(*s);
+		s++;
+	}
+}
+
+/*
+ * destructive transliterate to uppercase.
+ */
+void
+_citrus_bcs_convert_to_upper(char *s)
+{
+	while (*s) {
+		*s = _bcs_toupper(*s);
+		s++;
+	}
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_bcs.h src/sys/kiconv/citrus_bcs.h
--- src.orig/sys/kiconv/citrus_bcs.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_bcs.h	2011-06-03 14:37:04.000000000 +0900
@@ -0,0 +1,98 @@
+/*	$NetBSD: citrus_bcs.h,v 1.6 2009/01/11 02:46:24 christos Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_BCS_H_
+#define _CITRUS_BCS_H_
+
+/*
+ * predicate/conversion for basic character set.
+ *
+ * `Basic character set' is a term defined in the ISO C standard.
+ * Citrus bcs is, if anything, close to `portable character set'
+ * defined in the POSIX.
+ */
+
+#define _CITRUS_BCS_PRED(_name_, _cond_) \
+static __inline int _citrus_bcs_##_name_(uint8_t c) { return (_cond_); }
+
+/*
+ * predicates.
+ * Unlike predicates defined in ctype.h, these do not accept EOF.
+ */
+_CITRUS_BCS_PRED(isblank, c == ' ' || c == '\t')
+_CITRUS_BCS_PRED(iseol, c == '\n' || c == '\r')
+_CITRUS_BCS_PRED(isspace,
+		 _citrus_bcs_isblank(c) || _citrus_bcs_iseol(c) ||
+		 c == '\f' || c == '\v')
+_CITRUS_BCS_PRED(isdigit, c >= '0' && c <= '9')
+_CITRUS_BCS_PRED(isupper, c >= 'A' && c <= 'Z')
+_CITRUS_BCS_PRED(islower, c >= 'a' && c <= 'z')
+_CITRUS_BCS_PRED(isalpha, _citrus_bcs_isupper(c) || _citrus_bcs_islower(c))
+_CITRUS_BCS_PRED(isalnum, _citrus_bcs_isdigit(c) || _citrus_bcs_isalpha(c))
+_CITRUS_BCS_PRED(isxdigit,
+		 _citrus_bcs_isdigit(c) ||
+		 (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
+
+/*
+ * transliterate between uppercase and lowercase.
+ * Unlike transliterator defined in ctype.h, these do not accept EOF.
+ */
+static __inline uint8_t
+_citrus_bcs_toupper(uint8_t c)
+{
+	return (_citrus_bcs_islower(c) ? (c - 'a' + 'A') : c);
+}
+
+static __inline uint8_t
+_citrus_bcs_tolower(uint8_t c)
+{
+	return (_citrus_bcs_isupper(c) ? (c - 'A' + 'a') : c);
+}
+
+__BEGIN_DECLS
+int _citrus_bcs_strcasecmp(const char * __restrict, const char * __restrict);
+int _citrus_bcs_strncasecmp(const char * __restrict, const char * __restrict,
+			    size_t);
+const char *_citrus_bcs_skip_ws(const char * __restrict);
+const char *_citrus_bcs_skip_nonws(const char * __restrict);
+const char *_citrus_bcs_skip_ws_len(const char * __restrict,
+				       size_t * __restrict);
+const char *_citrus_bcs_skip_nonws_len(const char * __restrict,
+				       size_t * __restrict);
+void _citrus_bcs_trunc_rws_len(const char * __restrict, size_t * __restrict);
+void _citrus_bcs_convert_to_lower(char *);
+void _citrus_bcs_convert_to_upper(char *);
+
+long int _citrus_bcs_strtol(
+    const char * __restrict, char ** __restrict, int);
+unsigned long int _citrus_bcs_strtoul(
+    const char * __restrict, char ** __restrict, int);
+
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_bcs_strtol.c src/sys/kiconv/citrus_bcs_strtol.c
--- src.orig/sys/kiconv/citrus_bcs_strtol.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_bcs_strtol.c	2011-06-03 14:48:55.000000000 +0900
@@ -0,0 +1,68 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_bcs_strtol.c,v 1.2 2009/01/11 02:46:24 christos Exp */
+
+/*-
+ * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
+ * Copyright (c) 2003, 2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("NetBSD: citrus_bcs_strtol.c,v 1.2 2009/01/11 02:46:24 christos Exp");
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+#define	_FUNCNAME	_bcs_strtol
+#define	__INT		long int
+#define	__INT_MIN	LONG_MIN
+#define	__INT_MAX	LONG_MAX
+
+#undef isspace
+#define isspace(c)	_bcs_isspace(c)
+
+#undef isdigit
+#define isdigit(c)	_bcs_isdigit(c)
+
+#undef isalpha
+#define isalpha(c)	_bcs_isalpha(c)
+
+#undef isupper
+#define isupper(c)	_bcs_isupper(c)
+
+#include "_strtol.h"
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_bcs_strtoul.c src/sys/kiconv/citrus_bcs_strtoul.c
--- src.orig/sys/kiconv/citrus_bcs_strtoul.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_bcs_strtoul.c	2011-06-03 14:48:57.000000000 +0900
@@ -0,0 +1,73 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_bcs_strtoul.c,v 1.3 2009/01/11 02:46:24 christos Exp */
+
+/*-
+ * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
+ * Copyright (c) 2003, 2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("NetBSD: citrus_bcs_strtoul.c,v 1.3 2009/01/11 02:46:24 christos Exp");
+#endif /* not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+#define	_FUNCNAME	_bcs_strtoul
+#define	__UINT		unsigned long int
+#define	__UINT_MAX	ULONG_MAX
+
+#undef isspace
+#define isspace(c)	_bcs_isspace(c)
+
+#undef isdigit
+#define isdigit(c)	_bcs_isdigit(c)
+
+#undef isalpha
+#define isalpha(c)	_bcs_isalpha(c)
+
+#undef isupper
+#define isupper(c)	_bcs_isupper(c)
+
+#include "_strtoul.h"
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_csmapper.c src/sys/kiconv/citrus_csmapper.c
--- src.orig/sys/kiconv/citrus_csmapper.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_csmapper.c	2011-06-02 19:58:41.000000000 +0900
@@ -0,0 +1,441 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_csmapper.c,v 1.10 2009/01/11 02:46:24 christos Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)                                        
+__RCSID("NetBSD: citrus_csmapper.c,v 1.10 2009/01/11 02:46:24 christos Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/rwlock.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include "reentrant.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_module.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_csmapper.h"
+#include "citrus_pivot_file.h"
+#include "citrus_db.h"
+#include "citrus_db_hash.h"
+#include "citrus_lookup.h"
+
+krwlock_t kiconv_csmapper_lock __cacheline_aligned;
+static struct _citrus_mapper_area *maparea = NULL;
+
+#define CS_ALIAS	_PATH_CSMAPPER "/charset.alias"
+#define CS_PIVOT	_PATH_CSMAPPER "/charset.pivot"
+
+
+/* ---------------------------------------------------------------------- */
+
+static int
+get32(struct _region *r, uint32_t *rval)
+{
+	if (_region_size(r) != 4)
+		return EFTYPE;
+
+	memcpy(rval, _region_head(r), (size_t)4);
+	*rval = be32toh(*rval);
+
+	return 0;
+}
+
+static int
+open_subdb(struct _citrus_db **subdb, struct _citrus_db *db, const char *src)
+{
+	int ret;
+	struct _region r;
+
+	ret = _db_lookup_by_s(db, src, &r, NULL);
+	if (ret)
+		return ret;
+	ret = _db_open(subdb, &r, _CITRUS_PIVOT_SUB_MAGIC, _db_hash_std, NULL);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+
+#define NO_SUCH_FILE	EOPNOTSUPP
+static int
+find_best_pivot_pvdb(const char *src, const char *dst, char *pivot,
+		     size_t pvlen, unsigned long *rnorm)
+{
+	int ret, num, i;
+	struct _region fr, r1, r2;
+	struct _citrus_db *db1, *db2, *db3;
+	char *buf;
+	unsigned long norm;
+	uint32_t val32;
+
+	ret = _map_file(&fr, CS_PIVOT ".pvdb");
+	if (ret) {
+		if (ret == ENOENT)
+			ret = NO_SUCH_FILE;
+		return ret;
+	}
+	ret = _db_open(&db1, &fr, _CITRUS_PIVOT_MAGIC, _db_hash_std, NULL);
+	if (ret)
+		goto quit1;
+	ret = open_subdb(&db2, db1, src);
+	if (ret)
+		goto quit2;
+
+	buf = KICONV_LINEBUF_GET();
+	num = _db_get_num_entries(db2);
+	*rnorm = ULONG_MAX;
+	for (i = 0; i < num; i++) {
+		/* iterate each pivot */
+		ret = _db_get_entry(db2, i, &r1, &r2);
+		if (ret)
+			goto quit3;
+		/* r1:pivot name, r2:norm among src and pivot */
+		ret = get32(&r2, &val32);
+		if (ret)
+			goto quit3;
+		norm = val32;
+		snprintf(buf, LINE_MAX, "%.*s",
+			 (int)_region_size(&r1), (char *)_region_head(&r1));
+		/* buf: pivot name */
+		ret = open_subdb(&db3, db1, buf);
+		if (ret)
+			goto quit3;
+		ret = _db_lookup_by_s(db3, dst, &r2, NULL);
+		if (ret)
+			goto quit4;
+		/* r2: norm among pivot and dst */
+		ret = get32(&r2, &val32);
+		if (ret)
+			goto quit4;
+		norm += val32;
+		/* judge minimum norm */
+		if (norm < *rnorm) {
+			*rnorm = norm;
+			strlcpy(pivot, buf, pvlen);
+		}
+quit4:
+		_db_close(db3);
+		if (ret)
+			goto quit3;
+	}
+	KICONV_LINEBUF_PUT(buf);
+quit3:
+	_db_close(db2);
+quit2:
+	_db_close(db1);
+quit1:
+	_unmap_file(&fr);
+	if (ret)
+		return ret;
+
+	if (*rnorm == ULONG_MAX)
+		return ENOENT;
+
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct zone {
+	const char *begin, *end;
+};
+
+struct parse_arg {
+	char *dst;
+	unsigned long norm;
+};
+
+static int
+parse_line(struct parse_arg *pa, struct _region *r)
+{
+	char buf[20];
+	struct zone z1, z2;
+	size_t len;
+
+	len = _region_size(r);
+	z1.begin = _bcs_skip_ws_len(_region_head(r), &len);
+	if (len == 0)
+		return EFTYPE;
+	z1.end = _bcs_skip_nonws_len(z1.begin, &len);
+	if (len == 0)
+		return EFTYPE;
+	z2.begin = _bcs_skip_ws_len(z1.end, &len);
+	if (len == 0)
+		return EFTYPE;
+	z2.end = _bcs_skip_nonws_len(z2.begin, &len);
+
+	/* z1 : dst name, z2 : norm */
+	snprintf(pa->dst, PATH_MAX,
+		 "%.*s", (int)(z1.end-z1.begin), z1.begin);
+	snprintf(buf, sizeof(buf),
+		 "%.*s", (int)(z2.end-z2.begin), z2.begin);
+	pa->norm = _bcs_strtoul(buf, NULL, 0);
+
+	return 0;
+}
+
+static int
+find_dst(struct parse_arg *pasrc, const char *dst)
+{
+	int ret;
+	struct parse_arg padst;
+	struct _lookup *cl;
+	struct _region data;
+
+	ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE);
+	if (ret)
+		return ret;
+
+	padst.dst = PNBUF_GET();
+	KASSERT(padst.dst != NULL);
+	ret = _lookup_seq_lookup(cl, pasrc->dst, &data);
+	while (ret == 0) {
+		ret = parse_line(&padst, &data);
+		if (ret)
+			break;
+		if (strcmp(dst, padst.dst) == 0) {
+			pasrc->norm += padst.norm;
+			break;
+		}
+		ret = _lookup_seq_next(cl, NULL, &data);
+	}
+	PNBUF_PUT(padst.dst);
+
+	_lookup_seq_close(cl);
+
+	return ret;
+}
+
+static int
+find_best_pivot_lookup(const char *src, const char *dst, char *pivot,
+		       size_t pvlen, unsigned long *rnorm)
+{
+	int ret;
+	struct _lookup *cl;
+	struct _region data;
+	struct parse_arg pa;
+	unsigned long norm_min;
+	char *pivot_min;
+
+	ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE);
+	if (ret)
+		return ret;
+
+	norm_min = ULONG_MAX;
+
+	/* find pivot code */
+	pa.dst = PNBUF_GET();
+	KASSERT(pa.dst != NULL);
+	pivot_min = PNBUF_GET();
+	KASSERT(pivot_min != NULL);
+	ret = _lookup_seq_lookup(cl, src, &data);
+	while (ret == 0) {
+		ret = parse_line(&pa, &data);
+		if (ret)
+			break;
+		ret = find_dst(&pa, dst);
+		if (ret)
+			break;
+		if (pa.norm < norm_min) {
+			norm_min = pa.norm;
+			strlcpy(pivot_min, pa.dst, PATH_MAX);
+		}
+		ret = _lookup_seq_next(cl, NULL, &data);
+	}
+	_lookup_seq_close(cl);
+
+	if (ret != ENOENT) {
+		PNBUF_PUT(pivot_min);
+		PNBUF_PUT(pa.dst);
+		return ret;
+	}
+	if (norm_min == ULONG_MAX) {
+		PNBUF_PUT(pivot_min);
+		PNBUF_PUT(pa.dst);
+		return ENOENT;
+	}
+	strlcpy(pivot, pivot_min, pvlen);
+	if (rnorm)
+		*rnorm = norm_min;
+
+	PNBUF_PUT(pivot_min);
+	PNBUF_PUT(pa.dst);
+
+	return 0;
+}
+
+static int
+find_best_pivot(const char *src, const char *dst, char *pivot, size_t pvlen,
+		unsigned long *rnorm)
+{
+	int ret;
+
+	ret = find_best_pivot_pvdb(src, dst, pivot, pvlen, rnorm);
+	if (ret == NO_SUCH_FILE)
+		ret = find_best_pivot_lookup(src, dst, pivot, pvlen, rnorm);
+
+	return ret;
+}
+
+static __inline int
+open_serial_mapper(struct _citrus_mapper_area *__restrict ma,
+		   struct _citrus_mapper * __restrict * __restrict rcm,
+		   const char *src, const char *pivot, const char *dst)
+{
+	char *buf;
+	int ret;
+
+	buf = PNBUF_GET();
+	KASSERT(buf != NULL);
+	snprintf(buf, PATH_MAX, "%s/%s,%s/%s", src, pivot, pivot, dst);
+	ret = _mapper_open_direct(ma, rcm, "mapper_serial", buf);
+	PNBUF_PUT(buf);
+
+	return ret;
+}
+
+static struct _citrus_csmapper *csm_none = NULL;
+static int
+get_none(struct _citrus_mapper_area *__restrict ma,
+	 struct _citrus_csmapper *__restrict *__restrict rcsm)
+{
+	int ret = 0;
+
+	rw_enter(&kiconv_csmapper_lock, RW_READER);
+	if (csm_none == NULL) {
+		while (rw_tryupgrade(&kiconv_csmapper_lock) == 0)
+			kpause("kiccsmap", true, 1, NULL);
+		if (csm_none == NULL) {
+			ret = _mapper_open_direct(ma, &csm_none,
+			    "mapper_none", "");
+			if (ret)
+				goto out;
+			_mapper_set_persistent(csm_none);
+		}
+		rw_downgrade(&kiconv_csmapper_lock);
+	}
+	rw_exit(&kiconv_csmapper_lock);
+
+	*rcsm = csm_none;
+out:
+	return ret;
+}
+
+int
+_citrus_csmapper_open(struct _citrus_csmapper * __restrict * __restrict rcsm,
+		      const char * __restrict src, const char * __restrict dst,
+		      uint32_t flags, unsigned long *rnorm)
+{
+	int ret;
+	char *buf1, *buf2, *key, *pivot;
+	const char *realsrc, *realdst;
+	unsigned long norm;
+
+	norm = 0;	/* XXX gcc */
+
+	ret = _citrus_mapper_create_area(&maparea, _PATH_CSMAPPER);
+	if (ret)
+		return ret;
+
+	buf1 = PNBUF_GET();
+	KASSERT(buf1 != NULL);
+	buf2 = PNBUF_GET();
+	KASSERT(buf2 != NULL);
+
+	realsrc = _lookup_alias(CS_ALIAS, src, buf1, PATH_MAX,
+				_LOOKUP_CASE_IGNORE);
+	realdst = _lookup_alias(CS_ALIAS, dst, buf2, PATH_MAX,
+				_LOOKUP_CASE_IGNORE);
+	if (!strcmp(realsrc, realdst)) {
+		ret = get_none(maparea, rcsm);
+		if (ret == 0 && rnorm != NULL)
+			*rnorm = 0;
+		goto free_buf;
+	}
+
+	key = PNBUF_GET();
+	KASSERT(key != NULL);
+	snprintf(key, PATH_MAX, "%s/%s", realsrc, realdst);
+
+	ret = _mapper_open(maparea, rcsm, key);
+	if (ret == 0) {
+		if (rnorm != NULL)
+			*rnorm = 0;
+		goto free_key;
+	}
+	if (ret != ENOENT || (flags & _CSMAPPER_F_PREVENT_PIVOT)!=0)
+		goto free_key;
+
+	pivot = PNBUF_GET();
+	KASSERT(pivot != NULL);
+	ret = find_best_pivot(realsrc, realdst, pivot, PATH_MAX, &norm);
+	if (ret)
+		goto free_pivot;
+
+	ret = open_serial_mapper(maparea, rcsm, realsrc, pivot, realdst);
+	if (ret == 0 && rnorm != NULL)
+		*rnorm = norm;
+
+free_pivot:
+	PNBUF_PUT(pivot);
+free_key:
+	PNBUF_PUT(key);
+free_buf:
+	PNBUF_PUT(buf2);
+	PNBUF_PUT(buf1);
+
+	return ret;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_csmapper.h src/sys/kiconv/citrus_csmapper.h
--- src.orig/sys/kiconv/citrus_csmapper.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_csmapper.h	2011-06-03 14:37:47.000000000 +0900
@@ -0,0 +1,48 @@
+/*	$NetBSD: citrus_csmapper.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_CSMAPPER_H_
+#define _CITRUS_CSMAPPER_H
+
+#define _citrus_csmapper		_citrus_mapper
+#define _citrus_csmapper_close		_citrus_mapper_close
+#define _citrus_csmapper_convert	_citrus_mapper_convert
+#define _citrus_csmapper_init_state	_citrus_mapper_init_state
+#define _citrus_csmapper_get_state_size	_citrus_mapper_get_state_size
+#define _citrus_csmapper_get_src_max	_citrus_mapper_get_src_max
+#define _citrus_csmapper_get_dst_max	_citrus_mapper_get_dst_max
+
+#define _CITRUS_CSMAPPER_F_PREVENT_PIVOT	0x00000001
+__BEGIN_DECLS
+int	_citrus_csmapper_open(struct _citrus_csmapper *__restrict *__restrict,
+			      const char *__restrict,
+			      const char *__restrict, uint32_t,
+			      unsigned long *);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_ctype.c src/sys/kiconv/citrus_ctype.c
--- src.orig/sys/kiconv/citrus_ctype.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_ctype.c	2011-06-04 22:14:42.000000000 +0900
@@ -0,0 +1,190 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_ctype.c,v 1.5 2008/06/14 16:01:07 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)1999, 2000, 2001, 2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_ctype.c,v 1.5 2008/06/14 16:01:07 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <wchar.h>
+#endif
+
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_ctype_fallback.h"
+#include "citrus_none.h"
+#include _CITRUS_DEFAULT_CTYPE_HEADER
+
+_citrus_ctype_rec_t _citrus_ctype_default = {
+	&_CITRUS_DEFAULT_CTYPE_OPS,	/* cc_ops */
+	NULL,				/* cc_closure */
+	NULL				/* cc_module */
+};
+
+static int _initctypemodule(_citrus_ctype_t, char const *, _citrus_module_t,
+			    void *, size_t, size_t);
+
+static int
+_initctypemodule(_citrus_ctype_t cc, char const *modname,
+		 _citrus_module_t handle, void *variable, size_t lenvar,
+		 size_t szpriv)
+{
+	int ret;
+	_citrus_ctype_getops_t getops;
+
+	_DIAGASSERT(cc != NULL);
+
+	cc->cc_module = handle;
+
+	getops = (_citrus_ctype_getops_t)_citrus_find_getops(cc->cc_module,
+							     modname,
+							     "ctype");
+	if (getops == NULL)
+		return (EINVAL);
+
+	cc->cc_ops = malloc(sizeof(*cc->cc_ops), M_KICONV, M_WAITOK);
+	ret = (*getops)(cc->cc_ops, sizeof(*cc->cc_ops),
+			_CITRUS_CTYPE_ABI_VERSION);
+	if (ret)
+		goto bad;
+
+	/* If return ABI version is not expected, fixup it here*/
+	switch (cc->cc_ops->co_abi_version) {
+	case 0x00000001:
+		cc->cc_ops->co_btowc = &_citrus_ctype_btowc_fallback;
+		cc->cc_ops->co_wctob = &_citrus_ctype_wctob_fallback;
+		/* FALLTHROUGH */
+	case 0x00000002:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+
+	/* validation check */
+	if (cc->cc_ops->co_init == NULL ||
+	    cc->cc_ops->co_uninit == NULL ||
+	    cc->cc_ops->co_get_mb_cur_max == NULL ||
+	    cc->cc_ops->co_mblen == NULL ||
+	    cc->cc_ops->co_mbrlen == NULL ||
+	    cc->cc_ops->co_mbrtowc == NULL ||
+	    cc->cc_ops->co_mbsinit == NULL ||
+	    cc->cc_ops->co_mbsrtowcs == NULL ||
+	    cc->cc_ops->co_mbstowcs == NULL ||
+	    cc->cc_ops->co_mbtowc == NULL ||
+	    cc->cc_ops->co_wcrtomb == NULL ||
+	    cc->cc_ops->co_wcsrtombs == NULL ||
+	    cc->cc_ops->co_wcstombs == NULL ||
+	    cc->cc_ops->co_wctomb == NULL ||
+	    cc->cc_ops->co_btowc == NULL ||
+	    cc->cc_ops->co_wctob == NULL) {
+		ret = EINVAL;
+		goto bad;
+	}
+
+	/* init and get closure */
+	ret = (*cc->cc_ops->co_init)(
+		&cc->cc_closure, variable, lenvar, szpriv);
+	if (ret)
+		goto bad;
+
+	return (0);
+
+bad:
+	if (cc->cc_ops)
+		free(cc->cc_ops, M_KICONV);
+	cc->cc_ops = NULL;
+
+	return (ret);
+}
+
+int
+_citrus_ctype_open(_citrus_ctype_t *rcc,
+		   char const *encname, void *variable, size_t lenvar,
+		   size_t szpriv)
+{
+	int ret;
+	_citrus_module_t handle;
+	_citrus_ctype_t cc;
+
+	_DIAGASSERT(encname != NULL);
+	_DIAGASSERT(!lenvar || variable!=NULL);
+	_DIAGASSERT(rcc != NULL);
+
+	if (!strcmp(encname, _CITRUS_DEFAULT_CTYPE_NAME)) {
+		*rcc = &_citrus_ctype_default;
+		return (0);
+	}
+	ret = _citrus_load_module(&handle, encname);
+	if (ret)
+		return (ret);
+
+	cc = malloc(sizeof(*cc), M_KICONV, M_WAITOK|M_ZERO);
+	ret = _initctypemodule(cc, encname, handle, variable, lenvar, szpriv);
+	if (ret) {
+		free(cc, M_KICONV);
+		_citrus_unload_module(cc->cc_module);
+		return (ret);
+	}
+
+	*rcc = cc;
+
+	return (0);
+}
+
+void
+_citrus_ctype_close(_citrus_ctype_t cc)
+{
+
+	_DIAGASSERT(cc != NULL);
+
+	if (cc == &_citrus_ctype_default)
+		return;
+	(*cc->cc_ops->co_uninit)(cc->cc_closure);
+	if (cc->cc_ops)
+		free(cc->cc_ops, M_KICONV);
+	_citrus_unload_module(cc->cc_module);
+	free(cc, M_KICONV);
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_ctype.h src/sys/kiconv/citrus_ctype.h
--- src.orig/sys/kiconv/citrus_ctype.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_ctype.h	2011-06-03 14:23:28.000000000 +0900
@@ -0,0 +1,170 @@
+/*	$NetBSD: citrus_ctype.h,v 1.2 2003/03/05 20:18:15 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_CTYPE_H_
+#define _CITRUS_CTYPE_H_
+
+#include "citrus_ctype_local.h"
+
+typedef struct _citrus_ctype_rec *_citrus_ctype_t;
+
+__BEGIN_DECLS
+int _citrus_ctype_open(_citrus_ctype_t * __restrict,
+		       char const * __restrict, void * __restrict,
+		       size_t, size_t);
+void _citrus_ctype_close(_citrus_ctype_t);
+__END_DECLS
+
+static __inline unsigned
+_citrus_ctype_get_mb_cur_max(_citrus_ctype_t cc)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops);
+	return (*cc->cc_ops->co_get_mb_cur_max)(cc->cc_closure);
+}
+
+static __inline int
+_citrus_ctype_mblen(_citrus_ctype_t cc, const char *s, size_t n, int *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_mblen && nresult);
+	return (*cc->cc_ops->co_mblen)(cc->cc_closure, s, n, nresult);
+}
+
+static __inline int
+_citrus_ctype_mbrlen(_citrus_ctype_t cc, const char *s, size_t n,
+		     void *pspriv, size_t *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_mbrlen && nresult);
+	return (*cc->cc_ops->co_mbrlen)(cc->cc_closure, s, n, pspriv, nresult);
+}
+
+static __inline int
+_citrus_ctype_mbrtowc(_citrus_ctype_t cc, wchar_t *pwc, const char *s,
+		      size_t n, void *pspriv, size_t *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_mbrtowc);
+	return (*cc->cc_ops->co_mbrtowc)(cc->cc_closure, pwc, s, n, pspriv,
+					 nresult);
+}
+
+static __inline int
+_citrus_ctype_mbsinit(_citrus_ctype_t cc, void const *pspriv, int *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_mbsinit && nresult);
+	return (*cc->cc_ops->co_mbsinit)(cc->cc_closure, pspriv, nresult);
+}
+
+static __inline int
+_citrus_ctype_mbsrtowcs(_citrus_ctype_t cc, wchar_t *pwcs, const char **s,
+			size_t n, void *pspriv, size_t *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_mbsrtowcs && nresult);
+	return (*cc->cc_ops->co_mbsrtowcs)(cc->cc_closure, pwcs, s, n, pspriv,
+					   nresult);
+}
+
+static __inline int
+_citrus_ctype_mbstowcs(_citrus_ctype_t cc, wchar_t *pwcs, const char *s,
+		       size_t n, size_t *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_mbstowcs && nresult);
+	return (*cc->cc_ops->co_mbstowcs)(cc->cc_closure, pwcs, s, n, nresult);
+}
+
+static __inline int
+_citrus_ctype_mbtowc(_citrus_ctype_t cc, wchar_t *pw, const char *s, size_t n,
+		     int *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_mbtowc && nresult);
+	return (*cc->cc_ops->co_mbtowc)(cc->cc_closure, pw, s, n, nresult);
+}
+
+static __inline int
+_citrus_ctype_wcrtomb(_citrus_ctype_t cc, char *s, wchar_t wc,
+		      void *pspriv, size_t *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_wcrtomb && nresult);
+	return (*cc->cc_ops->co_wcrtomb)(cc->cc_closure, s, wc, pspriv,
+					 nresult);
+}
+
+static __inline int
+_citrus_ctype_wcsrtombs(_citrus_ctype_t cc, char *s, const wchar_t **ppwcs,
+			size_t n, void *pspriv, size_t *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_wcsrtombs && nresult);
+	return (*cc->cc_ops->co_wcsrtombs)(cc->cc_closure, s, ppwcs, n,
+					   pspriv, nresult);
+}
+
+static __inline int
+_citrus_ctype_wcstombs(_citrus_ctype_t cc, char *s, const wchar_t *wcs,
+		       size_t n, size_t *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_wcstombs && nresult);
+	return (*cc->cc_ops->co_wcstombs)(cc->cc_closure, s, wcs, n, nresult);
+}
+
+static __inline int
+_citrus_ctype_wctomb(_citrus_ctype_t cc, char *s, wchar_t wc, int *nresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_wctomb && nresult);
+	return (*cc->cc_ops->co_wctomb)(cc->cc_closure, s, wc, nresult);
+}
+
+static __inline int
+_citrus_ctype_btowc(_citrus_ctype_t cc, int c, wint_t *wcresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_btowc && wcresult);
+	return (*cc->cc_ops->co_btowc)(cc, c, wcresult);
+}
+
+static __inline int
+_citrus_ctype_wctob(_citrus_ctype_t cc, wint_t c, int *cresult)
+{
+
+	_DIAGASSERT(cc && cc->cc_ops && cc->cc_ops->co_wctob && cresult);
+	return (*cc->cc_ops->co_wctob)(cc, c, cresult);
+}
+
+extern _citrus_ctype_rec_t _citrus_ctype_default;
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_ctype_fallback.c src/sys/kiconv/citrus_ctype_fallback.c
--- src.orig/sys/kiconv/citrus_ctype_fallback.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_ctype_fallback.c	2011-06-03 15:03:35.000000000 +0900
@@ -0,0 +1,119 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_ctype_fallback.c,v 1.2 2003/06/27 14:52:25 yamt Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_ctype_fallback.c,v 1.2 2003/06/27 14:52:25 yamt Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <assert.h>
+#include <wchar.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#endif
+
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_ctype_fallback.h"
+
+/*
+ * for ABI version >= 0x00000002
+ */ 
+
+int
+_citrus_ctype_btowc_fallback(_citrus_ctype_rec_t * __restrict cc,
+			     int c, wint_t * __restrict wcresult)
+{
+	char mb;
+	/*
+	 * what we need is _PRIVSIZE
+	 * and we know that it's smaller than sizeof(mbstate_t).
+	 */
+	char pspriv[sizeof(mbstate_t)];
+	wchar_t wc;
+	size_t nr;
+	int err;
+
+	_DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
+
+	if (c == EOF) {
+		*wcresult = WEOF;
+		return 0;
+	}
+
+	memset(&pspriv, 0, sizeof(pspriv));
+	mb = (char)(unsigned)c;
+	err = _citrus_ctype_mbrtowc(cc, &wc, &mb, 1, (void *)&pspriv, &nr);
+	if (!err && (nr == 0 || nr == 1))
+		*wcresult = wc;
+	else
+		*wcresult = WEOF;
+
+	return 0;
+}
+
+int
+_citrus_ctype_wctob_fallback(_citrus_ctype_rec_t * __restrict cc,
+			     wint_t wc, int * __restrict cresult)
+{
+	/*
+	 * what we need is _PRIVSIZE
+	 * and we know that it's smaller than sizeof(mbstate_t).
+	 */
+	char pspriv[sizeof(mbstate_t)];
+	char buf[MB_LEN_MAX];
+	size_t nr;
+	int err;
+
+	_DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
+
+	if (wc == WEOF) {
+		*cresult = EOF;
+		return 0;
+	}
+	memset(&pspriv, 0, sizeof(pspriv));
+	err = _citrus_ctype_wcrtomb(cc, buf, (wchar_t)wc, (void *)&pspriv, &nr);
+	if (!err && nr == 1)
+		*cresult = buf[0];
+	else
+		*cresult = EOF;
+
+	return 0;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_ctype_fallback.h src/sys/kiconv/citrus_ctype_fallback.h
--- src.orig/sys/kiconv/citrus_ctype_fallback.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_ctype_fallback.h	2011-06-03 15:02:11.000000000 +0900
@@ -0,0 +1,38 @@
+/*	$NetBSD: citrus_ctype_fallback.h,v 1.1 2003/03/05 20:18:15 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_CTYPE_FALLBACK_H_
+#define _CITRUS_CTYPE_FALLBACK_H_
+
+/* fallback functions for 0x00000002 */
+int _citrus_ctype_btowc_fallback(_citrus_ctype_rec_t * __restrict,
+				 int, wint_t * __restrict);
+int _citrus_ctype_wctob_fallback(_citrus_ctype_rec_t * __restrict,
+				 wint_t, int * __restrict);
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_ctype_local.h src/sys/kiconv/citrus_ctype_local.h
--- src.orig/sys/kiconv/citrus_ctype_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_ctype_local.h	2011-06-03 14:23:48.000000000 +0900
@@ -0,0 +1,198 @@
+/*	$NetBSD: citrus_ctype_local.h,v 1.3 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_CTYPE_LOCAL_H_
+#define _CITRUS_CTYPE_LOCAL_H_
+
+#define _CITRUS_CTYPE_GETOPS_FUNC_BASE(_n_)				\
+int _n_(_citrus_ctype_ops_rec_t *, size_t, uint32_t)
+#define _CITRUS_CTYPE_GETOPS_FUNC(_n_)					\
+_CITRUS_CTYPE_GETOPS_FUNC_BASE(_citrus_##_n_##_ctype_getops)
+
+#define _CITRUS_CTYPE_DECLS(_e_)					      \
+static int	_citrus_##_e_##_ctype_init				      \
+	(void ** __restrict, void * __restrict, size_t, size_t);	      \
+static void	_citrus_##_e_##_ctype_uninit(void *);			      \
+static unsigned	_citrus_##_e_##_ctype_get_mb_cur_max(void *);		      \
+static int	_citrus_##_e_##_ctype_mblen(void * __restrict,		      \
+				     const char * __restrict,		      \
+				     size_t, int * __restrict);		      \
+static int	_citrus_##_e_##_ctype_mbrlen(void * __restrict,		      \
+				      const char * __restrict,		      \
+				      size_t, void * __restrict,	      \
+				      size_t * __restrict);		      \
+static int	_citrus_##_e_##_ctype_mbrtowc(void * __restrict,	      \
+				       wchar_t * __restrict,		      \
+				       const char * __restrict, size_t,	      \
+				       void * __restrict,		      \
+				       size_t * __restrict);		      \
+static int	_citrus_##_e_##_ctype_mbsinit(void * __restrict,	      \
+				       void const * __restrict,		      \
+				       int * __restrict);		      \
+static int	_citrus_##_e_##_ctype_mbsrtowcs(void * __restrict,	      \
+					 wchar_t * __restrict,		      \
+					 const char ** __restrict,	      \
+					 size_t, void * __restrict,	      \
+					 size_t * __restrict);		      \
+static int	_citrus_##_e_##_ctype_mbstowcs(void * __restrict,	      \
+					wchar_t * __restrict,		      \
+					const char * __restrict,	      \
+					size_t, size_t * __restrict);	      \
+static int	_citrus_##_e_##_ctype_mbtowc(void * __restrict,		      \
+				      wchar_t * __restrict,		      \
+				      const char * __restrict,		      \
+				      size_t, int * __restrict);	      \
+static int	_citrus_##_e_##_ctype_wcrtomb(void * __restrict,	      \
+				       char * __restrict, wchar_t,	      \
+				       void * __restrict,		      \
+				       size_t * __restrict);		      \
+static int	_citrus_##_e_##_ctype_wcsrtombs(void * __restrict,	      \
+					 char * __restrict,		      \
+					 const wchar_t ** __restrict,	      \
+					 size_t, void * __restrict,	      \
+					 size_t * __restrict);		      \
+static int	_citrus_##_e_##_ctype_wcstombs(void * __restrict,	      \
+					char * __restrict,		      \
+					const wchar_t * __restrict,	      \
+					size_t, size_t * __restrict);	      \
+static int	_citrus_##_e_##_ctype_wctomb(void * __restrict,		      \
+				      char * __restrict,		      \
+				      wchar_t, int * __restrict);	      \
+static int	_citrus_##_e_##_ctype_btowc(_citrus_ctype_rec_t * __restrict, \
+				      int, wint_t * __restrict);	      \
+static int	_citrus_##_e_##_ctype_wctob(_citrus_ctype_rec_t * __restrict, \
+				      wint_t, int * __restrict)
+
+#define _CITRUS_CTYPE_DEF_OPS(_e_)					\
+_citrus_ctype_ops_rec_t _citrus_##_e_##_ctype_ops = {			\
+	/* co_abi_version */	_CITRUS_CTYPE_ABI_VERSION,		\
+	/* co_init */		&_citrus_##_e_##_ctype_init,		\
+	/* co_uninit */		&_citrus_##_e_##_ctype_uninit,		\
+	/* co_get_mb_cur_max */	&_citrus_##_e_##_ctype_get_mb_cur_max,	\
+	/* co_mblen */		&_citrus_##_e_##_ctype_mblen,		\
+	/* co_mbrlen */		&_citrus_##_e_##_ctype_mbrlen,		\
+	/* co_mbrtowc */	&_citrus_##_e_##_ctype_mbrtowc,		\
+	/* co_mbsinit */	&_citrus_##_e_##_ctype_mbsinit,		\
+	/* co_mbsrtowcs */	&_citrus_##_e_##_ctype_mbsrtowcs,	\
+	/* co_mbstowcs */	&_citrus_##_e_##_ctype_mbstowcs,	\
+	/* co_mbtowc */		&_citrus_##_e_##_ctype_mbtowc,		\
+	/* co_wcrtomb */	&_citrus_##_e_##_ctype_wcrtomb,		\
+	/* co_wcsrtombs */	&_citrus_##_e_##_ctype_wcsrtombs,	\
+	/* co_wcstombs */	&_citrus_##_e_##_ctype_wcstombs,	\
+	/* co_wctomb */		&_citrus_##_e_##_ctype_wctomb,		\
+	/* co_btowc */		&_citrus_##_e_##_ctype_btowc,		\
+	/* co_wctob */		&_citrus_##_e_##_ctype_wctob		\
+}
+
+typedef struct _citrus_ctype_ops_rec	_citrus_ctype_ops_rec_t;
+typedef struct _citrus_ctype_rec	_citrus_ctype_rec_t;
+
+typedef int	(*_citrus_ctype_init_t)
+	(void ** __restrict, void * __restrict, size_t, size_t);
+typedef void	(*_citrus_ctype_uninit_t)(void *);
+typedef unsigned (*_citrus_ctype_get_mb_cur_max_t)(void *);
+typedef int	(*_citrus_ctype_mblen_t)
+	(void * __restrict, const char * __restrict, size_t, int * __restrict);
+typedef int	(*_citrus_ctype_mbrlen_t)
+	(void * __restrict, const char * __restrict, size_t,
+	 void * __restrict, size_t * __restrict);
+typedef int	(*_citrus_ctype_mbrtowc_t)
+	(void * __restrict, wchar_t * __restrict, const char * __restrict,
+	 size_t, void * __restrict, size_t * __restrict);
+typedef int	(*_citrus_ctype_mbsinit_t)
+	(void * __restrict, const void * __restrict, int * __restrict);
+typedef int	(*_citrus_ctype_mbsrtowcs_t)
+	(void * __restrict, wchar_t * __restrict, const char ** __restrict,
+	 size_t, void * __restrict,
+	 size_t * __restrict);
+typedef int	(*_citrus_ctype_mbstowcs_t)
+	(void * __restrict, wchar_t * __restrict, const char * __restrict,
+	 size_t, size_t * __restrict);
+typedef int	(*_citrus_ctype_mbtowc_t)
+	(void * __restrict, wchar_t * __restrict, const char * __restrict,
+	 size_t, int * __restrict);
+typedef int	(*_citrus_ctype_wcrtomb_t)
+	(void * __restrict, char * __restrict, wchar_t, void * __restrict,
+	 size_t * __restrict);
+typedef int	(*_citrus_ctype_wcsrtombs_t)
+	(void * __restrict, char * __restrict, const wchar_t ** __restrict,
+	 size_t, void * __restrict, size_t * __restrict);
+typedef int	(*_citrus_ctype_wcstombs_t)
+	(void * __restrict, char * __restrict, const wchar_t * __restrict,
+	 size_t, size_t * __restrict);
+typedef int	(*_citrus_ctype_wctomb_t)
+	(void * __restrict, char * __restrict, wchar_t, int * __restrict);
+typedef int	(*_citrus_ctype_btowc_t)
+	(_citrus_ctype_rec_t * __restrict, int, wint_t * __restrict);
+typedef int	(*_citrus_ctype_wctob_t)
+	(_citrus_ctype_rec_t * __restrict, wint_t, int * __restrict);
+
+/*
+ * ABI Version change log:
+ *   0x00000001
+ *     initial version
+ *   0x00000002
+ *     ops record:	btowc and wctob are added.
+ *     ctype record:	unchanged.
+ */
+#define _CITRUS_CTYPE_ABI_VERSION	0x00000002
+struct _citrus_ctype_ops_rec {
+	uint32_t			co_abi_version;
+	/* version 0x00000001 */
+	_citrus_ctype_init_t		co_init;
+	_citrus_ctype_uninit_t		co_uninit;
+	_citrus_ctype_get_mb_cur_max_t	co_get_mb_cur_max;
+	_citrus_ctype_mblen_t		co_mblen;
+	_citrus_ctype_mbrlen_t		co_mbrlen;
+	_citrus_ctype_mbrtowc_t		co_mbrtowc;
+	_citrus_ctype_mbsinit_t		co_mbsinit;
+	_citrus_ctype_mbsrtowcs_t	co_mbsrtowcs;
+	_citrus_ctype_mbstowcs_t	co_mbstowcs;
+	_citrus_ctype_mbtowc_t		co_mbtowc;
+	_citrus_ctype_wcrtomb_t		co_wcrtomb;
+	_citrus_ctype_wcsrtombs_t	co_wcsrtombs;
+	_citrus_ctype_wcstombs_t	co_wcstombs;
+	_citrus_ctype_wctomb_t		co_wctomb;
+	/* version 0x00000002 */
+	_citrus_ctype_btowc_t		co_btowc;
+	_citrus_ctype_wctob_t		co_wctob;
+};
+
+#define _CITRUS_DEFAULT_CTYPE_NAME	"NONE"
+#define _CITRUS_DEFAULT_CTYPE_OPS	_citrus_NONE_ctype_ops
+#define _CITRUS_DEFAULT_CTYPE_HEADER	"citrus_none.h"
+
+typedef _CITRUS_CTYPE_GETOPS_FUNC_BASE((*_citrus_ctype_getops_t));
+struct _citrus_ctype_rec {
+	_citrus_ctype_ops_rec_t	*cc_ops;
+	void			*cc_closure;
+	_citrus_module_t	cc_module;
+};
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_ctype_template.h src/sys/kiconv/citrus_ctype_template.h
--- src.orig/sys/kiconv/citrus_ctype_template.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_ctype_template.h	2011-06-03 11:21:55.000000000 +0900
@@ -0,0 +1,768 @@
+/*	$NetBSD: citrus_ctype_template.h,v 1.35 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/*
+ * CAUTION: THIS IS NOT STANDALONE FILE
+ *
+ * function templates of ctype encoding handler for each encodings.
+ *
+ * you need to define the macros below:
+ *
+ *   _FUNCNAME(method) :
+ *     It should convine the real function name for the method.
+ *      e.g. _FUNCNAME(mbrtowc) should be expanded to
+ *             _EUC_ctype_mbrtowc
+ *           for EUC locale.
+ *
+ *   _CEI_TO_STATE(cei, method) :
+ *     It should be expanded to the pointer of the method-internal state
+ *     structures.
+ *     e.g. _CEI_TO_STATE(cei, mbrtowc) might be expanded to
+ *             (cei)->states.s_mbrtowc
+ *     This structure may use if the function is called as
+ *           mbrtowc(&wc, s, n, NULL);
+ *     Such individual structures are needed by:
+ *           mblen
+ *           mbrlen
+ *           mbrtowc
+ *           mbtowc
+ *           mbsrtowcs
+ *           wcrtomb
+ *           wcsrtombs
+ *           wctomb
+ *     These need to be keeped in the ctype encoding information structure,
+ *     pointed by "cei".
+ *
+ *   _ENCODING_INFO :
+ *     It should be expanded to the name of the encoding information structure.
+ *     e.g. For EUC encoding, this macro is expanded to _EUCInfo.
+ *     Encoding information structure need to contain the common informations
+ *     for the codeset.
+ *
+ *   _ENCODING_STATE :
+ *     It should be expanded to the name of the encoding state structure.
+ *     e.g. For EUC encoding, this macro is expanded to _EUCState.
+ *     Encoding state structure need to contain the context-dependent states,
+ *     which are "unpacked-form" of mbstate_t type and keeped during sequent
+ *     calls of mb/wc functions,
+ *
+ *   _ENCODING_IS_STATE_DEPENDENT :
+ *     If the encoding is state dependent, this should be expanded to
+ *     non-zero integral value.  Otherwise, 0.
+ *
+ *   _STATE_NEEDS_EXPLICIT_INIT(ps) :
+ *     some encodings, states needs some explicit initialization.
+ *     (ie. initialization with memset isn't enough.)
+ *     If the encoding state pointed by "ps" needs to be initialized
+ *     explicitly, return non-zero. Otherwize, 0.
+ *
+ */
+
+
+/* prototypes */
+
+__BEGIN_DECLS
+static void _FUNCNAME(init_state)(_ENCODING_INFO * __restrict,
+				  _ENCODING_STATE * __restrict);
+static void _FUNCNAME(pack_state)(_ENCODING_INFO * __restrict,
+				  void * __restrict,
+				  const _ENCODING_STATE * __restrict);
+static void _FUNCNAME(unpack_state)(_ENCODING_INFO * __restrict,
+				    _ENCODING_STATE * __restrict,
+				    const void * __restrict);
+#if _ENCODING_IS_STATE_DEPENDENT
+static int _FUNCNAME(put_state_reset)(_ENCODING_INFO * __restrict,
+				      char * __restrict, size_t,
+				      _ENCODING_STATE * __restrict,
+				      size_t * __restrict);
+#endif
+
+/*
+ * standard form of mbrtowc_priv.
+ *
+ * note (differences from real mbrtowc):
+ *   - 3rd parameter is not "const char *s" but "const char **s".
+ *     after the call of the function, *s will point the first byte of
+ *     the next character.
+ *   - additional 4th parameter is the size of src buffer.
+ *   - 5th parameter is unpacked encoding-dependent state structure.
+ *   - additional 6th parameter is the storage to be stored
+ *     the return value in the real mbrtowc context.
+ *   - return value means "errno" in the real mbrtowc context.
+ */
+
+static int _FUNCNAME(mbrtowc_priv)(_ENCODING_INFO * __restrict,
+				   wchar_t * __restrict,
+				   const char ** __restrict,
+				   size_t, _ENCODING_STATE * __restrict,
+				   size_t * __restrict);
+
+/*
+ * standard form of wcrtomb_priv.
+ *
+ * note (differences from real wcrtomb):
+ *   - additional 3th parameter is the size of src buffer.
+ *   - 5th parameter is unpacked encoding-dependent state structure.
+ *   - additional 6th parameter is the storage to be stored
+ *     the return value in the real mbrtowc context.
+ *   - return value means "errno" in the real wcrtomb context.
+ *   - caller should ensure that 2nd parameter isn't NULL.
+ *     (XXX inconsist with mbrtowc_priv)
+ */
+
+static int _FUNCNAME(wcrtomb_priv)(_ENCODING_INFO * __restrict,
+				   char * __restrict, size_t, wchar_t,
+				   _ENCODING_STATE * __restrict,
+				   size_t * __restrict);
+__END_DECLS
+
+
+/*
+ * macros
+ */
+
+#define _TO_CEI(_cl_)	((_CTYPE_INFO*)(_cl_))
+
+
+/*
+ * templates
+ */
+
+/* internal routines */
+
+static __inline int
+_FUNCNAME(mbtowc_priv)(_ENCODING_INFO * __restrict ei,
+		       wchar_t * __restrict pwc,  const char * __restrict s,
+		       size_t n, _ENCODING_STATE * __restrict psenc,
+		       int * __restrict nresult)
+{
+	_ENCODING_STATE state;
+	const char *tmp = s, **sp = &tmp;	/* XXX:gcc */
+	size_t nr;
+	int err = 0;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	if (s == NULL) {
+		_FUNCNAME(init_state)(ei, psenc);
+		*nresult = _ENCODING_IS_STATE_DEPENDENT;
+		return (0);
+	}
+
+	state = *psenc;
+	err = _FUNCNAME(mbrtowc_priv)(ei, pwc, sp, n, psenc, &nr);
+	if (nr == (size_t)-2)
+		err = EILSEQ;
+	if (err) {
+		/* In error case, we should restore the state. */
+		*psenc = state;
+		*nresult = -1;
+		return (err);
+	}
+
+	*nresult = (int)nr;
+
+	return (0);
+}
+
+static int
+_FUNCNAME(mbsrtowcs_priv)(_ENCODING_INFO * __restrict ei,
+			  wchar_t * __restrict pwcs,
+			  const char ** __restrict s,
+			  size_t n, _ENCODING_STATE * __restrict psenc,
+			  size_t * __restrict nresult)
+{
+	int err, cnt;
+	size_t siz;
+	const char *s0;
+	size_t mbcurmax;
+
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(s == NULL);
+	_DIAGASSERT(*s == NULL);
+
+	/* if pwcs is NULL, ignore n */
+	if (pwcs == NULL)
+		n = 1; /* arbitrary >0 value */
+
+	err = cnt = 0;
+	s0 = *s; /* to keep *s unchanged for now, use copy instead. */
+	mbcurmax = _ENCODING_MB_CUR_MAX(ei);
+	while (n > 0) {
+		err = _FUNCNAME(mbrtowc_priv)(ei, pwcs, &s0, mbcurmax,
+					      psenc, &siz);
+		if (siz == (size_t)-2)
+			err = EILSEQ;
+		if (err) {
+			cnt = -1;
+			goto bye;
+		}
+		switch (siz) {
+		case 0:
+			if (pwcs) {
+				_FUNCNAME(init_state)(ei, psenc);
+			}
+			s0 = 0;
+			goto bye;
+		default:
+			if (pwcs) {
+				pwcs++;
+				n--;
+			}
+			cnt++;
+			break;
+		}
+	}
+bye:
+	if (pwcs)
+		*s = s0;
+
+	*nresult = (size_t)cnt;
+
+	return err;
+}
+
+
+static int
+_FUNCNAME(wcsrtombs_priv)(_ENCODING_INFO * __restrict ei, char * __restrict s,
+			  const wchar_t ** __restrict pwcs,
+			  size_t n, _ENCODING_STATE * __restrict psenc,
+			  size_t * __restrict nresult)
+{
+	int cnt = 0, err;
+	char buf[MB_LEN_MAX];
+	size_t siz;
+	const wchar_t* pwcs0;
+#if _ENCODING_IS_STATE_DEPENDENT
+	_ENCODING_STATE state;
+#endif
+
+	pwcs0 = *pwcs;
+
+	if (!s)
+		n = 1;
+
+	while (n > 0) {
+#if _ENCODING_IS_STATE_DEPENDENT
+		state = *psenc;
+#endif
+		err = _FUNCNAME(wcrtomb_priv)(ei, buf, sizeof(buf),
+					      *pwcs0, psenc, &siz);
+		if (siz == (size_t)-1) {
+			*nresult = siz;
+			return (err);
+		}
+
+		if (s) {
+			if (n < siz) {
+#if _ENCODING_IS_STATE_DEPENDENT
+				*psenc = state;
+#endif
+				break;
+			}
+			memcpy(s, buf, siz);
+			s += siz;
+			n -= siz;
+		}
+		cnt += siz;
+		if (!*pwcs0) {
+			if (s) {
+				_FUNCNAME(init_state)(ei, psenc);
+			}
+			pwcs0 = 0;
+			cnt--; /* don't include terminating null */
+			break;
+		}
+		pwcs0++;
+	}
+	if (s)
+		*pwcs = pwcs0;
+
+	*nresult = (size_t)cnt;
+	return (0);
+}
+
+
+/* ----------------------------------------------------------------------
+ * templates for public functions
+ */
+
+#define _RESTART_BEGIN(_func_, _cei_, _pspriv_, _pse_)			\
+do {									\
+	_ENCODING_STATE _state;						\
+	do {								\
+		if (_pspriv_ == NULL) {					\
+			_pse_ = &_CEI_TO_STATE(_cei_, _func_);		\
+			if (_STATE_NEEDS_EXPLICIT_INIT(_pse_))		\
+			    _FUNCNAME(init_state)(_CEI_TO_EI(_cei_),	\
+							(_pse_));	\
+		} else {						\
+			_pse_ = &_state;				\
+			_FUNCNAME(unpack_state)(_CEI_TO_EI(_cei_),	\
+						_pse_, _pspriv_);	\
+		}							\
+	} while (/*CONSTCOND*/0)
+
+#define _RESTART_END(_func_, _cei_, _pspriv_, _pse_)			\
+	if (_pspriv_ != NULL) {						\
+		_FUNCNAME(pack_state)(_CEI_TO_EI(_cei_), _pspriv_,	\
+				      _pse_);				\
+	}								\
+} while (/*CONSTCOND*/0)
+
+int
+_FUNCNAME(ctype_getops)(_citrus_ctype_ops_rec_t *ops, size_t lenops,
+			uint32_t expected_version)
+{
+	if (expected_version<_CITRUS_CTYPE_ABI_VERSION || lenops<sizeof(*ops))
+		return (EINVAL);
+
+	memcpy(ops, &_FUNCNAME(ctype_ops), sizeof(_FUNCNAME(ctype_ops)));
+
+	return (0);
+}
+
+static int
+_FUNCNAME(ctype_init)(void ** __restrict cl,
+		      void * __restrict var, size_t lenvar, size_t lenps)
+{
+	_CTYPE_INFO *cei;
+
+	_DIAGASSERT(cl != NULL);
+
+	/* sanity check to avoid overruns */
+	if (sizeof(_ENCODING_STATE) > lenps)
+		return (EINVAL);
+
+	cei = malloc(sizeof(_CTYPE_INFO), M_KICONV, M_ZERO|M_WAITOK);
+
+	*cl = (void *)cei;
+
+	return _FUNCNAME(encoding_module_init)(_CEI_TO_EI(cei), var, lenvar);
+}
+
+static void
+_FUNCNAME(ctype_uninit)(void *cl)
+{
+	if (cl) {
+		_FUNCNAME(encoding_module_uninit)(_CEI_TO_EI(_TO_CEI(cl)));
+		free(cl, M_KICONV);
+	}
+}
+
+static unsigned
+/*ARGSUSED*/
+_FUNCNAME(ctype_get_mb_cur_max)(void *cl)
+{
+	return _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
+}
+
+static int
+_FUNCNAME(ctype_mblen)(void * __restrict cl,
+		       const char * __restrict s, size_t n,
+		       int * __restrict nresult)
+{
+	_ENCODING_STATE *psenc;
+	_ENCODING_INFO *ei;
+
+	_DIAGASSERT(cl != NULL);
+
+	psenc = &_CEI_TO_STATE(_TO_CEI(cl), mblen);
+	ei = _CEI_TO_EI(_TO_CEI(cl));
+	if (_STATE_NEEDS_EXPLICIT_INIT(psenc))
+		_FUNCNAME(init_state)(ei, psenc);
+	return _FUNCNAME(mbtowc_priv)(ei, NULL, s, n, psenc, nresult);
+}
+
+static int
+_FUNCNAME(ctype_mbrlen)(void * __restrict cl, const char * __restrict s,
+			size_t n, void * __restrict pspriv,
+			size_t * __restrict nresult)
+{
+	_ENCODING_STATE *psenc;
+	_ENCODING_INFO *ei;
+	const char *tmp = s, **sp = &tmp; /* XXX: gcc */
+	int err = 0;
+
+	_DIAGASSERT(cl != NULL);
+
+	ei = _CEI_TO_EI(_TO_CEI(cl));
+	_RESTART_BEGIN(mbrlen, _TO_CEI(cl), pspriv, psenc);
+	if (s == NULL) {
+		_FUNCNAME(init_state)(ei, psenc);
+		*nresult = 0;
+	} else {
+		err = _FUNCNAME(mbrtowc_priv)(ei, NULL, sp, n, (void *)psenc,
+		    nresult);
+	}
+	_RESTART_END(mbrlen, _TO_CEI(cl), pspriv, psenc);
+
+	return (err);
+}
+
+static int
+_FUNCNAME(ctype_mbrtowc)(void * __restrict cl, wchar_t * __restrict pwc,
+			 const char * __restrict s, size_t n,
+			 void * __restrict pspriv, size_t * __restrict nresult)
+{
+	_ENCODING_STATE *psenc;
+	_ENCODING_INFO *ei;
+	const char *tmp = s, **sp = &tmp; /* XXX: gcc */
+	int err = 0;
+
+	_DIAGASSERT(cl != NULL);
+
+	ei = _CEI_TO_EI(_TO_CEI(cl));
+	_RESTART_BEGIN(mbrtowc, _TO_CEI(cl), pspriv, psenc);
+	if (s == NULL) {
+		_FUNCNAME(init_state)(ei, psenc);
+		*nresult = 0;
+	} else {
+		err = _FUNCNAME(mbrtowc_priv)(ei, pwc, sp, n, (void *)psenc,
+		    nresult);
+	}
+	_RESTART_END(mbrtowc, _TO_CEI(cl), pspriv, psenc);
+
+	return (err);
+}
+
+static int
+/*ARGSUSED*/
+_FUNCNAME(ctype_mbsinit)(void * __restrict cl, const void * __restrict pspriv,
+			 int * __restrict nresult)
+{
+	_ENCODING_STATE state;
+
+	if (pspriv == NULL) {
+		*nresult = 1;
+		return (0);
+	}
+
+	_FUNCNAME(unpack_state)(_CEI_TO_EI(_TO_CEI(cl)), &state, pspriv);
+
+	*nresult = (state.chlen == 0); /* XXX: FIXME */
+
+	return (0);
+}
+
+static int
+_FUNCNAME(ctype_mbsrtowcs)(void * __restrict cl, wchar_t * __restrict pwcs,
+			   const char ** __restrict s, size_t n,
+			   void * __restrict pspriv,
+			   size_t * __restrict nresult)
+{
+	_ENCODING_STATE *psenc;
+	_ENCODING_INFO *ei;
+	int err = 0;
+
+	_DIAGASSERT(cl != NULL);
+
+	ei = _CEI_TO_EI(_TO_CEI(cl));
+	_RESTART_BEGIN(mbsrtowcs, _TO_CEI(cl), pspriv, psenc);
+	err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, s, n, psenc, nresult);
+	_RESTART_END(mbsrtowcs, _TO_CEI(cl), pspriv, psenc);
+
+	return (err);
+}
+
+static int
+_FUNCNAME(ctype_mbstowcs)(void * __restrict cl, wchar_t * __restrict pwcs,
+			  const char * __restrict s, size_t n,
+			  size_t * __restrict nresult)
+{
+	int err;
+	_ENCODING_STATE state;
+	_ENCODING_INFO *ei;
+	const char *tmp = s, **sp = &tmp; /* XXX: gcc */
+
+	_DIAGASSERT(cl != NULL);
+
+	ei = _CEI_TO_EI(_TO_CEI(cl));
+	_FUNCNAME(init_state)(ei, &state);
+	err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, sp, n, &state, nresult);
+	if (*nresult == (size_t)-2) {
+		err = EILSEQ;
+		*nresult = (size_t)-1;
+	}
+
+	return (err);
+}
+
+static int
+_FUNCNAME(ctype_mbtowc)(void * __restrict cl, wchar_t * __restrict pwc,
+			const char * __restrict s, size_t n,
+			int * __restrict nresult)
+{
+	_ENCODING_STATE *psenc;
+	_ENCODING_INFO *ei;
+
+	_DIAGASSERT(cl != NULL);
+
+	psenc = &_CEI_TO_STATE(_TO_CEI(cl), mbtowc);
+	ei = _CEI_TO_EI(_TO_CEI(cl));
+	if (_STATE_NEEDS_EXPLICIT_INIT(psenc))
+		_FUNCNAME(init_state)(ei, psenc);
+	return _FUNCNAME(mbtowc_priv)(ei, pwc, s, n, psenc, nresult);
+}
+
+static int
+_FUNCNAME(ctype_wcrtomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
+			 void * __restrict pspriv, size_t * __restrict nresult)
+{
+	_ENCODING_STATE *psenc;
+	char buf[MB_LEN_MAX];
+	int err = 0;
+	size_t sz;
+#if _ENCODING_IS_STATE_DEPENDENT
+	size_t rsz = 0;
+#endif
+
+	_DIAGASSERT(cl != NULL);
+
+	if (s == NULL) {
+		/*
+		 * use internal buffer.
+		 */
+		s = buf;
+		wc = L'\0'; /* SUSv3 */
+	}
+
+	_RESTART_BEGIN(wcrtomb, _TO_CEI(cl), pspriv, psenc);
+	sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
+#if _ENCODING_IS_STATE_DEPENDENT
+	if (wc == L'\0') {
+		/* reset state */
+		err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s,
+						 sz, psenc, &rsz);
+		if (err) {
+			*nresult = -1;
+			goto quit;
+		}
+		s += rsz;
+		sz -= rsz;
+	}
+#endif
+	err = _FUNCNAME(wcrtomb_priv)(_CEI_TO_EI(_TO_CEI(cl)), s, sz,
+				      wc, psenc, nresult);
+#if _ENCODING_IS_STATE_DEPENDENT
+	if (err == 0)
+		*nresult += rsz;
+quit:
+#endif
+	if (err == E2BIG)
+		err = EINVAL;
+	_RESTART_END(wcrtomb, _TO_CEI(cl), pspriv, psenc);
+
+	return err;
+}
+
+static int
+/*ARGSUSED*/
+_FUNCNAME(ctype_wcsrtombs)(void * __restrict cl, char * __restrict s,
+			   const wchar_t ** __restrict pwcs, size_t n,
+			   void * __restrict pspriv,
+			   size_t * __restrict nresult)
+{
+	_ENCODING_STATE *psenc;
+	_ENCODING_INFO *ei;
+	int err = 0;
+
+	_DIAGASSERT(cl != NULL);
+
+	ei = _CEI_TO_EI(_TO_CEI(cl));
+	_RESTART_BEGIN(wcsrtombs, _TO_CEI(cl), pspriv, psenc);
+	err = _FUNCNAME(wcsrtombs_priv)(ei, s, pwcs, n, psenc, nresult);
+	_RESTART_END(wcsrtombs, _TO_CEI(cl), pspriv, psenc);
+
+	return err;
+}
+
+static int
+/*ARGSUSED*/
+_FUNCNAME(ctype_wcstombs)(void * __restrict cl, char * __restrict s,
+			  const wchar_t * __restrict pwcs, size_t n,
+			  size_t * __restrict nresult)
+{
+	_ENCODING_STATE state;
+	_ENCODING_INFO *ei;
+	const wchar_t *tmp = pwcs, **pwcsp = &tmp; /* XXX: gcc */
+	int err;
+
+	_DIAGASSERT(cl != NULL);
+
+	ei = _CEI_TO_EI(_TO_CEI(cl));
+	_FUNCNAME(init_state)(ei, &state);
+	err = _FUNCNAME(wcsrtombs_priv)(ei, s, pwcsp, n, &state, nresult);
+
+	return err;
+}
+
+static int
+_FUNCNAME(ctype_wctomb)(void * __restrict cl, char * __restrict s, wchar_t wc,
+			int * __restrict nresult)
+{
+	_ENCODING_STATE *psenc;
+	_ENCODING_INFO *ei;
+	size_t nr, sz;
+#if _ENCODING_IS_STATE_DEPENDENT
+	size_t rsz = 0;
+#endif
+	int err = 0;
+
+	_DIAGASSERT(cl != NULL);
+
+	ei = _CEI_TO_EI(_TO_CEI(cl));
+	psenc = &_CEI_TO_STATE(_TO_CEI(cl), wctomb);
+	if (_STATE_NEEDS_EXPLICIT_INIT(psenc))
+		_FUNCNAME(init_state)(ei, psenc);
+	if (s == NULL) {
+		_FUNCNAME(init_state)(ei, psenc);
+		*nresult = _ENCODING_IS_STATE_DEPENDENT;
+		return 0;
+	}
+	sz = _ENCODING_MB_CUR_MAX(_CEI_TO_EI(_TO_CEI(cl)));
+#if _ENCODING_IS_STATE_DEPENDENT
+	if (wc == L'\0') {
+		/* reset state */
+		err = _FUNCNAME(put_state_reset)(_CEI_TO_EI(_TO_CEI(cl)), s,
+						 sz, psenc, &rsz);
+		if (err) {
+			*nresult = -1; /* XXX */
+			return 0;
+		}
+		s += rsz;
+		sz -= rsz;
+	}
+#endif
+	err = _FUNCNAME(wcrtomb_priv)(ei, s, sz, wc, psenc, &nr);
+#if _ENCODING_IS_STATE_DEPENDENT
+	if (err == 0)
+		*nresult = (int)(nr + rsz);
+	else
+#endif
+	*nresult = (int)nr;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_FUNCNAME(ctype_btowc)(_citrus_ctype_rec_t * __restrict cc,
+		       int c, wint_t * __restrict wcresult)
+{
+	_ENCODING_STATE state;
+	_ENCODING_INFO *ei;
+	char mb;
+	char const *s;
+	wchar_t wc;
+	size_t nr;
+	int err;
+
+	_DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
+
+	if (c == EOF) {
+		*wcresult = WEOF;
+		return 0;
+	}
+	ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
+	_FUNCNAME(init_state)(ei, &state);
+	mb = (char)(unsigned)c;
+	s = &mb;
+	err = _FUNCNAME(mbrtowc_priv)(ei, &wc, &s, 1, &state, &nr);
+	if (!err && (nr == 0 || nr == 1))
+		*wcresult = (wint_t)wc;
+	else
+		*wcresult = WEOF;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_FUNCNAME(ctype_wctob)(_citrus_ctype_rec_t * __restrict cc,
+		       wint_t wc, int * __restrict cresult)
+{
+	_ENCODING_STATE state;
+	_ENCODING_INFO *ei;
+	char buf[MB_LEN_MAX];
+	size_t nr;
+	int err;
+
+	_DIAGASSERT(cc != NULL && cc->cc_closure != NULL);
+
+	if (wc == WEOF) {
+		*cresult = EOF;
+		return 0;
+	}
+	ei = _CEI_TO_EI(_TO_CEI(cc->cc_closure));
+	_FUNCNAME(init_state)(ei, &state);
+	err = _FUNCNAME(wcrtomb_priv)(ei, buf, _ENCODING_MB_CUR_MAX(ei),
+				      (wchar_t)wc, &state, &nr);
+	if (!err && nr == 1)
+		*cresult = buf[0];
+	else
+		*cresult = EOF;
+
+	return 0;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_db.c src/sys/kiconv/citrus_db.c
--- src.orig/sys/kiconv/citrus_db.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_db.c	2011-06-02 19:59:07.000000000 +0900
@@ -0,0 +1,348 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_db.c,v 1.5 2008/02/09 14:56:20 junyoung Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_db.c,v 1.5 2008/02/09 14:56:20 junyoung Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_db.h"
+#include "citrus_db_file.h"
+
+struct _citrus_db {
+	/* private */
+	struct _region db_region;
+	uint32_t (*db_hashfunc)(void *, struct _citrus_region *);
+	void *db_hashfunc_closure;
+};
+
+int
+_citrus_db_open(struct _citrus_db **rdb, struct _region *r, const char *magic,
+		uint32_t (*hashfunc)(void *, struct _citrus_region *),
+		void *hashfunc_closure)
+{
+	struct _memstream ms;
+	struct _citrus_db *db;
+	struct _citrus_db_header_x *dhx;
+
+	_memstream_bind(&ms, r);
+
+	/* sanity check */
+	dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx));
+	if (dhx == NULL)
+		return EFTYPE;
+	if (strncmp(dhx->dhx_magic, magic, _CITRUS_DB_MAGIC_SIZE) != 0)
+		return EFTYPE;
+	if (_memstream_seek(&ms, be32toh(dhx->dhx_entry_offset), SEEK_SET))
+		return EFTYPE;
+
+	if (be32toh(dhx->dhx_num_entries)*_CITRUS_DB_ENTRY_SIZE >
+	    _memstream_remainder(&ms))
+		return EFTYPE;
+
+	db = malloc(sizeof(*db), M_KICONV, M_WAITOK);
+	db->db_region = *r;
+	db->db_hashfunc = hashfunc;
+	db->db_hashfunc_closure = hashfunc_closure;
+	*rdb = db;
+
+	return 0;
+}
+
+void
+_citrus_db_close(struct _citrus_db *db)
+{
+	free(db, M_KICONV);
+}
+
+int
+_citrus_db_lookup(struct _citrus_db *db, struct _citrus_region *key,
+		  struct _citrus_region *data, struct _citrus_db_locator *dl)
+{
+	uint32_t hashval, num_entries;
+	size_t offset;
+	struct _memstream ms;
+	struct _citrus_db_header_x *dhx;
+	struct _citrus_db_entry_x *dex;
+	struct _citrus_region r;
+
+	_memstream_bind(&ms, &db->db_region);
+
+	dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx));
+	_DIAGASSERT(dhx);
+	num_entries = be32toh(dhx->dhx_num_entries);
+	if (num_entries == 0)
+		return ENOENT;
+
+	if (dl != NULL && dl->dl_offset>0) {
+		hashval = dl->dl_hashval;
+		offset = dl->dl_offset;
+		if (offset >= _region_size(&db->db_region))
+			return ENOENT;
+	} else {
+		hashval =
+		    db->db_hashfunc(db->db_hashfunc_closure, key)%num_entries;
+		offset =
+		    be32toh(dhx->dhx_entry_offset) +
+		    hashval * _CITRUS_DB_ENTRY_SIZE;
+		if (dl)
+			dl->dl_hashval = hashval;
+	}
+	do {
+		/* seek to the next entry */
+		if (_citrus_memory_stream_seek(&ms, offset, SEEK_SET))
+			return EFTYPE;
+		/* get the entry record */
+		dex = _memstream_getregion(&ms, NULL, _CITRUS_DB_ENTRY_SIZE);
+		if (dex == NULL)
+			return EFTYPE;
+
+		/* jump to next entry having the same hash value. */
+		offset = be32toh(dex->dex_next_offset);
+
+		/* save the current position */
+		if (dl) {
+			dl->dl_offset = offset;
+			if (offset==0)
+				dl->dl_offset = _region_size(&db->db_region);
+		}
+
+		/* compare hash value. */
+		if (be32toh(dex->dex_hash_value) != hashval)
+			/* not found */
+			break;
+		/* compare key length */
+		if (be32toh(dex->dex_key_size) == _region_size(key)) {
+			/* seek to the head of the key. */
+			if (_memstream_seek(&ms, be32toh(dex->dex_key_offset),
+					    SEEK_SET))
+				return EFTYPE;
+			/* get the region of the key */
+			if (_memstream_getregion(&ms, &r,
+						 _region_size(key)) == NULL)
+				return EFTYPE;
+			/* compare key byte stream */
+			if (memcmp(_region_head(&r), _region_head(key),
+				   _region_size(key)) == 0) {
+				/* match */
+				if (_memstream_seek(
+					&ms, be32toh(dex->dex_data_offset),
+					SEEK_SET))
+					return EFTYPE;
+				if (_memstream_getregion(
+					&ms, data,
+					be32toh(dex->dex_data_size)) == NULL)
+					return EFTYPE;
+				return 0;
+			}
+		}
+	} while (offset != 0);
+
+	return ENOENT;
+}
+
+int
+_citrus_db_lookup_by_string(struct _citrus_db *db, const char *key,
+			    struct _citrus_region *data,
+			    struct _citrus_db_locator *dl)
+{
+	struct _region r;
+
+	_region_init(&r, __UNCONST(key), strlen(key));
+
+	return _citrus_db_lookup(db, &r, data, dl);
+}
+
+int
+_citrus_db_lookup8_by_string(struct _citrus_db *db, const char *key,
+			     uint8_t *rval, struct _citrus_db_locator *dl)
+{
+	int ret;
+	struct _region r;
+
+	ret = _citrus_db_lookup_by_string(db, key, &r, dl);
+	if (ret)
+		return ret;
+
+	if (_region_size(&r) != 1)
+		return EFTYPE;
+
+	if (rval)
+		memcpy(rval, _region_head(&r), 1);
+
+	return 0;
+}
+
+int
+_citrus_db_lookup16_by_string(struct _citrus_db *db, const char *key,
+			      uint16_t *rval, struct _citrus_db_locator *dl)
+{
+	int ret;
+	struct _region r;
+	uint16_t val;
+
+	ret = _citrus_db_lookup_by_string(db, key, &r, dl);
+	if (ret)
+		return ret;
+
+	if (_region_size(&r) != 2)
+		return EFTYPE;
+
+	if (rval) {
+		memcpy(&val, _region_head(&r), 2);
+		*rval = be16toh(val);
+	}
+
+	return 0;
+}
+
+int
+_citrus_db_lookup32_by_string(struct _citrus_db *db, const char *key,
+			      uint32_t *rval, struct _citrus_db_locator *dl)
+{
+	int ret;
+	struct _region r;
+	uint32_t val;
+
+	ret = _citrus_db_lookup_by_string(db, key, &r, dl);
+	if (ret)
+		return ret;
+
+	if (_region_size(&r) != 4)
+		return EFTYPE;
+
+	if (rval) {
+		memcpy(&val, _region_head(&r), 4);
+		*rval = be32toh(val);
+	}
+
+	return 0;
+}
+
+int
+_citrus_db_lookup_string_by_string(struct _citrus_db *db, const char *key,
+				   const char **rdata,
+				   struct _citrus_db_locator *dl)
+{
+	int ret;
+	struct _region r;
+
+	ret = _citrus_db_lookup_by_string(db, key, &r, dl);
+	if (ret)
+		return ret;
+
+	/* check whether the string is null terminated */
+	if (_region_size(&r) == 0)
+		return EFTYPE;
+	if (*((const char*)_region_head(&r)+_region_size(&r)-1) != '\0')
+		return EFTYPE;
+
+	if (rdata)
+		*rdata = _region_head(&r);
+
+	return 0;
+}
+
+int
+_citrus_db_get_number_of_entries(struct _citrus_db *db)
+{
+	struct _memstream ms;
+	struct _citrus_db_header_x *dhx;
+
+	_memstream_bind(&ms, &db->db_region);
+
+	dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx));
+	_DIAGASSERT(dhx);
+	return (int)be32toh(dhx->dhx_num_entries);
+}
+
+int
+_citrus_db_get_entry(struct _citrus_db *db, int idx,
+		     struct _region *key, struct _region *data)
+{
+	uint32_t num_entries;
+	size_t offset;
+	struct _memstream ms;
+	struct _citrus_db_header_x *dhx;
+	struct _citrus_db_entry_x *dex;
+
+	_memstream_bind(&ms, &db->db_region);
+
+	dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx));
+	_DIAGASSERT(dhx);
+	num_entries = be32toh(dhx->dhx_num_entries);
+	if (idx < 0 || (uint32_t)idx >= num_entries)
+		return EINVAL;
+
+	/* seek to the next entry */
+	offset = be32toh(dhx->dhx_entry_offset) + idx * _CITRUS_DB_ENTRY_SIZE;
+	if (_citrus_memory_stream_seek(&ms, offset, SEEK_SET))
+		return EFTYPE;
+	/* get the entry record */
+	dex = _memstream_getregion(&ms, NULL, _CITRUS_DB_ENTRY_SIZE);
+	if (dex == NULL)
+		return EFTYPE;
+	/* seek to the head of the key. */
+	if (_memstream_seek(&ms, be32toh(dex->dex_key_offset), SEEK_SET))
+		return EFTYPE;
+	/* get the region of the key. */
+	if (_memstream_getregion(&ms, key, be32toh(dex->dex_key_size))==NULL)
+		return EFTYPE;
+	/* seek to the head of the data. */
+	if (_memstream_seek(&ms, be32toh(dex->dex_data_offset), SEEK_SET))
+		return EFTYPE;
+	/* get the region of the data. */
+	if (_memstream_getregion(&ms, data, be32toh(dex->dex_data_size))==NULL)
+		return EFTYPE;
+
+	return 0;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_db.h src/sys/kiconv/citrus_db.h
--- src.orig/sys/kiconv/citrus_db.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_db.h	2011-06-03 14:37:47.000000000 +0900
@@ -0,0 +1,74 @@
+/*	$NetBSD: citrus_db.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_H_
+#define _CITRUS_DB_H_
+
+struct _citrus_db;
+struct _citrus_db_locator {
+	uint32_t	dl_hashval;
+	size_t		dl_offset;
+};
+
+__BEGIN_DECLS
+int	_citrus_db_open(struct _citrus_db **, struct _citrus_region *,
+			const char *,
+			uint32_t (*)(void *, struct _citrus_region *),
+			void *);
+void	_citrus_db_close(struct _citrus_db *);
+int	_citrus_db_lookup(struct _citrus_db *, struct _citrus_region *,
+			  struct _citrus_region *,
+			  struct _citrus_db_locator *);
+int	_citrus_db_lookup_by_string(struct _citrus_db *, const char *,
+				    struct _citrus_region *,
+				    struct _citrus_db_locator *);
+int	_citrus_db_lookup8_by_string(struct _citrus_db *, const char *,
+				     uint8_t *,
+				     struct _citrus_db_locator *);
+int	_citrus_db_lookup16_by_string(struct _citrus_db *, const char *,
+				      uint16_t *,
+				      struct _citrus_db_locator *);
+int	_citrus_db_lookup32_by_string(struct _citrus_db *, const char *,
+				      uint32_t *,
+				      struct _citrus_db_locator *);
+int	_citrus_db_lookup_string_by_string(struct _citrus_db *, const char *,
+					   const char **,
+					   struct _citrus_db_locator *);
+int	_citrus_db_get_number_of_entries(struct _citrus_db *);
+int	_citrus_db_get_entry(struct _citrus_db *, int,
+			     struct _citrus_region *, struct _citrus_region *);
+__END_DECLS
+
+static __inline void
+_citrus_db_locator_init(struct _citrus_db_locator *dl)
+{
+	dl->dl_hashval = 0;
+	dl->dl_offset = 0;
+}
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_db_file.h src/sys/kiconv/citrus_db_file.h
--- src.orig/sys/kiconv/citrus_db_file.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_db_file.h	2011-06-03 14:38:14.000000000 +0900
@@ -0,0 +1,84 @@
+/*	$NetBSD: citrus_db_file.h,v 1.4 2008/02/10 05:58:22 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_FILE_H_
+#define _CITRUS_DB_FILE_H_
+
+/*
+ * db format:
+ *  +---
+ *  | header
+ *  |  - magic
+ *  |  - num entries
+ *  +---
+ *  | entry directory
+ *  |  +------------
+ *  |  | entry0
+ *  |  |  - hash value
+ *  |  |  - next entry
+ *  |  |  - key offset
+ *  |  |  - key len
+ *  |  |  - data offset
+ *  |  |  - data size
+ *  |  |---
+ *  |  | entry1
+ *  |  | ..
+ *  |  | entryN
+ *  |  +---
+ *  +---
+ *  | key table
+ *  |  - key0
+ *  |   ...
+ *  |  - keyN
+ *  +---
+ *  | data table
+ *  |  - data0
+ *  |   ...
+ *  |  - dataN
+ *  +---
+ */
+
+#define _CITRUS_DB_MAGIC_SIZE	8
+#define _CITRUS_DB_HEADER_SIZE	16
+struct _citrus_db_header_x {
+	char		dhx_magic[_CITRUS_DB_MAGIC_SIZE];
+	uint32_t	dhx_num_entries;
+	uint32_t	dhx_entry_offset;
+} __packed;
+
+struct _citrus_db_entry_x {
+	uint32_t	dex_hash_value;
+	uint32_t	dex_next_offset;
+	uint32_t	dex_key_offset;
+	uint32_t	dex_key_size;
+	uint32_t	dex_data_offset;
+	uint32_t	dex_data_size;
+} __packed;
+#define _CITRUS_DB_ENTRY_SIZE	24
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_db_hash.c src/sys/kiconv/citrus_db_hash.c
--- src.orig/sys/kiconv/citrus_db_hash.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_db_hash.c	2011-06-02 19:56:52.000000000 +0900
@@ -0,0 +1,80 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_db_hash.c,v 1.5 2008/02/09 14:56:20 junyoung Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_db_hash.c,v 1.5 2008/02/09 14:56:20 junyoung Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#ifndef HOSTPROG
+#include "namespace.h"
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_db_hash.h"
+
+uint32_t
+/*ARGSUSED*/
+_citrus_db_hash_std(void *closure, struct _region *r)
+{
+	const uint8_t *p = _region_head(r);
+	uint32_t hash = 0, tmp;
+	size_t i;
+
+	for (i = _region_size(r); i > 0; i--) {
+		hash <<= 4;
+		hash += _bcs_tolower(*p);
+		tmp = hash & 0xF0000000;
+		if (tmp != 0) {
+			hash ^= tmp;
+			hash ^= tmp >> 24;
+		}
+		p++;
+	}
+	return hash;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_db_hash.h src/sys/kiconv/citrus_db_hash.h
--- src.orig/sys/kiconv/citrus_db_hash.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_db_hash.h	2011-06-03 14:37:47.000000000 +0900
@@ -0,0 +1,36 @@
+/*	$NetBSD: citrus_db_hash.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_HASH_H_
+#define _CITRUS_DB_HASH_H_
+
+__BEGIN_DECLS
+uint32_t	_citrus_db_hash_std(void *, struct _citrus_region *);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_esdb.c src/sys/kiconv/citrus_esdb.c
--- src.orig/sys/kiconv/citrus_esdb.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_esdb.c	2011-06-08 12:52:00.000000000 +0900
@@ -0,0 +1,360 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_esdb.c,v 1.5 2008/02/09 14:56:20 junyoung Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_esdb.c,v 1.5 2008/02/09 14:56:20 junyoung Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <sys/types.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_lookup.h"
+#include "citrus_db.h"
+#include "citrus_db_hash.h"
+#include "citrus_esdb.h"
+#include "citrus_esdb_file.h"
+
+#define ESDB_DIR	"esdb.dir"
+#define ESDB_ALIAS	"esdb.alias"
+
+/*
+ * _citrus_esdb_alias:
+ *	resolve encoding scheme name aliases.
+ */
+const char *
+_citrus_esdb_alias(const char *esname, char *buf, size_t bufsize)
+{
+	return _lookup_alias(_PATH_ESDB "/" ESDB_ALIAS, esname, buf, bufsize,
+			     _LOOKUP_CASE_IGNORE);
+}
+
+
+/*
+ * conv_esdb:
+ *	external representation -> local structure.
+ */
+static int
+conv_esdb(struct _citrus_esdb *esdb, struct _region *fr)
+{
+	int ret;
+	struct _citrus_db *db;
+	uint32_t ver, num_charsets, csid, i, tmp;
+	char buf[100];
+	const char *str;
+
+	/* open db */
+	ret = _db_open(&db, fr, _CITRUS_ESDB_MAGIC, &_db_hash_std, NULL);
+	if (ret)
+		goto err0;
+
+	/* check version */
+	ret = _db_lookup32_by_s(db, _CITRUS_ESDB_SYM_VERSION, &ver, NULL);
+	if (ret)
+		goto err1;
+	switch (ver) {
+	case 0x00000001:
+		/* current version */
+		/* initial version */
+		break;
+	default:
+		ret = EFTYPE;
+		goto err1;
+	}
+
+	/* get encoding/variable */
+	ret = _db_lookupstr_by_s(db, _CITRUS_ESDB_SYM_ENCODING, &str, NULL);
+	if (ret)
+		goto err1;
+	esdb->db_encname = strdup(str);
+
+	esdb->db_len_variable = 0;
+	esdb->db_variable = NULL;
+	ret = _db_lookupstr_by_s(db, _CITRUS_ESDB_SYM_VARIABLE, &str, NULL);
+	if (ret == 0) {
+		esdb->db_len_variable = strlen(str)+1;
+		esdb->db_variable = strdup(str);
+	} else if (ret != ENOENT)
+		goto err2;
+
+	/* get number of charsets */
+	ret = _db_lookup32_by_s(db, _CITRUS_ESDB_SYM_NUM_CHARSETS,
+				&num_charsets, NULL);
+	if (ret)
+		goto err3;
+	esdb->db_num_charsets = num_charsets;
+
+	/* get invalid character */
+	ret = _db_lookup32_by_s(db, _CITRUS_ESDB_SYM_INVALID, &tmp, NULL);
+	if (ret == 0) {
+		esdb->db_use_invalid = 1;
+		esdb->db_invalid = tmp;
+	} else if (ret == ENOENT)
+		esdb->db_use_invalid = 0;
+	else
+		goto err3;
+
+	/* get charsets */
+	esdb->db_charsets = malloc(num_charsets * sizeof(*esdb->db_charsets),
+	    M_KICONV, M_WAITOK);
+	for (i = 0; i < num_charsets; i++) {
+		snprintf(buf, sizeof(buf),
+		    _CITRUS_ESDB_SYM_CSID_PREFIX "%d", i);
+		ret = _db_lookup32_by_s(db, buf, &csid, NULL);
+		if (ret)
+			goto err4;
+		esdb->db_charsets[i].ec_csid = csid;
+
+		snprintf(buf, sizeof(buf),
+		    _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", i);
+		ret = _db_lookupstr_by_s(db, buf, &str, NULL);
+		if (ret)
+			goto err4;
+		esdb->db_charsets[i].ec_csname = strdup(str);
+	}
+
+	_db_close(db);
+
+	return 0;
+
+err4:
+	for (; i > 0; i--)
+		free(esdb->db_charsets[i - 1].ec_csname, M_KICONV);
+	free(esdb->db_charsets, M_KICONV);
+err3:
+	free(esdb->db_variable, M_KICONV);
+err2:
+	free(esdb->db_encname, M_KICONV);
+err1:
+	_db_close(db);
+	if (ret == ENOENT)
+		ret = EFTYPE;
+err0:
+	return ret;
+}
+
+/*
+ * _citrus_esdb_open:
+ *	open an ESDB file.
+ */
+int
+_citrus_esdb_open(struct _citrus_esdb *esdb, const char *esname)
+{
+	int ret;
+	const char *realname, *encfile;
+	char *buf1, *buf2, *path;
+	struct _region fr;
+
+	_DIAGASSERT(esname != NULL);
+
+	buf1 = PNBUF_GET();
+	KASSERT(buf1 != NULL);
+	buf2 = PNBUF_GET();
+	KASSERT(buf2 != NULL);
+	path = PNBUF_GET();
+	KASSERT(path != NULL);
+
+	snprintf(path, PATH_MAX, "%s/%s", _PATH_ESDB, ESDB_ALIAS);
+	realname = _lookup_alias(path, esname, buf1, PATH_MAX,
+				 _LOOKUP_CASE_IGNORE);
+
+	snprintf(path, PATH_MAX, "%s/%s", _PATH_ESDB, ESDB_DIR);
+	encfile = _lookup_simple(path, realname, buf2, PATH_MAX,
+				 _LOOKUP_CASE_IGNORE);
+	if (encfile == NULL) {
+		ret = ENOENT;
+		goto out;
+	}
+
+	/* open file */
+	snprintf(path, PATH_MAX, "%s/%s", _PATH_ESDB, encfile);
+	ret = _map_file(&fr, path);
+	if (ret)
+		goto out;
+
+	ret = conv_esdb(esdb, &fr);
+
+	_unmap_file(&fr);
+
+out:
+	PNBUF_PUT(path);
+	PNBUF_PUT(buf2);
+	PNBUF_PUT(buf1);
+	return ret;
+}
+
+/*
+ * _citrus_esdb_close:
+ *	free an ESDB.
+ */
+void
+_citrus_esdb_close(struct _citrus_esdb *esdb)
+{
+	int i;
+
+	_DIAGASSERT(esdb != NULL);
+	_DIAGASSERT(esdb->db_num_charsets == 0 || esdb->db_charsets != NULL);
+
+	for (i = 0; i < esdb->db_num_charsets; i++)
+		if (esdb->db_charsets[i].ec_csname)
+			free(esdb->db_charsets[i].ec_csname, M_KICONV);
+	esdb->db_num_charsets = 0;
+	if (esdb->db_charsets) {
+		free(esdb->db_charsets, M_KICONV); esdb->db_charsets = NULL;
+	}
+	if (esdb->db_encname) {
+		free(esdb->db_encname, M_KICONV); esdb->db_encname = NULL;
+	}
+	esdb->db_len_variable = 0;
+	if (esdb->db_variable) {
+		free(esdb->db_variable, M_KICONV); esdb->db_variable = NULL;
+	}
+}
+
+/*
+ * _citrus_esdb_free_list:
+ *	free the list.
+ */
+void
+_citrus_esdb_free_list(char **list, size_t num)
+{
+	size_t i;
+
+	for (i = 0; i < num; i++)
+		free(list[i], M_KICONV);
+	free(list, M_KICONV);
+}
+
+/*
+ * _citrus_esdb_get_list:
+ *	get esdb entries.
+ */
+int
+_citrus_esdb_get_list(char ***rlist, size_t *rnum)
+{
+	int ret;
+	struct _region key;
+	size_t num;
+	struct _citrus_lookup *cla, *cld;
+	char **list, **q;
+	char *buf;
+
+	num = 0;
+
+	ret = _lookup_seq_open(&cla, _PATH_ESDB "/" ESDB_ALIAS,
+			       _LOOKUP_CASE_IGNORE);
+	if (ret)
+		goto quit0;
+
+	ret = _lookup_seq_open(&cld, _PATH_ESDB "/" ESDB_DIR,
+			       _LOOKUP_CASE_IGNORE);
+	if (ret)
+		goto quit1;
+
+	/* count number of entries */
+	num = _lookup_get_num_entries(cla) + _lookup_get_num_entries(cld);
+
+	_lookup_seq_rewind(cla);
+	_lookup_seq_rewind(cld);
+
+	/* allocate list pointer space */
+	list = malloc(num * sizeof(char *), M_KICONV, M_WAITOK);
+	num = 0;
+
+	/* get alias entries */
+	buf = PNBUF_GET();
+	KASSERT(buf != NULL);
+	while ((ret = _lookup_seq_next(cla, &key, NULL)) == 0) {
+		snprintf(buf, PATH_MAX, "%.*s",
+			 (int)_region_size(&key),
+			 (const char *)_region_head(&key));
+		_bcs_convert_to_lower(buf);
+		list[num] = strdup(buf);
+		num++;
+	}
+	if (ret != ENOENT)
+		goto quit3;
+	/* get dir entries */
+	while ((ret = _lookup_seq_next(cld, &key, NULL)) == 0) {
+		/* check duplicated entry */
+		snprintf(buf, PATH_MAX, "%.*s",
+			 (int)_region_size(&key),
+			 (const char *)_region_head(&key));
+		_bcs_convert_to_lower(buf);
+		ret = _lookup_seq_lookup(cla, buf, NULL);
+		if (ret) {
+			if (ret != ENOENT)
+				goto quit3;
+			/* not duplicated */
+			list[num] = strdup(buf);
+			num++;
+		}
+	}
+	if (ret != ENOENT)
+		goto quit3;
+
+	ret = 0;
+
+	q = realloc(list, num * sizeof(char *), M_KICONV, M_WAITOK);
+	list = q;
+	*rlist = list;
+	*rnum = num;
+quit3:
+	PNBUF_PUT(buf);
+	if (ret)
+		_citrus_esdb_free_list(list, num);
+	_lookup_seq_close(cld);
+quit1:
+	_lookup_seq_close(cla);
+quit0:
+	return ret;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_esdb.h src/sys/kiconv/citrus_esdb.h
--- src.orig/sys/kiconv/citrus_esdb.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_esdb.h	2011-06-03 14:22:56.000000000 +0900
@@ -0,0 +1,55 @@
+/*	$NetBSD: citrus_esdb.h,v 1.1 2003/06/25 09:51:32 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ESDB_H_
+#define _CITRUS_ESDB_H_
+
+struct _citrus_esdb_charset {
+	_citrus_csid_t			ec_csid;
+	char				*ec_csname;
+};
+
+struct _citrus_esdb {
+	char				*db_encname;
+	void				*db_variable;
+	size_t				db_len_variable;
+	int				db_num_charsets;
+	struct	_citrus_esdb_charset	*db_charsets;
+	int				db_use_invalid;
+	_citrus_wc_t			db_invalid;
+};
+
+__BEGIN_DECLS
+const char	*_citrus_esdb_alias(const char *, char *, size_t);
+int		_citrus_esdb_open(struct _citrus_esdb *, const char *);
+void		_citrus_esdb_close(struct _citrus_esdb *);
+void		_citrus_esdb_free_list(char **, size_t);
+int		_citrus_esdb_get_list(char ***, size_t *);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_esdb_file.h src/sys/kiconv/citrus_esdb_file.h
--- src.orig/sys/kiconv/citrus_esdb_file.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_esdb_file.h	2011-06-03 14:38:22.000000000 +0900
@@ -0,0 +1,44 @@
+/*	$NetBSD: citrus_esdb_file.h,v 1.1 2003/06/25 09:51:32 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ESDB_FILE_H_
+#define _CITRUS_ESDB_FILE_H_
+
+#define _CITRUS_ESDB_MAGIC	"ESDB\0\0\0\0"
+
+#define _CITRUS_ESDB_SYM_VERSION	"version"
+#define _CITRUS_ESDB_SYM_ENCODING	"encoding"
+#define _CITRUS_ESDB_SYM_VARIABLE	"variable"
+#define _CITRUS_ESDB_SYM_NUM_CHARSETS	"num_charsets"
+#define _CITRUS_ESDB_SYM_INVALID	"invalid"
+#define _CITRUS_ESDB_SYM_CSNAME_PREFIX	"csname_"
+#define _CITRUS_ESDB_SYM_CSID_PREFIX	"csid_"
+
+#define _CITRUS_ESDB_VERSION 0x00000001
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_hash.c src/sys/kiconv/citrus_hash.c
--- src.orig/sys/kiconv/citrus_hash.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_hash.c	2011-06-02 19:57:06.000000000 +0900
@@ -0,0 +1,63 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_hash.c,v 1.3 2008/02/09 14:56:20 junyoung Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_hash.c,v 1.3 2008/02/09 14:56:20 junyoung Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_region.h"
+#include "citrus_hash.h"
+#include "citrus_db_hash.h"
+
+int
+_citrus_string_hash_func(const char *key, int hashsize)
+{
+	struct _region r;
+
+	_region_init(&r, __UNCONST(key), strlen(key));
+
+	return (int)(_db_hash_std(NULL, &r) % (uint32_t)hashsize);
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_hash.h src/sys/kiconv/citrus_hash.h
--- src.orig/sys/kiconv/citrus_hash.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_hash.h	2011-06-03 14:22:56.000000000 +0900
@@ -0,0 +1,58 @@
+/*	$NetBSD: citrus_hash.h,v 1.3 2004/01/02 21:49:35 itojun Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_HASH_H_
+#define _CITRUS_HASH_H_
+
+#define _CITRUS_HASH_ENTRY(type) LIST_ENTRY(type)
+#define _CITRUS_HASH_HEAD(headname, type, hashsize)	\
+struct headname {					\
+	LIST_HEAD(, type)	chh_table[hashsize];	\
+}
+#define _CITRUS_HASH_INIT(head, hashsize)			\
+do {								\
+	int _ch_loop;						\
+	for (_ch_loop = 0; _ch_loop < hashsize; _ch_loop++)	\
+		LIST_INIT(&(head)->chh_table[_ch_loop]);	\
+} while (/*CONSTCOND*/0)
+#define _CITRUS_HASH_REMOVE(elm, field) LIST_REMOVE(elm, field)
+#define _CITRUS_HASH_INSERT(head, elm, field, hashval)		\
+LIST_INSERT_HEAD(&(head)->chh_table[hashval], elm, field)
+#define _CITRUS_HASH_SEARCH(head, elm, field, matchfunc, key, hashval)	\
+do {									\
+	LIST_FOREACH((elm), &(head)->chh_table[hashval], field) {	\
+		if (matchfunc((elm), key)==0)				\
+			break;						\
+	}								\
+} while (/*CONSTCOND*/0)
+
+__BEGIN_DECLS
+int	_citrus_string_hash_func(const char *, int);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_iconv.c src/sys/kiconv/citrus_iconv.c
--- src.orig/sys/kiconv/citrus_iconv.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_iconv.c	2011-06-02 19:59:52.000000000 +0900
@@ -0,0 +1,428 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_iconv.c,v 1.9 2011/03/30 08:22:01 jruoho Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_iconv.c,v 1.9 2011/03/30 08:22:01 jruoho Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/rwlock.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include "reentrant.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_module.h"
+#include "citrus_lookup.h"
+#include "citrus_hash.h"
+#include "citrus_iconv.h"
+
+#define _CITRUS_ICONV_DIR	"iconv.dir"
+#define _CITRUS_ICONV_ALIAS	"iconv.alias"
+
+#define CI_HASH_SIZE 101
+#define CI_INITIAL_MAX_REUSE	5
+
+krwlock_t kiconv_iconv_lock __cacheline_aligned;
+
+static bool isinit = false;
+static _CITRUS_HASH_HEAD(, _citrus_iconv_shared, CI_HASH_SIZE) shared_pool;
+static TAILQ_HEAD(, _citrus_iconv_shared) shared_unused;
+static int shared_num_unused, shared_max_reuse;
+
+static __inline void
+init_cache(void)
+{
+
+	rw_enter(&kiconv_iconv_lock, RW_READER);
+	if (!isinit) {
+		while (rw_tryupgrade(&kiconv_iconv_lock) == 0)
+			kpause("kicic", true, 1, NULL);
+		if (!isinit) {
+			_CITRUS_HASH_INIT(&shared_pool, CI_HASH_SIZE);
+			TAILQ_INIT(&shared_unused);
+			shared_max_reuse = CI_INITIAL_MAX_REUSE;
+			isinit = true;
+		}
+		rw_downgrade(&kiconv_iconv_lock);
+	}
+	rw_exit(&kiconv_iconv_lock);
+}
+
+/*
+ * lookup_iconv_entry:
+ *	lookup iconv.dir entry in the specified directory.
+ *
+ * line format of iconv.dir file:
+ *	key  module  arg
+ * key    : lookup key.
+ * module : iconv module name.
+ * arg    : argument for the module (generally, description file name)
+ *
+ */
+static __inline int
+lookup_iconv_entry(const char *curdir, const char *key,
+		   char *linebuf, size_t linebufsize,
+		   const char **module, const char **variable)
+{
+	const char *cp, *cq;
+	char *p, *path;
+
+	path = PNBUF_GET();
+	KASSERT(path != NULL);
+
+	/* iconv.dir path */
+	snprintf(path, PATH_MAX, ("%s/" _CITRUS_ICONV_DIR), curdir);
+
+	/* lookup db */
+	cp = p = _lookup_simple(path, key, linebuf, linebufsize,
+				_LOOKUP_CASE_IGNORE);
+	PNBUF_PUT(path);
+	if (p == NULL)
+		return ENOENT;
+
+	/* get module name */
+	*module = p;
+	cq = _bcs_skip_nonws(cp);
+	p[cq-cp] = '\0';
+	p += cq-cp+1;
+	cq++;
+
+	/* get variable */
+	cp = _bcs_skip_ws(cq);
+	*variable = p += cp - cq;
+	cq = _bcs_skip_nonws(cp);
+	p[cq-cp] = '\0';
+
+	return 0;
+}
+
+static __inline void
+close_shared(struct _citrus_iconv_shared *ci)
+{
+
+	if (ci) {
+		if (ci->ci_module) {
+			if (ci->ci_ops) {
+				if (ci->ci_closure)
+					(*ci->ci_ops->io_uninit_shared)(ci);
+				free(ci->ci_ops, M_KICONV);
+			}
+			_citrus_unload_module(ci->ci_module);
+		}
+		free(ci, M_KICONV);
+	}
+}
+
+static __inline int
+open_shared(struct _citrus_iconv_shared * __restrict * __restrict rci,
+	    const char * __restrict basedir, const char * __restrict convname,
+	    const char * __restrict src, const char * __restrict dst)
+{
+	int ret;
+	struct _citrus_iconv_shared *ci;
+	_citrus_iconv_getops_t getops;
+	char *linebuf;
+	const char *module, *variable;
+	size_t len_convname;
+
+	linebuf = KICONV_LINEBUF_GET();
+	KASSERT(linebuf != NULL);
+
+	/* search converter entry */
+	ret = lookup_iconv_entry(basedir, convname, linebuf, LINE_MAX,
+				 &module, &variable);
+	if (ret) {
+		if (ret == ENOENT) {
+			/* fallback */
+			ret = lookup_iconv_entry(basedir, "*",
+						 linebuf, LINE_MAX,
+						 &module, &variable);
+		}
+		if (ret) {
+			KICONV_LINEBUF_PUT(linebuf);
+			return ret;
+		}
+	}
+
+	/* initialize iconv handle */
+	len_convname = strlen(convname);
+	ci = malloc(sizeof(*ci)+len_convname+1, M_KICONV, M_WAITOK);
+	ci->ci_module = NULL;
+	ci->ci_ops = NULL;
+	ci->ci_closure = NULL;
+	ci->ci_convname = (void *)&ci[1];
+	memcpy(ci->ci_convname, convname, len_convname+1);
+
+	/* load module */
+	ret = _citrus_load_module(&ci->ci_module, module);
+	if (ret)
+		goto err;
+
+	/* get operators */
+	getops = (_citrus_iconv_getops_t)
+	    _citrus_find_getops(ci->ci_module, module, "iconv");
+	if (getops == NULL) {
+		ret = EOPNOTSUPP;
+		goto err;
+	}
+	ci->ci_ops = malloc(sizeof(*ci->ci_ops), M_KICONV, M_WAITOK);
+	ret = (*getops)(ci->ci_ops, sizeof(*ci->ci_ops),
+			_CITRUS_ICONV_ABI_VERSION);
+	if (ret)
+		goto err;
+
+	/* version check */
+	if (ci->ci_ops->io_abi_version == 1) {
+		/* binary compatibility broken at ver.2 */
+		ret = EINVAL;
+		goto err;
+	}
+
+	if (ci->ci_ops->io_init_shared == NULL ||
+	    ci->ci_ops->io_uninit_shared == NULL ||
+	    ci->ci_ops->io_init_context == NULL ||
+	    ci->ci_ops->io_uninit_context == NULL ||
+	    ci->ci_ops->io_convert == NULL) {
+		ret = EINVAL;
+		goto err;
+	}
+
+	/* initialize the converter */
+	ret = (*ci->ci_ops->io_init_shared)(ci, basedir, src, dst,
+					    (const void *)variable,
+					    strlen(variable)+1);
+	if (ret)
+		goto err;
+
+	KICONV_LINEBUF_PUT(linebuf);
+	*rci = ci;
+
+	return 0;
+err:
+	close_shared(ci);
+	KICONV_LINEBUF_PUT(linebuf);
+	return ret;
+}
+
+static __inline int
+hash_func(const char *key)
+{
+	return _string_hash_func(key, CI_HASH_SIZE);
+}
+
+static __inline int
+match_func(struct _citrus_iconv_shared * __restrict ci,
+	   const char * __restrict key)
+{
+	return strcmp(ci->ci_convname, key);
+}
+
+static int
+get_shared(struct _citrus_iconv_shared * __restrict * __restrict rci,
+	   const char *basedir, const char *src, const char *dst)
+{
+	int ret = 0;
+	int hashval;
+	struct _citrus_iconv_shared * ci;
+	char *convname;
+
+	convname = PNBUF_GET();
+	KASSERT(convname != NULL);
+	snprintf(convname, PATH_MAX, "%s/%s", src, dst);
+
+	rw_enter(&kiconv_iconv_lock, RW_READER);
+
+	/* lookup alread existing entry */
+	hashval = hash_func(convname);
+	_CITRUS_HASH_SEARCH(&shared_pool, ci, ci_hash_entry, match_func,
+			    convname, hashval);
+	if (ci != NULL) {
+		/* found */
+		if (ci->ci_used_count == 0) {
+			while (rw_tryupgrade(&kiconv_iconv_lock) == 0)
+				kpause("kicic", true, 1, NULL);
+			TAILQ_REMOVE(&shared_unused, ci, ci_tailq_entry);
+			shared_num_unused--;
+			rw_downgrade(&kiconv_iconv_lock);
+		}
+		ci->ci_used_count++;
+		*rci = ci;
+		goto unlock;
+	}
+
+	rw_exit(&kiconv_iconv_lock);
+
+	/* create new entry */
+	ret = open_shared(&ci, basedir, convname, src, dst);
+	if (ret)
+		goto out;
+
+	ci->ci_used_count = 1;
+	rw_enter(&kiconv_iconv_lock, RW_WRITER);
+	_CITRUS_HASH_INSERT(&shared_pool, ci, ci_hash_entry, hashval);
+	*rci = ci;
+
+unlock:
+	rw_exit(&kiconv_iconv_lock);
+out:
+	PNBUF_PUT(convname);
+	return ret;
+}
+
+static void
+release_shared(struct _citrus_iconv_shared * __restrict ci)
+{
+
+	ci->ci_used_count--;
+	if (ci->ci_used_count == 0) {
+		rw_enter(&kiconv_iconv_lock, RW_WRITER);
+		/* put it into unused list */
+		shared_num_unused++;
+		TAILQ_INSERT_TAIL(&shared_unused, ci, ci_tailq_entry);
+		/* flood out */
+		while (shared_num_unused > shared_max_reuse) {
+			ci = TAILQ_FIRST(&shared_unused);
+			_DIAGASSERT(ci != NULL);
+			TAILQ_REMOVE(&shared_unused, ci, ci_tailq_entry);
+			_CITRUS_HASH_REMOVE(ci, ci_hash_entry);
+			shared_num_unused--;
+			close_shared(ci);
+		}
+		rw_exit(&kiconv_iconv_lock);
+	}
+}
+
+/*
+ * _citrus_iconv_open:
+ *	open a converter for the specified in/out codes.
+ */
+int
+_citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict rcv,
+		   const char * __restrict basedir,
+		   const char * __restrict src, const char * __restrict dst)
+{
+	int ret;
+	struct _citrus_iconv_shared *ci = NULL;
+	struct _citrus_iconv *cv;
+	char *realsrc, *realdst;
+	char *buf, *path;
+
+	init_cache();
+
+	realsrc = PNBUF_GET();
+	KASSERT(realsrc != NULL);
+	realdst = PNBUF_GET();
+	KASSERT(realdst != NULL);
+	buf = PNBUF_GET();
+	KASSERT(buf != NULL);
+	path = PNBUF_GET();
+	KASSERT(path != NULL);
+
+	/* resolve codeset name aliases */
+	snprintf(path, PATH_MAX, "%s/%s", basedir, _CITRUS_ICONV_ALIAS);
+	strlcpy(realsrc,
+		_lookup_alias(path, src, buf, PATH_MAX, _LOOKUP_CASE_IGNORE),
+		PATH_MAX);
+	strlcpy(realdst,
+		_lookup_alias(path, dst, buf, PATH_MAX, _LOOKUP_CASE_IGNORE),
+		PATH_MAX);
+	PNBUF_PUT(path);
+	PNBUF_PUT(buf);
+
+	/* sanity check */
+	if (strchr(realsrc, '/') != NULL || strchr(realdst, '/')) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	/* get shared record */
+	ret = get_shared(&ci, basedir, realsrc, realdst);
+	if (ret)
+		goto out;
+
+	/* create/init context */
+	cv = malloc(sizeof(*cv), M_KICONV, M_WAITOK);
+	cv->cv_shared = ci;
+	ret = (*ci->ci_ops->io_init_context)(cv);
+	if (ret) {
+		release_shared(ci);
+		free(cv, M_KICONV);
+		goto out;
+	}
+	*rcv = cv;
+
+out:
+	PNBUF_PUT(realdst);
+	PNBUF_PUT(realsrc);
+	return ret;
+}
+
+/*
+ * _citrus_iconv_close:
+ *	close the specified converter.
+ */
+void
+_citrus_iconv_close(struct _citrus_iconv *cv)
+{
+
+	if (cv) {
+		(*cv->cv_shared->ci_ops->io_uninit_context)(cv);
+		release_shared(cv->cv_shared);
+		free(cv, M_KICONV);
+	}
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_iconv.h src/sys/kiconv/citrus_iconv.h
--- src.orig/sys/kiconv/citrus_iconv.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_iconv.h	2011-06-03 14:22:56.000000000 +0900
@@ -0,0 +1,69 @@
+/*	$NetBSD: citrus_iconv.h,v 1.5 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_H_
+#define _CITRUS_ICONV_H_
+
+struct _citrus_iconv_shared;
+struct _citrus_iconv_ops;
+struct _citrus_iconv;
+
+__BEGIN_DECLS
+int	_citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict,
+			   const char * __restrict,
+			   const char * __restrict, const char * __restrict);
+void	_citrus_iconv_close(struct _citrus_iconv *);
+__END_DECLS
+
+
+#include "citrus_iconv_local.h"
+
+#define _CITRUS_ICONV_F_HIDE_INVALID	0x0001
+
+/*
+ * _citrus_iconv_convert:
+ *	convert a string.
+ */
+static __inline int
+_citrus_iconv_convert(struct _citrus_iconv * __restrict cv,
+		      const char * __restrict * __restrict in,
+		      size_t * __restrict inbytes,
+		      char * __restrict * __restrict out,
+		      size_t * __restrict outbytes, uint32_t flags,
+		      size_t * __restrict nresults)
+{
+
+	_DIAGASSERT(cv && cv->cv_shared && cv->cv_shared->ci_ops &&
+	    cv->cv_shared->ci_ops->io_convert);
+	_DIAGASSERT(out || outbytes == 0);
+
+	return (*cv->cv_shared->ci_ops->io_convert)(cv, in, inbytes, out,
+						    outbytes, flags, nresults);
+}
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_iconv_local.h src/sys/kiconv/citrus_iconv_local.h
--- src.orig/sys/kiconv/citrus_iconv_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_iconv_local.h	2011-06-03 14:23:42.000000000 +0900
@@ -0,0 +1,107 @@
+/*	$NetBSD: citrus_iconv_local.h,v 1.3 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_LOCAL_H_
+#define _CITRUS_ICONV_LOCAL_H_
+
+#define _CITRUS_ICONV_GETOPS_FUNC_BASE(_n_)				\
+int _n_(struct _citrus_iconv_ops *, size_t, uint32_t)
+#define _CITRUS_ICONV_GETOPS_FUNC(_n_)					\
+_CITRUS_ICONV_GETOPS_FUNC_BASE(_citrus_##_n_##_iconv_getops)
+
+#define _CITRUS_ICONV_DECLS(_m_)					\
+static int	_citrus_##_m_##_iconv_init_shared			\
+	(struct _citrus_iconv_shared * __restrict,			\
+	 const char * __restrict,					\
+	 const char * __restrict, const char * __restrict,		\
+	 const void * __restrict, size_t);				\
+static void	_citrus_##_m_##_iconv_uninit_shared			\
+	(struct _citrus_iconv_shared *);				\
+static int	_citrus_##_m_##_iconv_convert				\
+	(struct _citrus_iconv * __restrict,				\
+	 const char * __restrict * __restrict, size_t * __restrict,	\
+	 char * __restrict * __restrict, size_t * __restrict outbytes,	\
+	 uint32_t, size_t * __restrict);				\
+static int	_citrus_##_m_##_iconv_init_context			\
+	(struct _citrus_iconv *);					\
+static void	_citrus_##_m_##_iconv_uninit_context			\
+	(struct _citrus_iconv *)
+
+
+#define _CITRUS_ICONV_DEF_OPS(_m_)					\
+struct _citrus_iconv_ops _citrus_##_m_##_iconv_ops = {			\
+	/* io_abi_version */	_CITRUS_ICONV_ABI_VERSION,		\
+	/* io_init_shared */	&_citrus_##_m_##_iconv_init_shared,	\
+	/* io_uninit_shared */	&_citrus_##_m_##_iconv_uninit_shared,	\
+	/* io_init_context */	&_citrus_##_m_##_iconv_init_context,	\
+	/* io_uninit_context */	&_citrus_##_m_##_iconv_uninit_context,	\
+	/* io_convert */	&_citrus_##_m_##_iconv_convert		\
+}
+
+typedef _CITRUS_ICONV_GETOPS_FUNC_BASE((*_citrus_iconv_getops_t));
+typedef	int	(*_citrus_iconv_init_shared_t)
+	(struct _citrus_iconv_shared * __restrict,
+	 const char * __restrict, const char * __restrict,
+	 const char * __restrict, const void * __restrict, size_t);
+typedef void	(*_citrus_iconv_uninit_shared_t)
+	(struct _citrus_iconv_shared *);
+typedef int	(*_citrus_iconv_convert_t)
+	(struct _citrus_iconv * __restrict,
+	 const char *__restrict* __restrict, size_t * __restrict,
+	 char * __restrict * __restrict, size_t * __restrict, uint32_t,
+	 size_t * __restrict);
+typedef int	(*_citrus_iconv_init_context_t)(struct _citrus_iconv *);
+typedef void	(*_citrus_iconv_uninit_context_t)(struct _citrus_iconv *);
+
+struct _citrus_iconv_ops {
+	uint32_t			io_abi_version;
+	_citrus_iconv_init_shared_t	io_init_shared;
+	_citrus_iconv_uninit_shared_t	io_uninit_shared;
+	_citrus_iconv_init_context_t	io_init_context;
+	_citrus_iconv_uninit_context_t	io_uninit_context;
+	_citrus_iconv_convert_t		io_convert;
+};
+#define _CITRUS_ICONV_ABI_VERSION	2
+
+struct _citrus_iconv_shared {
+	struct _citrus_iconv_ops			*ci_ops;
+	void						*ci_closure;
+	/* private */
+	_CITRUS_HASH_ENTRY(_citrus_iconv_shared)	ci_hash_entry;
+	TAILQ_ENTRY(_citrus_iconv_shared)		ci_tailq_entry;
+	_citrus_module_t				ci_module;
+	unsigned int					ci_used_count;
+	char						*ci_convname;
+};
+
+struct _citrus_iconv {
+	struct _citrus_iconv_shared	*cv_shared;
+	void				*cv_closure;
+};
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_lc_ctype.c src/sys/kiconv/citrus_lc_ctype.c
--- src.orig/sys/kiconv/citrus_lc_ctype.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_lc_ctype.c	2011-06-03 21:56:47.000000000 +0900
@@ -0,0 +1,144 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_lc_ctype.c,v 1.9 2010/06/19 13:26:51 tnozaki Exp */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_lc_ctype.c,v 1.9 2010/06/19 13:26:51 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/namei.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/ctype_bits.h>
+#include <sys/queue.h>
+#include <assert.h>
+#include <errno.h>
+#include <langinfo.h>
+#include <limits.h>
+#define __SETLOCALE_SOURCE__
+#include <locale.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#endif
+
+#include "setlocale_local.h"
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_lookup.h"
+#include "citrus_aliasname_local.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_mmap.h"
+
+#include "runetype_local.h"
+#include "multibyte.h"
+
+/*
+ * macro required by all template headers
+ */
+#define _PREFIX(name)		__CONCAT(_citrus_LC_CTYPE_, name)
+
+/*
+ * macro required by nb_lc_template(_decl).h
+ */
+#define _CATEGORY_TYPE          _RuneLocale
+
+#include "nb_lc_template_decl.h"
+
+static int
+_citrus_LC_CTYPE_create_impl(const char * __restrict root,
+    const char * __restrict name, _RuneLocale ** __restrict pdata)
+{
+	char *path;
+	int ret;
+	struct _region r;
+
+	_DIAGASSERT(root != NULL);
+	_DIAGASSERT(name != NULL);
+	_DIAGASSERT(pdata != NULL);
+
+	path = PNBUF_GET();
+	KASSERT(path != NULL);
+	snprintf(path, PATH_MAX, "%s/%s/LC_CTYPE", root, name);
+	ret = _citrus_map_file(&r, path);
+	PNBUF_PUT(path);
+	if (!ret) {
+		ret = _rune_load((const char *)r.r_head, r.r_size, pdata);
+		_citrus_unmap_file(&r);
+	}
+	return ret;
+}
+
+static __inline void
+_PREFIX(build_cache)(struct _klocale_cache_t * __restrict cache,
+    _RuneLocale * __restrict data)
+{
+	_DIAGASSERT(cache != NULL);
+	_DIAGASSERT(cache->items != NULL);
+	_DIAGASSERT(data != NULL);
+
+	cache->ctype_tab = data->rl_ctype_tab;
+	cache->tolower_tab = data->rl_tolower_tab;
+	cache->toupper_tab = data->rl_toupper_tab;
+	cache->mb_cur_max = _citrus_ctype_get_mb_cur_max(data->rl_citrus_ctype);
+}
+
+static __inline void
+_PREFIX(fixup)(_RuneLocale *data)
+{
+	_DIAGASSERT(data != NULL);
+
+	__mb_cur_max = _citrus_ctype_get_mb_cur_max(data->rl_citrus_ctype);
+	_ctype_ = data->rl_ctype_tab;
+	_tolower_tab_ = data->rl_tolower_tab;
+	_toupper_tab_ = data->rl_toupper_tab;
+	_CurrentRuneLocale = data;
+}
+
+/*
+ * macro required by nb_lc_template.h
+ */
+#define _CATEGORY_ID		LC_CTYPE
+#define _CATEGORY_NAME		"LC_CTYPE"
+#define _CATEGORY_DEFAULT	_DefaultRuneLocale
+
+#include "nb_lc_template.h"
+_LOCALE_CATEGORY_ENTRY(_citrus_LC_CTYPE_);
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_lookup.c src/sys/kiconv/citrus_lookup.c
--- src.orig/sys/kiconv/citrus_lookup.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_lookup.c	2011-06-27 08:25:33.000000000 +0900
@@ -0,0 +1,377 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_lookup.c,v 1.6 2009/02/03 04:58:38 lukem Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_lookup.c,v 1.6 2009/02/03 04:58:38 lukem Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <dirent.h>
+#include <sys/types.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_db.h"
+#include "citrus_db_hash.h"
+#include "citrus_lookup.h"
+#include "citrus_lookup_file.h"
+
+struct _citrus_lookup {
+	union {
+		struct {
+			struct _citrus_db *db;
+			struct _citrus_region file;
+			int num, idx;
+			struct _db_locator locator;
+		} db;
+		struct {
+			struct _region r;
+			struct _memstream ms;
+		} plain;
+	} u;
+#define cl_db		u.db.db
+#define cl_dbidx	u.db.idx
+#define cl_dbfile	u.db.file
+#define cl_dbnum	u.db.num
+#define cl_dblocator	u.db.locator
+#define cl_plainr	u.plain.r
+#define cl_plainms	u.plain.ms
+	int cl_ignore_case;
+	int cl_rewind;
+	char *cl_key;
+	size_t cl_keylen;
+	int (*cl_next)(struct _citrus_lookup *, struct _region *,
+		       struct _region *);
+	int (*cl_lookup)(struct _citrus_lookup *, const char *,
+			 struct _region *);
+	int (*cl_num_entries)(struct _citrus_lookup *);
+	void (*cl_close)(struct _citrus_lookup *);
+};
+
+static int
+seq_get_num_entries_db(struct _citrus_lookup *cl)
+{
+	return cl->cl_dbnum;
+}
+
+static int
+seq_next_db(struct _citrus_lookup *cl,
+	    struct _region *key, struct _region *data)
+{
+
+	if (cl->cl_key) {
+		if (key)
+			_region_init(key, cl->cl_key, cl->cl_keylen);
+		return _db_lookup_by_s(cl->cl_db, cl->cl_key, data,
+				       &cl->cl_dblocator);
+	}
+
+	if (cl->cl_rewind) {
+		cl->cl_dbidx = 0;
+	}
+	cl->cl_rewind = 0;
+	if (cl->cl_dbidx >= cl->cl_dbnum)
+		return ENOENT;
+
+	return _db_get_entry(cl->cl_db, cl->cl_dbidx++, key, data);
+}
+
+static int
+seq_lookup_db(struct _citrus_lookup *cl, const char *key,
+	      struct _region *data)
+{
+
+	cl->cl_rewind = 0;
+	if (cl->cl_key)
+		free(cl->cl_key, M_KICONV);
+	cl->cl_key = strdup(key);
+	if (cl->cl_ignore_case)
+		_bcs_convert_to_lower(cl->cl_key);
+	cl->cl_keylen = strlen(cl->cl_key);
+	_db_locator_init(&cl->cl_dblocator);
+	return _db_lookup_by_s(cl->cl_db, cl->cl_key, data, &cl->cl_dblocator);
+}
+
+static void
+seq_close_db(struct _citrus_lookup *cl)
+{
+
+	_db_close(cl->cl_db);
+	_unmap_file(&cl->cl_dbfile);
+}
+
+static int
+seq_open_db(struct _citrus_lookup *cl, const char *name)
+{
+	int ret;
+	struct _region r;
+	char *path;
+
+	path = PNBUF_GET();
+	KASSERT(path != NULL);
+	snprintf(path, PATH_MAX, "%s.db", name);
+	ret = _map_file(&r, path);
+	PNBUF_PUT(path);
+	if (ret)
+		return ret;
+
+	ret = _db_open(&cl->cl_db, &r, _CITRUS_LOOKUP_MAGIC,
+		       _db_hash_std, NULL);
+	if (ret) {
+		_unmap_file(&r);
+		return ret;
+	}
+
+	cl->cl_dbfile = r;
+	cl->cl_dbnum = _db_get_num_entries(cl->cl_db);
+	cl->cl_dbidx = 0;
+	cl->cl_rewind = 1;
+	cl->cl_lookup = &seq_lookup_db;
+	cl->cl_next = &seq_next_db;
+	cl->cl_num_entries = &seq_get_num_entries_db;
+	cl->cl_close = &seq_close_db;
+
+	return 0;
+}
+
+#define T_COMM '#'
+static int
+seq_next_plain(struct _citrus_lookup *cl, struct _region *key,
+	       struct _region *data)
+{
+	const char *p, *q;
+	size_t len;
+
+	if (cl->cl_rewind)
+		_memstream_bind(&cl->cl_plainms, &cl->cl_plainr);
+	cl->cl_rewind = 0;
+
+retry:
+	p = _memstream_getln(&cl->cl_plainms, &len);
+	if (p == NULL)
+		return ENOENT;
+
+	/* ignore comment */
+	q = memchr(p, T_COMM, len);
+	if (q) {
+		len = q-p;
+	}
+	/* ignore trailing spaces */
+	_bcs_trunc_rws_len(p, &len);
+	p = _bcs_skip_ws_len(p, &len);
+	q = _bcs_skip_nonws_len(p, &len);
+	if (p==q)
+		goto retry;
+	if (cl->cl_key && ((size_t)(q-p) != cl->cl_keylen ||
+			   memcmp(p, cl->cl_key, (size_t)(q-p)) != 0))
+		goto retry;
+
+	/* found a entry */
+	if (key)
+		_region_init(key, __UNCONST(p), (size_t)(q-p));
+	p = _bcs_skip_ws_len(q, &len);
+	if (data)
+		_region_init(data, len ? __UNCONST(p) : NULL, len);
+
+	return 0;
+}
+
+static int
+seq_get_num_entries_plain(struct _citrus_lookup *cl)
+{
+	int num;
+
+	num = 0;
+	while (seq_next_plain(cl, NULL, NULL) == 0)
+		num++;
+
+	return num;
+}
+
+static int
+seq_lookup_plain(struct _citrus_lookup *cl, const char *key,
+		 struct _region *data)
+{
+	size_t len;
+	const char *p;
+
+	cl->cl_rewind = 0;
+	if (cl->cl_key)
+		free(cl->cl_key, M_KICONV);
+	cl->cl_key = strdup(key);
+	if (cl->cl_ignore_case)
+		_bcs_convert_to_lower(cl->cl_key);
+	cl->cl_keylen = strlen(cl->cl_key);
+	_memstream_bind(&cl->cl_plainms, &cl->cl_plainr);
+	p = _memstream_matchline(&cl->cl_plainms, cl->cl_key, &len, 0);
+	if (p == NULL)
+		return ENOENT;
+	if (data)
+		_region_init(data, __UNCONST(p), len);
+
+	return 0;
+}
+
+static void
+seq_close_plain(struct _citrus_lookup *cl)
+{
+
+	_unmap_file(&cl->cl_plainr);
+}
+
+static int
+seq_open_plain(struct _citrus_lookup *cl, const char *name)
+{
+	int ret;
+
+	/* open read stream */
+	ret = _map_file(&cl->cl_plainr, name);
+	if (ret)
+		return ret;
+
+	cl->cl_rewind = 1;
+	cl->cl_next = &seq_next_plain;
+	cl->cl_lookup = &seq_lookup_plain;
+	cl->cl_num_entries = &seq_get_num_entries_plain;
+	cl->cl_close = &seq_close_plain;
+
+	return 0;
+}
+
+int
+_citrus_lookup_seq_open(struct _citrus_lookup **rcl, const char *name,
+			int ignore_case)
+{
+	int ret;
+	struct _citrus_lookup *cl;
+
+	cl = malloc(sizeof(*cl), M_KICONV, M_WAITOK);
+	cl->cl_key = NULL;
+	cl->cl_keylen = 0;
+	cl->cl_ignore_case = ignore_case;
+	ret = seq_open_db(cl, name);
+	if (ret == ENOENT)
+		ret = seq_open_plain(cl, name);
+	if (!ret)
+		*rcl = cl;
+	else
+		free(cl, M_KICONV);
+
+	return ret;
+}
+
+void
+_citrus_lookup_seq_rewind(struct _citrus_lookup *cl)
+{
+	cl->cl_rewind = 1;
+	if (cl->cl_key) {
+		free(cl->cl_key, M_KICONV);
+		cl->cl_key = NULL;
+	}
+	cl->cl_keylen = 0;
+}
+
+int
+_citrus_lookup_seq_next(struct _citrus_lookup *cl,
+			struct _region *key, struct _region *data)
+{
+	return (*cl->cl_next)(cl, key, data);
+}
+
+int
+_citrus_lookup_seq_lookup(struct _citrus_lookup *cl, const char *key,
+			  struct _region *data)
+{
+	return (*cl->cl_lookup)(cl, key, data);
+}
+
+int
+_citrus_lookup_get_number_of_entries(struct _citrus_lookup *cl)
+{
+	return (*cl->cl_num_entries)(cl);
+}
+
+void
+_citrus_lookup_seq_close(struct _citrus_lookup *cl)
+{
+
+	if (cl->cl_key)
+		free(cl->cl_key, M_KICONV);
+	(*cl->cl_close)(cl);
+	free(cl, M_KICONV);
+}
+
+char *
+_citrus_lookup_simple(const char *name, const char *key,
+		      char *linebuf, size_t linebufsize, int ignore_case)
+{
+	int ret;
+	struct _citrus_lookup *cl;
+	struct _region data;
+
+	ret = _citrus_lookup_seq_open(&cl, name, ignore_case);
+	if (ret)
+		return NULL;
+
+	ret = _citrus_lookup_seq_lookup(cl, key, &data);
+	if (ret) {
+		_citrus_lookup_seq_close(cl);
+		return NULL;
+	}
+
+	snprintf(linebuf, linebufsize, "%.*s",
+		 (int)_region_size(&data), (const char *)_region_head(&data));
+
+	_citrus_lookup_seq_close(cl);
+
+	return linebuf;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_lookup.h src/sys/kiconv/citrus_lookup.h
--- src.orig/sys/kiconv/citrus_lookup.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_lookup.h	2011-06-03 14:37:47.000000000 +0900
@@ -0,0 +1,61 @@
+/*	$NetBSD: citrus_lookup.h,v 1.2 2004/07/21 14:16:34 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_LOOKUP_H_
+#define _CITRUS_LOOKUP_H_
+
+#define _CITRUS_LOOKUP_CASE_SENSITIVE	0
+#define _CITRUS_LOOKUP_CASE_IGNORE	1
+
+struct _citrus_lookup;
+__BEGIN_DECLS
+char *_citrus_lookup_simple(const char *, const char *, char *, size_t, int);
+int _citrus_lookup_seq_open(struct _citrus_lookup **, const char *, int);
+void _citrus_lookup_seq_rewind(struct _citrus_lookup *);
+int _citrus_lookup_seq_next(struct _citrus_lookup *,
+			    struct _region *, struct _region *);
+int _citrus_lookup_seq_lookup(struct _citrus_lookup *, const char *,
+			      struct _region *);
+int _citrus_lookup_get_number_of_entries(struct _citrus_lookup *);
+void _citrus_lookup_seq_close(struct _citrus_lookup *);
+__END_DECLS
+
+static __inline const char *
+_citrus_lookup_alias(const char *path, const char *key, char *buf, size_t n,
+		     int ignore_case)
+{
+	const char *ret;
+
+	ret = _citrus_lookup_simple(path, key, buf, n, ignore_case);
+	if (ret == NULL)
+		ret = key;
+
+	return ret;
+}
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_lookup_file.h src/sys/kiconv/citrus_lookup_file.h
--- src.orig/sys/kiconv/citrus_lookup_file.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_lookup_file.h	2011-06-03 14:38:30.000000000 +0900
@@ -0,0 +1,34 @@
+/*	$NetBSD: citrus_lookup_file.h,v 1.1 2003/06/25 09:51:36 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_LOOKUP_FILE_H_
+#define _CITRUS_LOOKUP_FILE_H_
+
+#define _CITRUS_LOOKUP_MAGIC	"LOOKUP\0\0"
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_mapper.c src/sys/kiconv/citrus_mapper.c
--- src.orig/sys/kiconv/citrus_mapper.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_mapper.c	2011-06-03 16:59:40.000000000 +0900
@@ -0,0 +1,441 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_mapper.c,v 1.7 2008/07/25 14:05:25 christos Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_mapper.c,v 1.7 2008/07/25 14:05:25 christos Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/rwlock.h>
+#include <sys/filedesc.h>
+#include <sys/namei.h>
+#include <sys/vnode.h>
+#include <sys/kauth.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include "reentrant.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_bcs.h"
+#include "citrus_mmap.h"
+#include "citrus_module.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+
+#define _CITRUS_MAPPER_DIR	"mapper.dir"
+
+#define CM_HASH_SIZE 101
+#define REFCOUNT_PERSISTENT	-1
+
+krwlock_t kiconv_mapper_lock __cacheline_aligned;
+
+struct _citrus_mapper_area {
+	_CITRUS_HASH_HEAD(, _citrus_mapper, CM_HASH_SIZE)	ma_cache;
+	char							*ma_dir;
+};
+
+
+/*
+ * _citrus_mapper_create_area:
+ *	create mapper area
+ */
+
+int
+_citrus_mapper_create_area(
+	struct _citrus_mapper_area *__restrict *__restrict rma,
+	const char *__restrict area)
+{
+	struct _citrus_mapper_area *ma;
+	struct pathbuf *pb;
+	struct nameidata nd;
+	struct vattr va;
+	char *path;
+	struct vnode *vp;
+	int error;
+	extern struct cwdinfo cwdi0;
+
+	if (*rma != NULL)
+		return 0;
+
+	if (cwdi0.cwdi_cdir == NULL) {
+		printf("_citrus_mapper_create_area(%s/%s) call too early.\n",
+		    area, _CITRUS_MAPPER_DIR);
+		return ENOENT;
+	}
+
+	path = PNBUF_GET();
+	KASSERT(path != NULL);
+	snprintf(path, PATH_MAX, "%s/%s", area, _CITRUS_MAPPER_DIR);
+	pb = pathbuf_create(path);
+	PNBUF_PUT(path);
+	if (pb == NULL) {
+		error = ENOMEM;
+		goto out;
+	}
+	NDINIT(&nd, LOOKUP, FOLLOW | NOCHROOT, pb);
+	error = vn_open(&nd, FREAD, 0);
+	pathbuf_destroy(pb);
+	if (error)
+		goto out;
+
+	vp = nd.ni_vp;
+
+	error = VOP_GETATTR(vp, &va, kauth_cred_get());
+	if (error)
+		goto res_free;
+
+	if (va.va_type != VREG) {
+		error = EINVAL;
+		goto res_free;
+	}
+
+	ma = malloc(sizeof(*ma), M_KICONV, M_WAITOK);
+	ma->ma_dir = strdup(area);
+	_CITRUS_HASH_INIT(&ma->ma_cache, CM_HASH_SIZE);
+	*rma = ma;
+
+res_free:
+	VOP_UNLOCK(vp);
+	(void)vn_close(vp, FREAD, kauth_cred_get());
+out:
+	return error;
+}
+
+
+/*
+ * lookup_mapper_entry:
+ *	lookup mapper.dir entry in the specified directory.
+ *
+ * line format of iconv.dir file:
+ *	mapper	module	arg
+ * mapper : mapper name.
+ * module : mapper module name.
+ * arg    : argument for the module (generally, description file name)
+ */
+
+static int
+lookup_mapper_entry(const char *dir, const char *mapname,
+		    void *linebuf, size_t linebufsize,
+		    const char **module, const char **variable)
+{
+	struct _region r;
+	struct _memstream ms;
+	int ret;
+	const char *cp, *cq;
+	char *p;
+	size_t len;
+	char *path;
+
+	path = PNBUF_GET();
+	KASSERT(path != NULL);
+
+	/* create mapper.dir path */
+	snprintf(path, PATH_MAX, "%s/%s", dir, _CITRUS_MAPPER_DIR);
+
+	/* open read stream */
+	ret = _map_file(&r, path);
+	PNBUF_PUT(path);
+	if (ret)
+		return ret;
+
+	_memstream_bind(&ms, &r);
+
+	/* search the line matching to the map name */
+	cp = _memstream_matchline(&ms, mapname, &len, 0);
+	if (!cp) {
+		ret = ENOENT;
+		goto quit;
+	}
+	if (!len || len>linebufsize-1) {
+		ret = EINVAL;
+		goto quit;
+	}
+
+	p = linebuf;
+	/* get module name */
+	*module = p;
+	cq = _bcs_skip_nonws_len(cp, &len);
+	memcpy(p, cp, cq-cp);
+	p[cq-cp] = '\0';
+	p += cq-cp+1;
+
+	/* get variable */
+	*variable = p;
+	cp = _bcs_skip_ws_len(cq, &len);
+	memcpy(p, cp, len);
+	p[len] = '\0';
+
+quit:
+	_unmap_file(&r);
+	return ret;
+}
+
+/*
+ * mapper_close:
+ *	simply close a mapper. (without handling hash)
+ */
+static void
+mapper_close(struct _citrus_mapper *cm)
+{
+
+	if (cm->cm_module) {
+		if (cm->cm_ops) {
+			if (cm->cm_closure)
+				(*cm->cm_ops->mo_uninit)(cm);
+			free(cm->cm_ops, M_KICONV);
+		}
+		_citrus_unload_module(cm->cm_module);
+	}
+	if (cm->cm_traits)
+		free(cm->cm_traits, M_KICONV);
+	free(cm, M_KICONV);
+}
+
+/*
+ * mapper_open:
+ *	simply open a mapper. (without handling hash)
+ */
+static int
+mapper_open(struct _citrus_mapper_area *__restrict ma,
+	    struct _citrus_mapper * __restrict * __restrict rcm,
+	    const char * __restrict module,
+	    const char * __restrict variable)
+{
+	int ret;
+	struct _citrus_mapper *cm;
+	_citrus_mapper_getops_t getops;
+
+	/* initialize mapper handle */
+	cm = malloc(sizeof(*cm), M_KICONV, M_WAITOK);
+	cm->cm_module = NULL;
+	cm->cm_ops = NULL;
+	cm->cm_closure = NULL;
+	cm->cm_traits = NULL;
+	cm->cm_refcount = 0;
+	cm->cm_key = NULL;
+
+	/* load module */
+	ret = _citrus_load_module(&cm->cm_module, module);
+	if (ret)
+		goto err;
+
+	/* get operators */
+	getops = (_citrus_mapper_getops_t)
+	    _citrus_find_getops(cm->cm_module, module, "mapper");
+	if (getops == NULL) {
+		ret = EOPNOTSUPP;
+		goto err;
+	}
+	cm->cm_ops = malloc(sizeof(*cm->cm_ops), M_KICONV, M_WAITOK);
+	ret = (*getops)(cm->cm_ops, sizeof(*cm->cm_ops),
+			_CITRUS_MAPPER_ABI_VERSION);
+	if (ret)
+		goto err;
+
+	if (!cm->cm_ops->mo_init ||
+	    !cm->cm_ops->mo_uninit ||
+	    !cm->cm_ops->mo_convert ||
+	    !cm->cm_ops->mo_init_state) {
+		ret = EINVAL;
+		goto err;
+	}
+
+	/* allocate traits structure */
+	cm->cm_traits = malloc(sizeof(*cm->cm_traits), M_KICONV, M_WAITOK);
+
+	/* initialize the mapper */
+	ret = (*cm->cm_ops->mo_init)(ma, cm, ma->ma_dir,
+				     (const void *)variable,
+				     strlen(variable)+1,
+				     cm->cm_traits, sizeof(*cm->cm_traits));
+	if (ret)
+		goto err;
+
+	*rcm = cm;
+
+	return 0;
+
+err:
+	mapper_close(cm);
+	return ret;
+}
+
+/*
+ * _citrus_mapper_open_direct:
+ *	open a mapper.
+ */
+int
+_citrus_mapper_open_direct(struct _citrus_mapper_area *__restrict ma,
+			   struct _citrus_mapper * __restrict * __restrict rcm,
+			   const char * __restrict module,
+			   const char * __restrict variable)
+{
+	return mapper_open(ma, rcm, module, variable);
+}
+
+/*
+ * hash_func
+ */
+static __inline int
+hash_func(const char *key)
+{
+	return _string_hash_func(key, CM_HASH_SIZE);
+}
+
+/*
+ * match_func
+ */
+static __inline int
+match_func(struct _citrus_mapper *cm, const char *key)
+{
+	return strcmp(cm->cm_key, key);
+}
+
+/*
+ * _citrus_mapper_open:
+ *	open a mapper with looking up "mapper.dir".
+ */
+int
+_citrus_mapper_open(struct _citrus_mapper_area *__restrict ma,
+		    struct _citrus_mapper * __restrict * __restrict rcm,
+		    const char * __restrict mapname)
+{
+	int ret;
+	char *linebuf;
+	const char *module, *variable = NULL;
+	struct _citrus_mapper *cm;
+	int hashval;
+
+	linebuf = KICONV_LINEBUF_GET();
+	KASSERT(linebuf != NULL);
+
+	rw_enter(&kiconv_mapper_lock, RW_READER);
+
+	/* search in the cache */
+	hashval = hash_func(mapname);
+	_CITRUS_HASH_SEARCH(&ma->ma_cache, cm, cm_entry, match_func, mapname,
+			    hashval);
+	if (cm) {
+		/* found */
+		cm->cm_refcount++;
+		*rcm = cm;
+		ret = 0;
+		goto unlock;
+	}
+
+	rw_exit(&kiconv_mapper_lock);
+
+	/* search mapper entry */
+	ret = lookup_mapper_entry(ma->ma_dir, mapname, linebuf, LINE_MAX,
+	    &module, &variable);
+	if (ret)
+		goto out;
+
+	/* open mapper */
+	ret = mapper_open(ma, &cm, module, variable);
+	if (ret)
+		goto out;
+	cm->cm_key = strdup(mapname);
+
+	/* insert to the cache */
+	cm->cm_refcount = 1;
+	rw_enter(&kiconv_mapper_lock, RW_WRITER);
+	_CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval);
+
+	*rcm = cm;
+unlock:
+	rw_exit(&kiconv_mapper_lock);
+out:
+	KICONV_LINEBUF_PUT(linebuf);
+	return ret;
+}
+
+/*
+ * _citrus_mapper_close:
+ *	close the specified mapper.
+ */
+void
+_citrus_mapper_close(struct _citrus_mapper *cm)
+{
+
+	if (cm) {
+		rw_enter(&kiconv_mapper_lock, RW_READER);
+		if (cm->cm_refcount == REFCOUNT_PERSISTENT)
+			goto quit;
+		if (cm->cm_refcount > 0) {
+			if (--cm->cm_refcount > 0)
+				goto quit;
+			while (rw_tryupgrade(&kiconv_mapper_lock) == 0)
+				kpause("kicmap", true, 1, NULL);
+			_CITRUS_HASH_REMOVE(cm, cm_entry);
+			rw_downgrade(&kiconv_mapper_lock);
+			if (cm->cm_key)
+				free(cm->cm_key, M_KICONV);
+		}
+		rw_exit(&kiconv_mapper_lock);
+		mapper_close(cm);
+		return;
+quit:
+		rw_exit(&kiconv_mapper_lock);
+	}
+}
+
+/*
+ * _citrus_mapper_set_persistent:
+ *	set persistent count.
+ */
+void
+_citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)
+{
+
+	rw_enter(&kiconv_mapper_lock, RW_WRITER);
+	cm->cm_refcount = REFCOUNT_PERSISTENT;
+	rw_exit(&kiconv_mapper_lock);
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_mapper.h src/sys/kiconv/citrus_mapper.h
--- src.orig/sys/kiconv/citrus_mapper.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_mapper.h	2011-06-03 14:37:47.000000000 +0900
@@ -0,0 +1,142 @@
+/*	$NetBSD: citrus_mapper.h,v 1.3 2003/07/12 15:39:19 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_H_
+#define _CITRUS_MAPPER_H_
+
+struct _citrus_mapper_area;
+struct _citrus_mapper;
+struct _citrus_mapper_ops;
+struct _citrus_mapper_traits;
+
+__BEGIN_DECLS
+int	_citrus_mapper_create_area(
+		struct _citrus_mapper_area *__restrict *__restrict,
+		const char *__restrict);
+int	_citrus_mapper_open(struct _citrus_mapper_area *__restrict,
+			    struct _citrus_mapper *__restrict *__restrict,
+			    const char *__restrict);
+int	_citrus_mapper_open_direct(
+		struct _citrus_mapper_area *__restrict,
+		struct _citrus_mapper *__restrict *__restrict,
+		const char *__restrict, const char *__restrict);
+void	_citrus_mapper_close(struct _citrus_mapper *);
+void	_citrus_mapper_set_persistent(struct _citrus_mapper * __restrict);
+__END_DECLS
+
+#include "citrus_mapper_local.h"
+
+/* return values of _citrus_mapper_convert */
+#define _CITRUS_MAPPER_CONVERT_SUCCESS		(0)
+#define _CITRUS_MAPPER_CONVERT_NONIDENTICAL	(1)
+#define _CITRUS_MAPPER_CONVERT_SRC_MORE		(2)
+#define _CITRUS_MAPPER_CONVERT_DST_MORE		(3)
+#define _CITRUS_MAPPER_CONVERT_ILSEQ		(4)
+#define _CITRUS_MAPPER_CONVERT_FATAL		(5)
+
+/*
+ * _citrus_mapper_convert:
+ *	convert an index.
+ *	- if the converter supports M:1 converter, the function may return
+ *	  _CITRUS_MAPPER_CONVERT_SRC_MORE and the storage pointed by dst
+ *	  may be unchanged in this case, although the internal status of
+ *	  the mapper is affected.
+ *	- if the converter supports 1:N converter, the function may return
+ *	  _CITRUS_MAPPER_CONVERT_DST_MORE. In this case, the contiguous
+ *	  call of this function ignores src and changes the storage pointed
+ *	  by dst.
+ *	- if the converter supports M:N converter, the function may behave
+ *	  the combination of the above.
+ *
+ */
+static __inline int
+_citrus_mapper_convert(struct _citrus_mapper * __restrict cm,
+		       _citrus_index_t * __restrict dst,
+		       _citrus_index_t src,
+		       void * __restrict ps)
+{
+
+	_DIAGASSERT(cm && cm->cm_ops && cm->cm_ops->mo_convert && dst);
+
+	return (*cm->cm_ops->mo_convert)(cm, dst, src, ps);
+}
+
+/*
+ * _citrus_mapper_init_state:
+ *	initialize the state.
+ */
+static __inline void
+_citrus_mapper_init_state(struct _citrus_mapper * __restrict cm,
+			  void * __restrict ps)
+{
+
+	_DIAGASSERT(cm && cm->cm_ops && cm->cm_ops->mo_init_state);
+
+	(*cm->cm_ops->mo_init_state)(cm, ps);
+}
+
+/*
+ * _citrus_mapper_get_state_size:
+ *	get the size of state storage.
+ */
+static __inline size_t
+_citrus_mapper_get_state_size(struct _citrus_mapper * __restrict cm)
+{
+
+	_DIAGASSERT(cm && cm->cm_traits);
+
+	return cm->cm_traits->mt_state_size;
+}
+
+/*
+ * _citrus_mapper_get_src_max:
+ *	get the maximum number of suspended sources.
+ */
+static __inline size_t
+_citrus_mapper_get_src_max(struct _citrus_mapper * __restrict cm)
+{
+
+	_DIAGASSERT(cm && cm->cm_traits);
+
+	return cm->cm_traits->mt_src_max;
+}
+
+/*
+ * _citrus_mapper_get_dst_max:
+ *	get the maximum number of suspended destinations.
+ */
+static __inline size_t
+_citrus_mapper_get_dst_max(struct _citrus_mapper * __restrict cm)
+{
+
+	_DIAGASSERT(cm && cm->cm_traits);
+
+	return cm->cm_traits->mt_dst_max;
+}
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_mapper_local.h src/sys/kiconv/citrus_mapper_local.h
--- src.orig/sys/kiconv/citrus_mapper_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_mapper_local.h	2011-06-03 14:38:01.000000000 +0900
@@ -0,0 +1,105 @@
+/*	$NetBSD: citrus_mapper_local.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_LOCAL_H_
+#define _CITRUS_MAPPER_LOCAL_H_
+
+#define _CITRUS_MAPPER_GETOPS_FUNC_BASE(_n_)				\
+int _n_(struct _citrus_mapper_ops *, size_t, uint32_t)
+#define _CITRUS_MAPPER_GETOPS_FUNC(_n_)					\
+_CITRUS_MAPPER_GETOPS_FUNC_BASE(_citrus_##_n_##_mapper_getops)
+
+#define _CITRUS_MAPPER_DECLS(_m_)					\
+static int	_citrus_##_m_##_mapper_init				\
+	(struct _citrus_mapper_area *__restrict,			\
+	 struct _citrus_mapper * __restrict, const char * __restrict,	\
+	 const void * __restrict, size_t,				\
+	 struct _citrus_mapper_traits * __restrict, size_t);		\
+static void	_citrus_##_m_##_mapper_uninit(struct _citrus_mapper *);	\
+static int	_citrus_##_m_##_mapper_convert				\
+	(struct _citrus_mapper * __restrict,				\
+	 _citrus_index_t * __restrict, _citrus_index_t,			\
+	 void * __restrict);						\
+static void	_citrus_##_m_##_mapper_init_state			\
+	(struct _citrus_mapper * __restrict, void * __restrict);
+
+#define _CITRUS_MAPPER_DEF_OPS(_m_)					\
+struct _citrus_mapper_ops _citrus_##_m_##_mapper_ops = {		\
+	/* mo_abi_version */	_CITRUS_MAPPER_ABI_VERSION,		\
+	/* mo_init */		&_citrus_##_m_##_mapper_init,		\
+	/* mo_uninit */		&_citrus_##_m_##_mapper_uninit,		\
+	/* mo_convert */	&_citrus_##_m_##_mapper_convert,	\
+	/* mo_init_state */	&_citrus_##_m_##_mapper_init_state	\
+}
+
+typedef _CITRUS_MAPPER_GETOPS_FUNC_BASE((*_citrus_mapper_getops_t));
+typedef	int	(*_citrus_mapper_init_t)(
+	struct _citrus_mapper_area *__restrict,
+	struct _citrus_mapper *__restrict, const char *__restrict,
+	const void *__restrict, size_t,
+	struct _citrus_mapper_traits * __restrict, size_t);
+typedef void	(*_citrus_mapper_uninit_t)(struct _citrus_mapper *);
+typedef int	(*_citrus_mapper_convert_t)(struct _citrus_mapper * __restrict,
+					    _citrus_index_t * __restrict,
+					    _citrus_index_t,
+					    void * __restrict);
+typedef void	(*_citrus_mapper_init_state_t)(
+	struct _citrus_mapper * __restrict, void * __restrict);
+
+/*
+ * ABI version change log
+ *   0x00000001
+ *     initial version
+ */
+#define _CITRUS_MAPPER_ABI_VERSION	0x00000001
+struct _citrus_mapper_ops {
+	uint32_t			mo_abi_version;
+	/* version 0x00000001 */
+	_citrus_mapper_init_t		mo_init;
+	_citrus_mapper_uninit_t		mo_uninit;
+	_citrus_mapper_convert_t	mo_convert;
+	_citrus_mapper_init_state_t	mo_init_state;
+};
+
+struct _citrus_mapper_traits {
+	/* version 0x00000001 */
+	size_t				mt_state_size;
+	size_t				mt_src_max;
+	size_t				mt_dst_max;
+};
+
+struct _citrus_mapper {
+	struct _citrus_mapper_ops		*cm_ops;
+	void					*cm_closure;
+	_citrus_module_t			cm_module;
+	struct _citrus_mapper_traits		*cm_traits;
+	_CITRUS_HASH_ENTRY(_citrus_mapper)	cm_entry;
+	int					cm_refcount;
+	char					*cm_key;
+};
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_memstream.c src/sys/kiconv/citrus_memstream.c
--- src.orig/sys/kiconv/citrus_memstream.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_memstream.c	2011-06-02 20:00:49.000000000 +0900
@@ -0,0 +1,163 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_memstream.c,v 1.4 2009/02/03 05:02:12 lukem Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_memstream.c,v 1.4 2009/02/03 05:02:12 lukem Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_bcs.h"
+
+const char *
+_citrus_memory_stream_getln(struct _citrus_memory_stream * __restrict ms,
+			    size_t * __restrict rlen)
+{
+	int i;
+	const uint8_t *h, *p;
+	size_t ret;
+
+	if (ms->ms_pos>=_region_size(&ms->ms_region))
+		return (NULL);
+
+	h = p = (uint8_t *)_region_offset(&ms->ms_region, ms->ms_pos);
+	ret = 0;
+	for (i = _region_size(&ms->ms_region) - ms->ms_pos; i > 0; i--) {
+		ret++;
+		if (_bcs_iseol(*p))
+			break;
+		p++;
+	}
+
+	ms->ms_pos += ret;
+	*rlen = ret;
+	return ((const char *)h);
+}
+
+#define T_COMM	'#'
+
+const char *
+_citrus_memory_stream_matchline(struct _citrus_memory_stream * __restrict ms,
+				const char * __restrict key,
+				size_t * __restrict rlen,
+				int iscasesensitive)
+{
+	const char *p, *q;
+	size_t len, keylen;
+
+	keylen = strlen(key);
+	while (/*CONSTCOND*/ 1) {
+		p = _citrus_memory_stream_getln(ms, &len);
+		if (p == NULL)
+			return (NULL);
+
+		/* ignore comment */
+		q = memchr(p, T_COMM, len);
+		if (q) {
+			len = q-p;
+		}
+		/* ignore trailing white space and newline */
+		_bcs_trunc_rws_len(p, &len);
+		if (len == 0)
+			continue; /* ignore null line */
+
+		/* skip white spaces at the head of the line */
+		p = _bcs_skip_ws_len(p, &len);
+		q = _bcs_skip_nonws_len(p, &len);
+
+		if ((size_t)(q-p) == keylen) {
+			if (iscasesensitive) {
+				if (memcmp(key, p, keylen) == 0)
+					break; /* match */
+			} else {
+				if (_bcs_strncasecmp(key, p, keylen) == 0)
+					break; /* match */
+			}
+		}
+	}
+
+	p = _bcs_skip_ws_len(q, &len);
+	*rlen = len;
+
+	return (p);
+}
+
+void *
+_citrus_memory_stream_chr(struct _citrus_memory_stream *ms,
+			  struct _citrus_region *r, char ch)
+{
+	void *head, *chr;
+	size_t sz;
+
+	if (ms->ms_pos >= _region_size(&ms->ms_region))
+		return NULL;
+
+	head = _region_offset(&ms->ms_region, ms->ms_pos);
+	chr = memchr(head, ch, _memstream_remainder(ms));
+	if (chr == NULL) {
+		_region_init(r, head, _memstream_remainder(ms));
+		ms->ms_pos = _region_size(&ms->ms_region);
+		return NULL;
+	}
+	sz = (char *)chr - (char *)head;
+
+	_region_init(r, head, sz);
+	ms->ms_pos += sz+1;
+
+	return chr;
+}
+
+void
+_citrus_memory_stream_skip_ws(struct _citrus_memory_stream *ms)
+{
+	int ch;
+
+	while ((ch = _memstream_peek(ms)) != EOF) {
+		if (!_bcs_isspace(ch))
+			break;
+		_memstream_getc(ms);
+	}
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_memstream.h src/sys/kiconv/citrus_memstream.h
--- src.orig/sys/kiconv/citrus_memstream.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_memstream.h	2011-06-03 14:37:47.000000000 +0900
@@ -0,0 +1,213 @@
+/*	$NetBSD: citrus_memstream.h,v 1.3 2005/05/14 17:55:42 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_MEMSTREAM_H_
+#define _CITRUS_MEMSTREAM_H_
+
+struct _citrus_memory_stream {
+	struct _citrus_region	ms_region;
+	size_t			ms_pos;
+};
+
+__BEGIN_DECLS
+const char *	_citrus_memory_stream_getln(
+	struct _citrus_memory_stream * __restrict, size_t * __restrict);
+const char *	_citrus_memory_stream_matchline(
+	struct _citrus_memory_stream * __restrict, const char * __restrict,
+	size_t * __restrict, int);
+void *		_citrus_memory_stream_chr(struct _citrus_memory_stream *,
+					  struct _citrus_region *, char);
+void		_citrus_memory_stream_skip_ws(struct _citrus_memory_stream *);
+__END_DECLS
+
+static __inline int
+_citrus_memory_stream_iseof(struct _citrus_memory_stream *ms)
+{
+	return ms->ms_pos >= _citrus_region_size(&ms->ms_region);
+}
+
+static __inline void
+_citrus_memory_stream_bind(struct _citrus_memory_stream * __restrict ms,
+			   const struct _citrus_region * __restrict r)
+{
+	ms->ms_region = *r;
+	ms->ms_pos = 0;
+}
+
+static __inline void
+_citrus_memory_stream_bind_ptr(struct _citrus_memory_stream * __restrict ms,
+			       void *ptr, size_t sz)
+{
+	struct _citrus_region r;
+
+	_citrus_region_init(&r, ptr, sz);
+	_citrus_memory_stream_bind(ms, &r);
+}
+
+static __inline void
+_citrus_memory_stream_rewind(struct _citrus_memory_stream *ms)
+{
+	ms->ms_pos = 0;
+}
+
+static __inline size_t
+_citrus_memory_stream_tell(struct _citrus_memory_stream *ms)
+{
+	return ms->ms_pos;
+}
+
+static __inline size_t
+_citrus_memory_stream_remainder(struct _citrus_memory_stream *ms)
+{
+	size_t sz;
+	sz = _citrus_region_size(&ms->ms_region);
+	if (ms->ms_pos>sz)
+		return 0;
+	return sz-ms->ms_pos;
+}
+
+static __inline int
+_citrus_memory_stream_seek(struct _citrus_memory_stream *ms, size_t pos, int w)
+{
+	size_t sz = _citrus_region_size(&ms->ms_region);
+	switch (w) {
+	case SEEK_SET:
+		if (pos>=sz)
+			return -1;
+		ms->ms_pos = pos;
+		break;
+	case SEEK_CUR:
+		pos += (ssize_t)ms->ms_pos;
+		if (pos>=sz)
+			return -1;
+		ms->ms_pos = pos;
+		break;
+	case SEEK_END:
+		if (sz<pos)
+			return -1;
+		ms->ms_pos = sz - pos;
+		break;
+	}
+	return 0;
+}
+
+static __inline int
+_citrus_memory_stream_getc(struct _citrus_memory_stream *ms)
+{
+	if (_citrus_memory_stream_iseof(ms))
+		return (EOF);
+	return _citrus_region_peek8(&ms->ms_region, ms->ms_pos++);
+}
+
+static __inline void
+_citrus_memory_stream_ungetc(struct _citrus_memory_stream *ms, int ch)
+{
+	if (ch != EOF && ms->ms_pos > 0)
+		ms->ms_pos--;
+}
+
+static __inline int
+_citrus_memory_stream_peek(struct _citrus_memory_stream *ms)
+{
+	if (_citrus_memory_stream_iseof(ms))
+		return (EOF);
+	return _citrus_region_peek8(&ms->ms_region, ms->ms_pos);
+}
+
+static __inline void *
+_citrus_memory_stream_getregion(struct _citrus_memory_stream *ms,
+				struct _citrus_region *r, size_t sz)
+{
+	void *ret;
+
+	if (ms->ms_pos + sz > _citrus_region_size(&ms->ms_region))
+		return NULL;
+
+	ret = _citrus_region_offset(&ms->ms_region, ms->ms_pos);
+	ms->ms_pos += sz;
+	if (r)
+		_citrus_region_init(r, ret, sz);
+
+	return ret;
+}
+
+static __inline int
+_citrus_memory_stream_get8(struct _citrus_memory_stream *ms, uint8_t *rval)
+{
+
+	if (ms->ms_pos + 1 > _citrus_region_size(&ms->ms_region))
+		return -1;
+
+	*rval = _citrus_region_peek8(&ms->ms_region, ms->ms_pos);
+	ms->ms_pos += 2;
+
+	return 0;
+}
+
+static __inline int
+_citrus_memory_stream_get16(struct _citrus_memory_stream *ms, uint16_t *rval)
+{
+
+	if (ms->ms_pos + 2 > _citrus_region_size(&ms->ms_region))
+		return -1;
+
+	*rval = _citrus_region_peek16(&ms->ms_region, ms->ms_pos);
+	ms->ms_pos += 2;
+
+	return 0;
+}
+
+static __inline int
+_citrus_memory_stream_get32(struct _citrus_memory_stream *ms, uint32_t *rval)
+{
+
+	if (ms->ms_pos + 4 > _citrus_region_size(&ms->ms_region))
+		return -1;
+
+	*rval = _citrus_region_peek32(&ms->ms_region, ms->ms_pos);
+	ms->ms_pos += 4;
+
+	return 0;
+}
+
+static __inline int
+_citrus_memory_stream_getln_region(struct _citrus_memory_stream *ms,
+				   struct _citrus_region *r)
+{
+	const char *ptr;
+	size_t sz;
+
+	ptr = _citrus_memory_stream_getln(ms, &sz);
+	if (ptr)
+		_citrus_region_init(r, __UNCONST(ptr), sz);
+
+	return ptr == NULL;
+}
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_mmap.c src/sys/kiconv/citrus_mmap.c
--- src.orig/sys/kiconv/citrus_mmap.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_mmap.c	2011-06-02 20:01:02.000000000 +0900
@@ -0,0 +1,138 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_mmap.c,v 1.3 2005/01/19 00:52:37 mycroft Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_mmap.c,v 1.3 2005/01/19 00:52:37 mycroft Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/filedesc.h>
+#include <sys/namei.h>
+#include <sys/vnode.h>
+#include <sys/kauth.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <sys/mman.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_mmap.h"
+
+int
+_citrus_map_file(struct _citrus_region * __restrict r,
+    const char * __restrict path)
+{
+	struct pathbuf *pb;
+	struct nameidata nd;
+	struct vattr va;
+	struct vnode *vp;
+	void *head;
+	int error;
+	extern struct cwdinfo cwdi0;
+
+	_DIAGASSERT(r != NULL);
+
+	_region_init(r, NULL, 0);
+
+	if (cwdi0.cwdi_cdir == NULL) {
+		printf("_citrus_map_file(%s)called too early.\n", path);
+		error = ENOENT;
+		goto out;
+	}
+
+	pb = pathbuf_create(path);
+	if (pb == NULL) {
+		error = ENOMEM;
+		goto out;
+	}
+
+	NDINIT(&nd, LOOKUP, FOLLOW | NOCHROOT, pb);
+	error = vn_open(&nd, FREAD, 0);
+	pathbuf_destroy(pb);
+	if (error)
+		goto out;
+
+	vp = nd.ni_vp;
+
+	error = VOP_GETATTR(vp, &va, kauth_cred_get());
+	if (error) {
+		VOP_UNLOCK(vp);
+		goto close;
+	}
+
+	if (va.va_type != VREG) {
+		VOP_UNLOCK(vp);
+		error = EINVAL;
+		goto close;
+	}
+
+	VOP_UNLOCK(vp);
+
+	head = malloc(va.va_size, M_KICONV, M_WAITOK);
+	error = vn_rdwr(UIO_READ, vp, head, va.va_size, 0, UIO_SYSSPACE, 0,
+	    kauth_cred_get(), NULL, curlwp);
+	if (error) {
+		free(head, M_KICONV);
+		goto close;
+	}
+	_region_init(r, head, va.va_size);
+
+close:
+	(void)vn_close(vp, FREAD, kauth_cred_get());
+out:
+	return error;
+}
+
+void
+_citrus_unmap_file(struct _citrus_region *r)
+{
+
+	_DIAGASSERT(r != NULL);
+
+	if (_region_head(r)) {
+		free(_region_head(r), M_KICONV);
+		_region_init(r, NULL, 0);
+	}
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_mmap.h src/sys/kiconv/citrus_mmap.h
--- src.orig/sys/kiconv/citrus_mmap.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_mmap.h	2011-06-03 14:37:47.000000000 +0900
@@ -0,0 +1,39 @@
+/*	$NetBSD: citrus_mmap.h,v 1.1 2003/06/25 09:51:38 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_MMAP_H_
+#define _CITRUS_MMAP_H_
+
+__BEGIN_DECLS
+int _citrus_map_file(struct _citrus_region * __restrict,
+		     const char * __restrict);
+void _citrus_unmap_file(struct _citrus_region *);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_module.c src/sys/kiconv/citrus_module.c
--- src.orig/sys/kiconv/citrus_module.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_module.c	2011-06-03 21:16:09.000000000 +0900
@@ -0,0 +1,114 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by NONAKA Kimihiro.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/namei.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+
+#include "citrus_namespace.h"
+#include "citrus_module.h"
+
+void *
+_citrus_find_getops(_citrus_module_t handle, const char *modname,
+		    const char *ifname)
+{
+	struct kiconv_getops *getops;
+	char *name;
+
+	KDASSERT(modname != NULL);
+	KDASSERT(ifname != NULL);
+
+	name = PNBUF_GET();
+	KASSERT(name != NULL);
+	snprintf(name, PATH_MAX, "%s_%s", modname, ifname);
+	getops = kiconv_find_getops(name);
+	PNBUF_PUT(name);
+
+	return getops->kg_getops;
+}
+
+int
+_citrus_load_module(_citrus_module_t *rhandle, const char *encname)
+{
+	char *modname;
+	int error;
+
+	KDASSERT(rhandle != NULL);
+	KDASSERT(encname != NULL);
+
+	modname = malloc(MAXMODNAME, M_KICONV, M_WAITOK);
+	snprintf(modname, MAXMODNAME, "kiconv_%s", encname);
+
+#if 0
+	error = module_hold(modname);
+	if (error) {
+		if (error != ENOENT)
+			goto error;
+
+		error = module_autoload(modname, MODULE_CLASS_MISC);
+		if (error != 0 && error != EEXIST)
+			goto error;
+		error = module_hold(modname);
+		if (error)
+			goto error;
+	}
+#else
+	error = module_autoload(modname, MODULE_CLASS_MISC);
+	if (error != 0 && error != EEXIST)
+		goto error;
+#endif
+
+	*rhandle = (_citrus_module_t)modname;
+	return 0;
+
+error:
+	printf("kiconv: couldn't load module (%s)\n", modname);
+	free(modname, M_KICONV);
+	return error;
+}
+
+void
+_citrus_unload_module(_citrus_module_t handle)
+{
+
+	if (handle) {
+#if 0
+		(void)module_rele((const char *)handle);
+#endif
+		free(handle, M_KICONV);
+	}
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_module.h src/sys/kiconv/citrus_module.h
--- src.orig/sys/kiconv/citrus_module.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_module.h	2011-06-03 14:22:56.000000000 +0900
@@ -0,0 +1,43 @@
+/*	$NetBSD: citrus_module.h,v 1.1 2002/03/17 22:14:20 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_MODULE_H_
+#define _CITRUS_MODULE_H_
+
+typedef struct _citrus_module_rec *_citrus_module_t;
+
+__BEGIN_DECLS
+void *_citrus_find_getops(_citrus_module_t __restrict,
+			  const char * __restrict, const char * __restrict);
+int _citrus_load_module(_citrus_module_t * __restrict,
+			const char * __restrict);
+void _citrus_unload_module(_citrus_module_t);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_namespace.h src/sys/kiconv/citrus_namespace.h
--- src.orig/sys/kiconv/citrus_namespace.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_namespace.h	2011-06-03 14:37:04.000000000 +0900
@@ -0,0 +1,238 @@
+/*	$NetBSD: citrus_namespace.h,v 1.8 2009/01/11 02:46:24 christos Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_NAMESPACE_H_
+#define _CITRUS_NAMESPACE_H_
+
+/* citrus_alias */
+#ifndef _CITRUS_ALIAS_NO_NAMESPACE
+#define _alias_lookup		_citrus_alias_lookup
+#endif /* _CITRUS_ALIAS_NO_NAMESPACE */
+
+/* citrus_bcs */
+#ifndef _CITRUS_BCS_NO_NAMESPACE
+#define _bcs_isalnum		_citrus_bcs_isalnum
+#define _bcs_isalpha		_citrus_bcs_isalpha
+#define _bcs_isblank		_citrus_bcs_isblank
+#define _bcs_isdigit		_citrus_bcs_isdigit
+#define _bcs_islower		_citrus_bcs_islower
+#define _bcs_iseol		_citrus_bcs_iseol
+#define _bcs_isspace		_citrus_bcs_isspace
+#define _bcs_isupper		_citrus_bcs_isupper
+#define _bcs_isxdigit		_citrus_bcs_isxdigit
+#define _bcs_skip_nonws		_citrus_bcs_skip_nonws
+#define _bcs_skip_nonws_len	_citrus_bcs_skip_nonws_len
+#define _bcs_skip_ws		_citrus_bcs_skip_ws
+#define _bcs_skip_ws_len	_citrus_bcs_skip_ws_len
+#define _bcs_strcasecmp		_citrus_bcs_strcasecmp
+#define _bcs_strncasecmp	_citrus_bcs_strncasecmp
+#define _bcs_tolower		_citrus_bcs_tolower
+#define _bcs_toupper		_citrus_bcs_toupper
+#define _bcs_trunc_rws_len	_citrus_bcs_trunc_rws_len
+#define _bcs_convert_to_lower	_citrus_bcs_convert_to_lower
+#define _bcs_convert_to_upper	_citrus_bcs_convert_to_upper
+#define _bcs_strtol		_citrus_bcs_strtol
+#define _bcs_strtoul		_citrus_bcs_strtoul
+#endif /* _CITRUS_BCS_NO_NAMESPACE */
+
+/* citrus_csmapper */
+#ifndef _CITRUS_CSMAPPER_NO_NAMESPACE
+#define _csmapper		_citrus_csmapper
+#define _csmapper_open		_citrus_csmapper_open
+#define _csmapper_close		_citrus_csmapper_close
+#define _csmapper_convert	_citrus_csmapper_convert
+#define _csmapper_init_state	_citrus_csmapper_init_state
+#define _csmapper_get_state_size _citrus_csmapper_get_state_size
+#define _csmapper_get_src_max	_citrus_csmapper_get_src_max
+#define _csmapper_get_dst_max	_citrus_csmapper_get_dst_max
+#define _CSMAPPER_F_PREVENT_PIVOT _CITRUS_CSMAPPER_F_PREVENT_PIVOT
+#endif /* _CITRUS_CSMAPPER_NO_NAMESPACE */
+
+/* citrus_db */
+#ifndef _CITRUS_DB_NO_NAMESPACE
+#define _db_open		_citrus_db_open
+#define _db_close		_citrus_db_close
+#define _db_lookup		_citrus_db_lookup
+#define _db_lookup_by_s		_citrus_db_lookup_by_string
+#define _db_lookup8_by_s	_citrus_db_lookup8_by_string
+#define _db_lookup16_by_s	_citrus_db_lookup16_by_string
+#define _db_lookup32_by_s	_citrus_db_lookup32_by_string
+#define _db_lookupstr_by_s	_citrus_db_lookup_string_by_string
+#define _db_hash_std		_citrus_db_hash_std
+#define _db_get_num_entries	_citrus_db_get_number_of_entries
+#define _db_get_entry		_citrus_db_get_entry
+#define _db_locator		_citrus_db_locator
+#define _db_locator_init	_citrus_db_locator_init
+#endif /* _CITRUS_DB_NO_NAMESPACE */
+
+/* citrus_db_factory */
+#ifndef _CITRUS_DB_FACTORY_NO_NAMESPACE
+#define _db_factory		_citrus_db_factory
+#define _db_factory_create	_citrus_db_factory_create
+#define _db_factory_free	_citrus_db_factory_free
+#define _db_factory_add		_citrus_db_factory_add
+#define _db_factory_add_by_s	_citrus_db_factory_add_by_string
+#define _db_factory_add8_by_s	_citrus_db_factory_add8_by_string
+#define _db_factory_add16_by_s	_citrus_db_factory_add16_by_string
+#define _db_factory_add32_by_s	_citrus_db_factory_add32_by_string
+#define _db_factory_addstr_by_s	_citrus_db_factory_add_string_by_string
+#define _db_factory_calc_size	_citrus_db_factory_calc_size
+#define _db_factory_serialize	_citrus_db_factory_serialize
+#endif /* _CITRUS_DB_FACTORY_NO_NAMESPACE */
+
+/* citrus_lookup */
+#ifndef _CITRUS_DB_NO_NAMESPACE
+#define _LOOKUP_CASE_SENSITIVE	_CITRUS_LOOKUP_CASE_SENSITIVE
+#define _LOOKUP_CASE_IGNORE	_CITRUS_LOOKUP_CASE_IGNORE
+#define _lookup			_citrus_lookup
+#define _lookup_simple		_citrus_lookup_simple
+#define _lookup_alias		_citrus_lookup_alias
+#define _lookup_seq_open	_citrus_lookup_seq_open
+#define _lookup_seq_rewind	_citrus_lookup_seq_rewind
+#define _lookup_seq_next	_citrus_lookup_seq_next
+#define _lookup_seq_lookup	_citrus_lookup_seq_lookup
+#define _lookup_get_num_entries	_citrus_lookup_get_number_of_entries
+#define _lookup_seq_close	_citrus_lookup_seq_close
+#define _lookup_factory_convert	_citrus_lookup_factory_convert
+#endif /* _CITRUS_DB_NO_NAMESPACE */
+
+/* citrus_esdb */
+#ifndef _CITRUS_ESDB_NO_NAMESPACE
+#define _esdb			_citrus_esdb
+#define _esdb_charset		_citrus_esdb_charset
+#define _esdb_open		_citrus_esdb_open
+#define _esdb_close		_citrus_esdb_close
+#define _esdb_get_list		_citrus_esdb_get_list
+#define _esdb_free_list		_citrus_esdb_free_list
+#endif /* _CITRUS_ESDB_NO_NAMESPACE */
+
+/* citrus_hash */
+#ifndef _CITRUS_HASH_NO_NAMESPACE
+#define _citrus_string_hash_func _string_hash_func
+#endif /* _CITRUS_HASH_NO_NAMESPACE */
+
+/* citrus_mapper */
+#ifndef _CITRUS_MAPPER_NO_NAMESPACE
+#define _mapper			_citrus_mapper
+#define _mapper_ops		_citrus_mapper_ops
+#define _mapper_traits		_citrus_mapper_traits
+#define _mapper_open		_citrus_mapper_open
+#define _mapper_open_direct	_citrus_mapper_open_direct
+#define _mapper_close		_citrus_mapper_close
+#define _MAPPER_CONVERT_SUCCESS	_CITRUS_MAPPER_CONVERT_SUCCESS
+#define _MAPPER_CONVERT_NONIDENTICAL _CITRUS_MAPPER_CONVERT_NONIDENTICAL
+#define _MAPPER_CONVERT_SRC_MORE _CITRUS_MAPPER_CONVERT_SRC_MORE
+#define _MAPPER_CONVERT_DST_MORE _CITRUS_MAPPER_CONVERT_DST_MORE
+#define _MAPPER_CONVERT_ILSEQ	_CITRUS_MAPPER_CONVERT_ILSEQ
+#define _MAPPER_CONVERT_FATAL	_CITRUS_MAPPER_CONVERT_FATAL
+#define _mapper_convert		_citrus_mapper_convert
+#define _mapper_init_state	_citrus_mapper_init_state
+#define _mapper_get_state_size	_citrus_mapper_get_state_size
+#define _mapper_get_src_max	_citrus_mapper_get_src_max
+#define _mapper_get_dst_max	_citrus_mapper_get_dst_max
+#define _mapper_set_persistent	_citrus_mapper_set_persistent
+#endif /* _CITRUS_MAPPER_NO_NAMESPACE */
+
+/* citrus_memstream */
+#ifndef _CITRUS_MEMSTREAM_NO_NAMESPACE
+#define _memstream		_citrus_memory_stream
+#define _memstream_getln	_citrus_memory_stream_getln
+#define _memstream_matchline	_citrus_memory_stream_matchline
+#define _memstream_chr		_citrus_memory_stream_chr
+#define _memstream_skip_ws	_citrus_memory_stream_skip_ws
+#define _memstream_iseof	_citrus_memory_stream_iseof
+#define _memstream_bind		_citrus_memory_stream_bind
+#define _memstream_bind_ptr	_citrus_memory_stream_bind_ptr
+#define _memstream_seek		_citrus_memory_stream_seek
+#define _memstream_rewind	_citrus_memory_stream_rewind
+#define _memstream_tell		_citrus_memory_stream_tell
+#define _memstream_remainder	_citrus_memory_stream_remainder
+#define _memstream_getc		_citrus_memory_stream_getc
+#define _memstream_ungetc	_citrus_memory_stream_ungetc
+#define _memstream_peek		_citrus_memory_stream_peek
+#define _memstream_getregion	_citrus_memory_stream_getregion
+#define _memstream_getln_region	_citrus_memory_stream_getln_region
+#endif /* _CITRUS_MEMSTREAM_NO_NAMESPACE */
+
+/* citrus_mmap */
+#ifndef _CITRUS_MMAP_NO_NAMESPACE
+#define _map_file		_citrus_map_file
+#define _unmap_file		_citrus_unmap_file
+#endif /* _CITRUS_MMAP_NO_NAMESPACE */
+
+#ifndef _CITRUS_PIVOT_NO_NAMESPACE
+#define _pivot_factory_convert	_citrus_pivot_factory_convert
+#endif /* _CITRUS_PIVOT_NO_NAMESPACE */
+
+/* citrus_region.h */
+#ifndef _CITRUS_REGION_NO_NAMESPACE
+#define _region			_citrus_region
+#define _region_init		_citrus_region_init
+#define _region_head		_citrus_region_head
+#define _region_size		_citrus_region_size
+#define _region_check		_citrus_region_check
+#define _region_offset		_citrus_region_offset
+#define _region_peek8		_citrus_region_peek8
+#define _region_peek16		_citrus_region_peek16
+#define _region_peek32		_citrus_region_peek32
+#define _region_get_subregion	_citrus_region_get_subregion
+#endif /* _CITRUS_REGION_NO_NAMESPACE */
+
+/* citrus_stdenc.h */
+#ifndef _CITRUS_STDENC_NO_NAMESPACE
+#define _stdenc			_citrus_stdenc
+#define _stdenc_ops		_citrus_stdenc_ops
+#define _stdenc_traits		_citrus_stdenc_traits
+#define _stdenc_state_desc	_citrus_stdenc_state_desc
+#define _stdenc_open		_citrus_stdenc_open
+#define _stdenc_close		_citrus_stdenc_close
+#define _stdenc_init_state	_citrus_stdenc_init_state
+#define _stdenc_mbtocs		_citrus_stdenc_mbtocs
+#define _stdenc_cstomb		_citrus_stdenc_cstomb
+#define _stdenc_mbtowc		_citrus_stdenc_mbtowc
+#define _stdenc_wctomb		_citrus_stdenc_wctomb
+#define _stdenc_put_state_reset	_citrus_stdenc_put_state_reset
+#define _stdenc_get_state_size	_citrus_stdenc_get_state_size
+#define _stdenc_get_mb_cur_max	_citrus_stdenc_get_mb_cur_max
+#define _stdenc_get_state_desc	_citrus_stdenc_get_state_desc
+#define _STDENC_SDID_GENERIC	_CITRUS_STDENC_SDID_GENERIC
+#define _STDENC_SDGEN_UNKNOWN	_CITRUS_STDENC_SDGEN_UNKNOWN
+#define _STDENC_SDGEN_INITIAL	_CITRUS_STDENC_SDGEN_INITIAL
+#define _STDENC_SDGEN_STABLE	_CITRUS_STDENC_SDGEN_STABLE
+#define _STDENC_SDGEN_INCOMPLETE_CHAR _CITRUS_STDENC_SDGEN_INCOMPLETE_CHAR
+#define _STDENC_SDGEN_INCOMPLETE_SHIFT _CITRUS_STDENC_SDGEN_INCOMPLETE_SHIFT
+#endif /* _CITRUS_STDENC_NO_NAMESPACE */
+
+/* citrus_types.h */
+#ifndef _CITRUS_TYPES_NO_NAMESPACE
+#define _index_t		_citrus_index_t
+#define _csid_t			_citrus_csid_t
+#define _wc_t			_citrus_wc_t
+#endif /* _CITRUS_TYPES_NO_NAMESPACE */
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_none.c src/sys/kiconv/citrus_none.c
--- src.orig/sys/kiconv/citrus_none.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_none.c	2011-06-02 19:57:45.000000000 +0900
@@ -0,0 +1,512 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <sys/types.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_none.h"
+#include "citrus_stdenc.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_CTYPE_DECLS(NONE);
+_CITRUS_CTYPE_DEF_OPS(NONE);
+
+
+/* ---------------------------------------------------------------------- */
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_init(void ** __restrict cl, void * __restrict var,
+			size_t lenvar, size_t lenps)
+{
+	*cl = NULL;
+	return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_NONE_ctype_uninit(void *cl)
+{
+}
+
+static unsigned
+/*ARGSUSED*/
+_citrus_NONE_ctype_get_mb_cur_max(void *cl)
+{
+	return (1);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_mblen(void * __restrict cl, const char * __restrict s,
+			 size_t n, int * __restrict nresult)
+{
+	if (!s) {
+		*nresult = 0; /* state independent */
+		return (0);
+	}
+	if (n==0) {
+		*nresult = -1;
+		return (EILSEQ);
+	}
+	*nresult = (*s == 0) ? 0 : 1;
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_mbrlen(void * __restrict cl, const char * __restrict s,
+			  size_t n, void * __restrict pspriv,
+			  size_t * __restrict nresult)
+{
+	if (!s) {
+		*nresult = 0;
+		return (0);
+	}
+	if (n==0) {
+		*nresult = (size_t)-2;
+		return (0);
+	}
+	*nresult = (*s == 0) ? 0 : 1;
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_mbrtowc(void * __restrict cl, wchar_t * __restrict pwc,
+			   const char * __restrict s, size_t n,
+			   void * __restrict pspriv,
+			   size_t * __restrict nresult)
+{
+	if (s == NULL) {
+		*nresult = 0;
+		return (0);
+	}
+	if (n == 0) {
+		*nresult = (size_t)-2;
+		return (0);
+	}
+
+	if (pwc != NULL)
+		*pwc = (wchar_t)(unsigned char) *s;
+
+	*nresult = *s == '\0' ? 0 : 1;
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_mbsinit(void * __restrict cl,
+			   const void * __restrict pspriv,
+			   int * __restrict nresult)
+{
+	*nresult = 1;  /* always initial state */
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_mbsrtowcs(void * __restrict cl, wchar_t * __restrict pwcs,
+			     const char ** __restrict s, size_t n,
+			     void * __restrict pspriv,
+			     size_t * __restrict nresult)
+{
+	int cnt;
+	const char *s0;
+
+	/* if pwcs is NULL, ignore n */
+	if (pwcs == NULL)
+		n = 1; /* arbitrary >0 value */
+
+	cnt = 0;
+	s0 = *s; /* to keep *s unchanged for now, use copy instead. */
+	while (n > 0) {
+		if (pwcs != NULL) {
+			*pwcs = (wchar_t)(unsigned char)*s0;
+		}
+		if (*s0 == '\0') {
+			s0 = NULL;
+			break;
+		}
+		s0++;
+		if (pwcs != NULL) {
+			pwcs++;
+			n--;
+		}
+		cnt++;
+	}
+	if (pwcs)
+		*s = s0;
+
+	*nresult = (size_t)cnt;
+
+	return (0);
+}
+
+static int
+_citrus_NONE_ctype_mbstowcs(void * __restrict cl, wchar_t * __restrict wcs,
+			    const char * __restrict s, size_t n,
+			    size_t * __restrict nresult)
+{
+	const char *rs = s;
+
+	return (_citrus_NONE_ctype_mbsrtowcs(cl, wcs, &rs, n, NULL, nresult));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_mbtowc(void * __restrict cl, wchar_t * __restrict pwc,
+			  const char * __restrict s, size_t n,
+			  int * __restrict nresult)
+{
+
+	if (s == NULL) {
+		*nresult = 0; /* state independent */
+		return (0);
+	}
+	if (n == 0) {
+		return (EILSEQ);
+	}
+	if (pwc == NULL) {
+		if (*s == '\0') {
+			*nresult = 0;
+		} else {
+			*nresult = 1;
+		}
+		return (0);
+	}
+
+	*pwc = (wchar_t)(unsigned char)*s;
+	*nresult = *s == '\0' ? 0 : 1;
+
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_wcrtomb(void * __restrict cl, char * __restrict s,
+			   wchar_t wc, void * __restrict pspriv,
+			   size_t * __restrict nresult)
+{
+	if ((wc&~0xFFU) != 0) {
+		*nresult = (size_t)-1;
+		return (EILSEQ);
+	}
+
+	*nresult = 1;
+	if (s!=NULL)
+		*s = (char)wc;
+
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_wcsrtombs(void * __restrict cl, char * __restrict s,
+			     const wchar_t ** __restrict pwcs, size_t n,
+			     void * __restrict pspriv,
+			     size_t * __restrict nresult)
+{
+	size_t count;
+	const wchar_t *pwcs0;
+
+	pwcs0 = *pwcs;
+	count = 0;
+
+	if (s == NULL)
+		n = 1;
+
+	while (n > 0) {
+		if ((*pwcs0 & ~0xFFU) != 0) {
+			*nresult = (size_t)-1;
+			return (EILSEQ);
+		}
+		if (s != NULL) {
+			*s++ = (char)*pwcs0;
+			n--;
+		}
+		if (*pwcs0 == L'\0') {
+			pwcs0 = NULL;
+			break;
+		}
+		count++;
+		pwcs0++;
+	}
+	if (s != NULL)
+		*pwcs = pwcs0;
+
+	*nresult = count;
+
+	return (0);
+}
+
+static int
+_citrus_NONE_ctype_wcstombs(void * __restrict cl, char * __restrict s,
+			    const wchar_t * __restrict pwcs, size_t n,
+			    size_t * __restrict nresult)
+{
+	const wchar_t *rpwcs = pwcs;
+
+	return (_citrus_NONE_ctype_wcsrtombs(cl, s, &rpwcs, n, NULL, nresult));
+}
+
+static int
+_citrus_NONE_ctype_wctomb(void * __restrict cl, char * __restrict s,
+			  wchar_t wc, int * __restrict nresult)
+{
+	int ret;
+	size_t nr;
+
+	if (s == 0) {
+		/*
+		 * initialize state here.
+		 * (nothing to do for us.)
+		 */
+		*nresult = 0; /* we're state independent */
+		return (0);
+	}
+
+	ret = _citrus_NONE_ctype_wcrtomb(cl, s, wc, NULL, &nr);
+	*nresult = (int)nr;
+
+	return (ret);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_btowc(_citrus_ctype_rec_t * __restrict cc,
+			 int c, wint_t * __restrict wcresult)
+{
+	if (c == EOF || c & ~0xFF)
+		*wcresult = WEOF;
+	else
+		*wcresult = (wint_t)c;
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_ctype_wctob(_citrus_ctype_rec_t * __restrict cc,
+			 wint_t wc, int * __restrict cresult)
+{
+	if (wc == WEOF || wc & ~0xFF)
+		*cresult = EOF;
+	else
+		*cresult = (int)wc;
+	return (0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_STDENC_DECLS(NONE);
+_CITRUS_STDENC_DEF_OPS(NONE);
+struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits = {
+	0,	/* et_state_size */
+	1,	/* mb_cur_max */
+};
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_stdenc_init(struct _citrus_stdenc * __restrict ce,
+			 const void *var, size_t lenvar,
+			 struct _citrus_stdenc_traits * __restrict et)
+{
+
+	et->et_state_size = 0;
+	et->et_mb_cur_max = 1;
+
+	ce->ce_closure = NULL;
+
+	return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_NONE_stdenc_uninit(struct _citrus_stdenc *ce)
+{
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_stdenc_init_state(struct _citrus_stdenc * __restrict ce,
+			       void * __restrict ps)
+{
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce,
+			   _csid_t *csid, _index_t *idx,
+			   const char **s, size_t n,
+			   void *ps, size_t *nresult)
+{
+
+	_DIAGASSERT(csid != NULL && idx != NULL);
+
+	if (n<1) {
+		*nresult = (size_t)-2;
+		return (0);
+	}
+
+	*csid = 0;
+	*idx = (_index_t)(unsigned char)*(*s)++;
+	*nresult = *idx == 0 ? 0 : 1;
+
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_stdenc_cstomb(struct _citrus_stdenc * __restrict ce,
+			   char *s, size_t n,
+			   _csid_t csid, _index_t idx,
+			   void *ps, size_t *nresult)
+{
+
+	if (csid == _CITRUS_CSID_INVALID) {
+		*nresult = 0;
+		return (0);
+	}
+	if (n<1) {
+		*nresult = (size_t)-1;
+		return (E2BIG);
+	}
+	if (csid != 0 || (idx&0xFF) != idx)
+		return (EILSEQ);
+
+	*s = (char)idx;
+	*nresult = 1;
+
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce,
+			   _wc_t * __restrict pwc,
+			   const char ** __restrict s, size_t n,
+			   void * __restrict pspriv,
+			   size_t * __restrict nresult)
+{
+	if (s == NULL) {
+		*nresult = 0;
+		return (0);
+	}
+	if (n == 0) {
+		*nresult = (size_t)-2;
+		return (0);
+	}
+
+	if (pwc != NULL)
+		*pwc = (_wc_t)(unsigned char) **s;
+
+	*nresult = *s == '\0' ? 0 : 1;
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce,
+			   char * __restrict s, size_t n,
+			   _wc_t wc, void * __restrict pspriv,
+			   size_t * __restrict nresult)
+{
+	if ((wc&~0xFFU) != 0) {
+		*nresult = (size_t)-1;
+		return (EILSEQ);
+	}
+	if (n==0) {
+		*nresult = (size_t)-1;
+		return (E2BIG);
+	}
+
+	*nresult = 1;
+	if (s!=NULL && n>0)
+		*s = (char)wc;
+
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce,
+				    char * __restrict s, size_t n,
+				    void * __restrict pspriv,
+				    size_t * __restrict nresult)
+{
+
+	*nresult = 0;
+
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_NONE_stdenc_get_state_desc(struct _stdenc * __restrict ce,
+				   void * __restrict ps,
+				   int id,
+				   struct _stdenc_state_desc * __restrict d)
+{
+	int ret = 0;
+
+	switch (id) {
+	case _STDENC_SDID_GENERIC:
+		d->u.generic.state = _STDENC_SDGEN_INITIAL;
+		break;
+	default:
+		ret = EOPNOTSUPP;
+	}
+
+	return ret;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_none.h src/sys/kiconv/citrus_none.h
--- src.orig/sys/kiconv/citrus_none.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_none.h	2011-06-03 14:38:40.000000000 +0900
@@ -0,0 +1,36 @@
+/*	$NetBSD: citrus_none.h,v 1.3 2003/06/25 09:51:38 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_NONE_H_
+#define _CITRUS_NONE_H_
+
+extern struct _citrus_ctype_ops_rec	_citrus_NONE_ctype_ops;
+extern struct _citrus_stdenc_ops	_citrus_NONE_stdenc_ops;
+extern struct _citrus_stdenc_traits	_citrus_NONE_stdenc_traits;
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_pivot_file.h src/sys/kiconv/citrus_pivot_file.h
--- src.orig/sys/kiconv/citrus_pivot_file.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_pivot_file.h	2011-06-03 14:37:47.000000000 +0900
@@ -0,0 +1,35 @@
+/*	$NetBSD: citrus_pivot_file.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_PIVOT_FILE_H_
+#define _CITRUS_PIVOT_FILE_H_
+
+#define _CITRUS_PIVOT_MAGIC	"CSPIVOT\0"
+#define _CITRUS_PIVOT_SUB_MAGIC	"CSPIVSUB"
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_prop.c src/sys/kiconv/citrus_prop.c
--- src.orig/sys/kiconv/citrus_prop.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_prop.c	2011-06-08 12:52:11.000000000 +0900
@@ -0,0 +1,472 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_prop.c,v 1.4 2011/03/30 08:22:01 jruoho Exp */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_prop.c,v 1.4 2011/03/30 08:22:01 jruoho Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_prop.h"
+
+typedef struct {
+	_citrus_prop_type_t type;
+	union {
+		const char *str;
+		int chr;
+		bool boolean;
+		uint64_t num;
+	} u;
+} _citrus_prop_object_t;
+
+static __inline void
+_citrus_prop_object_init(_citrus_prop_object_t *obj, _citrus_prop_type_t type)
+{
+	_DIAGASSERT(obj != NULL);
+
+	obj->type = type;
+	memset(&obj->u, 0, sizeof(obj->u));
+}
+
+static __inline void
+_citrus_prop_object_uninit(_citrus_prop_object_t *obj)
+{
+	_DIAGASSERT(obj != NULL);
+
+	if (obj->type == _CITRUS_PROP_STR)
+		free(__UNCONST(obj->u.str), M_KICONV);
+}
+
+static const char *xdigit = "0123456789ABCDEF";
+
+#define _CITRUS_PROP_READ_UINT_COMMON(_func_, _type_, _max_)		\
+static int								\
+_citrus_prop_read_##_func_##_common(struct _memstream * __restrict ms,	\
+	_type_ * __restrict result, int base)				\
+{									\
+	_type_ acc, cutoff;						\
+	int n, ch, cutlim;						\
+	char *p;							\
+									\
+	_DIAGASSERT(ms != NULL);					\
+	_DIAGASSERT(result != NULL);					\
+									\
+	acc = (_type_)0;						\
+	cutoff = _max_ / base;						\
+	cutlim = _max_ % base;						\
+	for (;;) {							\
+		ch = _memstream_getc(ms);				\
+		p = strchr(xdigit, _bcs_toupper(ch));			\
+		if (p == NULL || (n = (p - xdigit)) >= base)		\
+			break;						\
+		if (acc > cutoff || (acc == cutoff && n > cutlim))	\
+			break;						\
+		acc *= base;						\
+		acc += n;						\
+	}								\
+	_memstream_ungetc(ms, ch);					\
+	*result = acc;							\
+	return 0;							\
+}
+_CITRUS_PROP_READ_UINT_COMMON(chr, int, UCHAR_MAX)
+_CITRUS_PROP_READ_UINT_COMMON(num, uint64_t, UINT64_MAX)
+#undef _CITRUS_PROP_READ_UINT_COMMON
+
+#define _CITRUS_PROP_READ_INT(_func_, _type_)			\
+static int							\
+_citrus_prop_read_##_func_(struct _memstream * __restrict ms,	\
+	_citrus_prop_object_t * __restrict obj)			\
+{								\
+	int ch, neg, base;					\
+								\
+	_DIAGASSERT(ms != NULL);				\
+	_DIAGASSERT(obj != NULL);				\
+								\
+	_memstream_skip_ws(ms);					\
+	ch = _memstream_getc(ms);				\
+	neg = 0;						\
+	switch (ch) {						\
+	case '-':						\
+		neg = 1;					\
+	case '+':						\
+		ch = _memstream_getc(ms);			\
+	}							\
+	base = 10;						\
+	if (ch == '0') {					\
+		base -= 2;					\
+		ch = _memstream_getc(ms);			\
+		if (ch == 'x' || ch == 'X') {			\
+			ch = _memstream_getc(ms);		\
+			if (_bcs_isxdigit(ch) == 0) {		\
+				_memstream_ungetc(ms, ch);	\
+				obj->u._func_ = 0;		\
+				return 0;			\
+			}					\
+			base += 8;				\
+		}						\
+	} else if (_bcs_isdigit(ch) == 0)			\
+		return EINVAL;					\
+	_memstream_ungetc(ms, ch);				\
+	return _citrus_prop_read_##_func_##_common		\
+	    (ms, &obj->u._func_, base);				\
+}
+_CITRUS_PROP_READ_INT(chr, int)
+_CITRUS_PROP_READ_INT(num, uint64_t)
+#undef _CITRUS_PROP_READ_INT
+
+static int
+_citrus_prop_read_character_common(struct _memstream * __restrict ms,
+	int * __restrict result)
+{
+	int ch, base;
+
+	_DIAGASSERT(ms != NULL);
+	_DIAGASSERT(result != NULL);
+
+	ch = _memstream_getc(ms);
+	if (ch != '\\') {
+		*result = ch;
+	} else {
+		ch = _memstream_getc(ms);
+		base = 16;
+		switch (ch) {
+		case 'a': *result = '\a'; break;
+		case 'b': *result = '\b'; break;
+		case 'f': *result = '\f'; break;
+		case 'n': *result = '\n'; break;
+		case 'r': *result = '\r'; break;
+		case 't': *result = '\t'; break;
+		case 'v': *result = '\v'; break;
+		/*FALLTHROUGH*/
+		case '0': case '1': case '2': case '3':
+		case '4': case '5': case '6': case '7':
+			_memstream_ungetc(ms, ch);
+			base -= 8;
+		case 'x':
+			return _citrus_prop_read_chr_common(ms, result, base);
+			
+		default:
+			/* unknown escape */
+			*result = ch;
+		}
+	}
+	return 0;
+}
+
+static int
+_citrus_prop_read_character(struct _memstream * __restrict ms,
+	_citrus_prop_object_t * __restrict obj)
+{
+	int ch, errnum;
+
+	_DIAGASSERT(ms != NULL);
+	_DIAGASSERT(obj != NULL);
+
+	_memstream_skip_ws(ms);
+	ch = _memstream_getc(ms);
+	if (ch != '\'') {
+		_memstream_ungetc(ms, ch);
+		return _citrus_prop_read_chr(ms, obj);
+	}
+	errnum = _citrus_prop_read_character_common(ms, &ch);
+	if (errnum != 0)
+		return errnum;
+	obj->u.chr = ch;
+	ch = _memstream_getc(ms);
+	if (ch != '\'')
+		return EINVAL;
+	return 0;
+}
+
+static int
+_citrus_prop_read_bool(struct _memstream * __restrict ms,
+	_citrus_prop_object_t * __restrict obj)
+{
+	_DIAGASSERT(ms != NULL);
+	_DIAGASSERT(obj != NULL);
+
+	_memstream_skip_ws(ms);
+	switch (_bcs_tolower(_memstream_getc(ms))) {
+	case 't':
+		if (_bcs_tolower(_memstream_getc(ms)) == 'r' &&
+		    _bcs_tolower(_memstream_getc(ms)) == 'u' &&
+		    _bcs_tolower(_memstream_getc(ms)) == 'e') {
+			obj->u.boolean = true;
+			return 0;
+		}
+		break;
+	case 'f':
+		if (_bcs_tolower(_memstream_getc(ms)) == 'a' &&
+		    _bcs_tolower(_memstream_getc(ms)) == 'l' &&
+		    _bcs_tolower(_memstream_getc(ms)) == 's' &&
+		    _bcs_tolower(_memstream_getc(ms)) == 'e') {
+			obj->u.boolean = false;
+			return 0;
+		}
+	}
+	return EINVAL;
+}
+
+static int
+_citrus_prop_read_str(struct _memstream * __restrict ms,
+	_citrus_prop_object_t * __restrict obj)
+{
+	int errnum, quot, ch;
+	char *s, *t;
+#define _CITRUS_PROP_STR_BUFSIZ	512
+	size_t n, m;
+
+	_DIAGASSERT(ms != NULL);
+	_DIAGASSERT(obj != NULL);
+
+	m = _CITRUS_PROP_STR_BUFSIZ;
+	s = malloc(m, M_KICONV, M_WAITOK);
+	n = 0;
+	_memstream_skip_ws(ms);
+	quot = _memstream_getc(ms);
+	switch (quot) {
+	case EOF:
+		goto done;
+	case '\\':
+		_memstream_ungetc(ms, quot);
+		quot = EOF;
+	/*FALLTHROUGH*/
+	case '\"': case '\'':
+		break;
+	default:
+		s[n] = quot;
+		++n, --m;
+		quot = EOF;
+	}
+	for (;;) {
+		if (m < 1) {
+			m = _CITRUS_PROP_STR_BUFSIZ;
+			t = realloc(s, n + m, M_KICONV, M_WAITOK);
+			s = t;
+		}
+		ch = _memstream_getc(ms);
+		if (quot == ch || (quot == EOF &&
+		    (ch == ';' || _bcs_isspace(ch)))) {
+done:
+			s[n] = '\0';
+			obj->u.str = (const char *)s;
+			return 0;
+		}
+		_memstream_ungetc(ms, ch);
+		errnum = _citrus_prop_read_character_common(ms, &ch);
+		if (errnum != 0)
+			return errnum;
+		s[n] = ch;
+		++n, --m;
+	}
+	free(s, M_KICONV);
+	return EINVAL;
+#undef _CITRUS_PROP_STR_BUFSIZ
+}
+
+typedef int (*_citrus_prop_read_type_t)(struct _memstream * __restrict,
+	_citrus_prop_object_t * __restrict);
+
+static const _citrus_prop_read_type_t readers[] = {
+	_citrus_prop_read_bool,
+	_citrus_prop_read_str,
+	_citrus_prop_read_character,
+	_citrus_prop_read_num,
+};
+
+static __inline int
+_citrus_prop_read_symbol(struct _memstream * __restrict ms,
+	char * __restrict s, size_t n)
+{
+	int ch;
+	size_t m;
+
+	_DIAGASSERT(ms != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(n > 0);
+
+	for (m = 0; m < n; ++m) {
+		ch = _memstream_getc(ms);
+		if (ch != '_' && _bcs_isalnum(ch) == 0)
+			goto name_found;
+		s[m] = ch;
+	}
+	ch = _memstream_getc(ms);
+	if (ch == '_' || _bcs_isalnum(ch) != 0)
+		return EINVAL;
+
+name_found:
+	_memstream_ungetc(ms, ch);
+	s[m] = '\0';
+
+	return 0;
+}
+
+static int
+_citrus_prop_parse_element(struct _memstream * __restrict ms,
+	const _citrus_prop_hint_t * __restrict hints,
+	void ** __restrict context)
+{
+	int ch, errnum;
+#define _CITRUS_PROP_HINT_NAME_LEN_MAX	255
+	char name[_CITRUS_PROP_HINT_NAME_LEN_MAX + 1];
+	const _citrus_prop_hint_t *hint;
+	_citrus_prop_object_t ostart, oend;
+
+	_DIAGASSERT(ms != NULL);
+	_DIAGASSERT(hints != NULL);
+
+	errnum = _citrus_prop_read_symbol(ms, name, sizeof(name));
+	if (errnum != 0)
+		return errnum;
+	for (hint = hints; hint->name != NULL; ++hint) {
+		if (_citrus_bcs_strcasecmp(name, hint->name) == 0)
+			goto hint_found;
+	}
+	return EINVAL;
+
+hint_found:
+	_memstream_skip_ws(ms);
+	ch = _memstream_getc(ms);
+	if (ch != '=' && ch != ':')
+		_memstream_ungetc(ms, ch);
+	do {
+		_citrus_prop_object_init(&ostart, hint->type);
+		_citrus_prop_object_init(&oend, hint->type);
+		errnum = (*readers[hint->type])(ms, &ostart);
+		if (errnum != 0)
+			return errnum;
+		_memstream_skip_ws(ms);
+		ch = _memstream_getc(ms);
+		switch (hint->type) {
+		case _CITRUS_PROP_BOOL:
+		case _CITRUS_PROP_STR:
+			break;
+		default:
+			if (ch != '-')
+				break;
+			errnum = (*readers[hint->type])(ms, &oend);
+			if (errnum != 0)
+				return errnum;
+			_memstream_skip_ws(ms);
+			ch = _memstream_getc(ms);
+		}
+#define CALL0(_func_)					\
+do {							\
+	_DIAGASSERT(hint->cb._func_.func != NULL);	\
+	errnum = (*hint->cb._func_.func)(context,	\
+	    hint->name,	ostart.u._func_);		\
+} while (/*CONSTCOND*/0)
+#define CALL1(_func_)					\
+do {							\
+	_DIAGASSERT(hint->cb._func_.func != NULL);	\
+	errnum = (*hint->cb._func_.func)(context,	\
+	    hint->name,	ostart.u._func_, oend.u._func_);\
+} while (/*CONSTCOND*/0)
+
+		switch (hint->type) {
+
+		case _CITRUS_PROP_BOOL:
+			CALL0(boolean);
+			break;
+
+		case _CITRUS_PROP_STR:
+			CALL0(str);
+			break;
+
+		case _CITRUS_PROP_CHR:
+			CALL1(chr);
+			break;
+
+		case _CITRUS_PROP_NUM:
+			CALL1(num);
+			break;
+
+		default:
+			panic("unknown prop type (type=%d)", hint->type);
+			/*NOTREACHED*/
+		}
+#undef CALL0
+#undef CALL1
+		_citrus_prop_object_uninit(&ostart);
+		_citrus_prop_object_uninit(&oend);
+		if (errnum != 0)
+			return errnum;
+	} while (ch == ',');
+	if (ch != ';')
+		_memstream_ungetc(ms, ch);
+	return 0;
+}
+
+int
+_citrus_prop_parse_variable(const _citrus_prop_hint_t * __restrict hints,
+	void * __restrict context, const void *var, size_t lenvar)
+{
+	struct _memstream ms;
+	int errnum, ch;
+	void *tmp = context, **ctxp = &tmp;	/* XXX: gcc */
+
+	_DIAGASSERT(hints != NULL);
+
+	_memstream_bind_ptr(&ms, __UNCONST(var), lenvar);
+	for (;;) {
+		_memstream_skip_ws(&ms);
+		ch = _memstream_getc(&ms);
+		if (ch == EOF || ch == '\0')
+			break;
+		_memstream_ungetc(&ms, ch);
+		errnum = _citrus_prop_parse_element(&ms, hints, ctxp);
+		if (errnum != 0)
+			return errnum;
+	}
+	return 0;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_prop.h src/sys/kiconv/citrus_prop.h
--- src.orig/sys/kiconv/citrus_prop.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_prop.h	2011-06-03 14:39:03.000000000 +0900
@@ -0,0 +1,91 @@
+/* $NetBSD: citrus_prop.h,v 1.5 2011/05/23 14:52:32 joerg Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_PROP_H_
+#define _CITRUS_PROP_H_
+
+typedef enum {
+	_CITRUS_PROP_BOOL = 0,
+	_CITRUS_PROP_STR  = 1,
+	_CITRUS_PROP_CHR  = 2,
+	_CITRUS_PROP_NUM  = 3,
+} _citrus_prop_type_t;
+
+typedef struct _citrus_prop_hint_t _citrus_prop_hint_t;
+
+#define _CITRUS_PROP_CB0_T(_func_, _type_) \
+typedef int (*_citrus_prop_##_func_##_cb_func_t) \
+	(void ** __restrict, const char *, _type_); \
+typedef struct { \
+	_citrus_prop_##_func_##_cb_func_t func; \
+} _citrus_prop_##_func_##_cb_t;
+_CITRUS_PROP_CB0_T(boolean, int)
+_CITRUS_PROP_CB0_T(str, const char *)
+#undef _CITRUS_PROP_CB0_T
+
+#define _CITRUS_PROP_CB1_T(_func_, _type_) \
+typedef int (*_citrus_prop_##_func_##_cb_func_t) \
+	(void ** __restrict, const char *, _type_, _type_); \
+typedef struct { \
+	_citrus_prop_##_func_##_cb_func_t func; \
+} _citrus_prop_##_func_##_cb_t;
+_CITRUS_PROP_CB1_T(chr, int)
+_CITRUS_PROP_CB1_T(num, uint64_t)
+#undef _CITRUS_PROP_CB1_T
+
+struct _citrus_prop_hint_t {
+	const char *name;
+	_citrus_prop_type_t type;
+#define _CITRUS_PROP_CB_T_OPS(_name_) \
+	_citrus_prop_##_name_##_cb_t _name_
+	union {
+		_CITRUS_PROP_CB_T_OPS(boolean);
+		_CITRUS_PROP_CB_T_OPS(str);
+		_CITRUS_PROP_CB_T_OPS(chr);
+		_CITRUS_PROP_CB_T_OPS(num);
+	} cb;
+};
+
+#define _CITRUS_PROP_HINT_BOOL(name, cb) \
+	{ name, _CITRUS_PROP_BOOL, { .boolean = { cb } } }
+#define _CITRUS_PROP_HINT_STR(name, cb) \
+	{ name, _CITRUS_PROP_STR, { .str = { cb } } }
+#define _CITRUS_PROP_HINT_CHR(name, cb) \
+	{ name, _CITRUS_PROP_CHR, { .chr = { cb } } }
+#define _CITRUS_PROP_HINT_NUM(name, cb) \
+	{ name, _CITRUS_PROP_NUM, { .num = { cb } } }
+#define _CITRUS_PROP_HINT_END \
+	{ .name = NULL }
+
+__BEGIN_DECLS
+int _citrus_prop_parse_variable(const _citrus_prop_hint_t * __restrict,
+	void * __restrict, const void *, size_t);
+__END_DECLS
+
+#endif /* !_CITRUS_PROP_H_ */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_region.h src/sys/kiconv/citrus_region.h
--- src.orig/sys/kiconv/citrus_region.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_region.h	2011-06-03 14:37:47.000000000 +0900
@@ -0,0 +1,108 @@
+/*	$NetBSD: citrus_region.h,v 1.7 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_REGION_H_
+#define _CITRUS_REGION_H_
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+struct _citrus_region {
+/* private: */
+	void	*r_head;
+	size_t	r_size;
+};
+
+static __inline void
+_citrus_region_init(struct _citrus_region *r, void *h, size_t sz)
+{
+	_DIAGASSERT(r);
+	r->r_head = h;
+	r->r_size = sz;
+}
+
+static __inline void *
+_citrus_region_head(const struct _citrus_region *r)
+{
+	return r->r_head;
+}
+
+static __inline size_t
+_citrus_region_size(const struct _citrus_region *r)
+{
+	return r->r_size;
+}
+
+static __inline int
+_citrus_region_check(const struct _citrus_region *r, size_t ofs, size_t sz)
+{
+	return r->r_size >= ofs + sz ? 0 : -1;
+}
+
+static __inline void *
+_citrus_region_offset(const struct _citrus_region *r, size_t pos)
+{
+	return (void *)((uint8_t *)r->r_head + pos);
+}
+
+static __inline uint8_t
+_citrus_region_peek8(const struct _citrus_region *r, size_t pos)
+{
+	return *(uint8_t *)_citrus_region_offset(r, pos);
+}
+
+static __inline uint16_t
+_citrus_region_peek16(const struct _citrus_region *r, size_t pos)
+{
+	uint16_t val;
+	memcpy(&val, _citrus_region_offset(r, pos), (size_t)2);
+	return val;
+}
+
+static __inline uint32_t
+_citrus_region_peek32(const struct _citrus_region *r, size_t pos)
+{
+	uint32_t val;
+	memcpy(&val, _citrus_region_offset(r, pos), (size_t)4);
+	return val;
+}
+
+static __inline int
+_citrus_region_get_subregion(struct _citrus_region *subr,
+			     const struct _citrus_region *r,
+			     size_t ofs, size_t sz)
+{
+	if (_citrus_region_check(r, ofs, sz))
+		return -1;
+	_citrus_region_init(subr, _citrus_region_offset(r, ofs), sz);
+	return 0;
+}
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_stdenc.c src/sys/kiconv/citrus_stdenc.c
--- src.orig/sys/kiconv/citrus_stdenc.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_stdenc.c	2011-06-03 21:56:50.000000000 +0900
@@ -0,0 +1,172 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_stdenc.c,v 1.3 2005/10/29 18:02:04 tshiozak Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_stdenc.c,v 1.3 2005/10/29 18:02:04 tshiozak Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include "namespace.h"
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_none.h"
+
+struct _citrus_stdenc _citrus_stdenc_default = {
+	&_citrus_NONE_stdenc_ops,	/* ce_ops */
+	NULL,				/* ce_closure */
+	NULL,				/* ce_module */
+	&_citrus_NONE_stdenc_traits,	/* ce_traits */
+};
+
+static int
+/*ARGSUSED*/
+get_state_desc_default(struct _citrus_stdenc * __restrict ce,
+		       void * __restrict ps,
+		       int id,
+		       struct _citrus_stdenc_state_desc * __restrict d)
+{
+	return EOPNOTSUPP;
+}
+
+int
+_citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce,
+		    char const * __restrict encname,
+		    const void * __restrict variable, size_t lenvar)
+{
+	int ret;
+	_citrus_module_t handle;
+	struct _citrus_stdenc *ce;
+	_citrus_stdenc_getops_t getops;
+
+	_DIAGASSERT(encname != NULL);
+	_DIAGASSERT(!lenvar || variable!=NULL);
+	_DIAGASSERT(rce != NULL);
+
+	if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) {
+		*rce = &_citrus_stdenc_default;
+		return (0);
+	}
+	ce = malloc(sizeof(*ce), M_KICONV, M_WAITOK);
+	ce->ce_ops = NULL;
+	ce->ce_closure = NULL;
+	ce->ce_module = NULL;
+	ce->ce_traits = NULL;
+
+	ret = _citrus_load_module(&handle, encname);
+	if (ret)
+		goto bad;
+
+	ce->ce_module = handle;
+
+	getops =
+	    (_citrus_stdenc_getops_t)_citrus_find_getops(ce->ce_module,
+							 encname, "stdenc");
+	if (getops == NULL) {
+		ret = EINVAL;
+		goto bad;
+	}
+
+	ce->ce_ops = (struct _citrus_stdenc_ops *)malloc(sizeof(*ce->ce_ops),
+	    M_KICONV, M_WAITOK);
+
+	ret = (*getops)(ce->ce_ops, sizeof(*ce->ce_ops),
+			_CITRUS_STDENC_ABI_VERSION);
+	if (ret)
+		goto bad;
+
+	/* If return ABI version is not expected, should fixup it */
+	if (ce->ce_ops->eo_abi_version < 0x00000002) {
+		ce->ce_ops->eo_get_state_desc = &get_state_desc_default;
+	}
+
+	/* validation check */
+	if (ce->ce_ops->eo_init == NULL ||
+	    ce->ce_ops->eo_uninit == NULL ||
+	    ce->ce_ops->eo_init_state == NULL ||
+	    ce->ce_ops->eo_mbtocs == NULL ||
+	    ce->ce_ops->eo_cstomb == NULL ||
+	    ce->ce_ops->eo_mbtowc == NULL ||
+	    ce->ce_ops->eo_wctomb == NULL ||
+	    ce->ce_ops->eo_get_state_desc == NULL) {
+		ret = EINVAL;
+		goto bad;
+	}
+
+	/* allocate traits */
+	ce->ce_traits = malloc(sizeof(*ce->ce_traits), M_KICONV, M_WAITOK);
+
+	/* init and get closure */
+	ret = (*ce->ce_ops->eo_init)(ce, variable, lenvar, ce->ce_traits);
+	if (ret)
+		goto bad;
+
+	*rce = ce;
+
+	return (0);
+
+bad:
+	_citrus_stdenc_close(ce);
+	return (ret);
+}
+
+void
+_citrus_stdenc_close(struct _citrus_stdenc *ce)
+{
+
+	_DIAGASSERT(ce != NULL);
+
+	if (ce == &_citrus_stdenc_default)
+		return;
+
+	if (ce->ce_module) {
+		if (ce->ce_ops) {
+			if (ce->ce_closure && ce->ce_ops->eo_uninit)
+				(*ce->ce_ops->eo_uninit)(ce);
+			free(ce->ce_ops, M_KICONV);
+		}
+		free(ce->ce_traits, M_KICONV);
+		_citrus_unload_module(ce->ce_module);
+	}
+	free(ce, M_WAITOK);
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_stdenc.h src/sys/kiconv/citrus_stdenc.h
--- src.orig/sys/kiconv/citrus_stdenc.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_stdenc.h	2011-06-03 14:38:46.000000000 +0900
@@ -0,0 +1,145 @@
+/*	$NetBSD: citrus_stdenc.h,v 1.4 2005/10/29 18:02:04 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_STDENC_H_
+#define _CITRUS_STDENC_H_
+
+struct _citrus_stdenc;
+struct _citrus_stdenc_ops;
+struct _citrus_stdenc_traits;
+
+#define _CITRUS_STDENC_SDID_GENERIC		0
+struct _citrus_stdenc_state_desc
+{
+	union {
+		struct {
+			int	state;
+#define _CITRUS_STDENC_SDGEN_UNKNOWN		0
+#define _CITRUS_STDENC_SDGEN_INITIAL		1
+#define _CITRUS_STDENC_SDGEN_STABLE		2
+#define _CITRUS_STDENC_SDGEN_INCOMPLETE_CHAR	3
+#define _CITRUS_STDENC_SDGEN_INCOMPLETE_SHIFT	4
+		} generic;
+	} u;
+};
+
+#include "citrus_stdenc_local.h"
+
+__BEGIN_DECLS
+int _citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict,
+			char const * __restrict,
+			const void * __restrict, size_t);
+void _citrus_stdenc_close(struct _citrus_stdenc *);
+__END_DECLS
+
+static __inline int
+_citrus_stdenc_init_state(struct _citrus_stdenc * __restrict ce,
+			  void * __restrict ps)
+{
+	_DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_init_state);
+	return (*ce->ce_ops->eo_init_state)(ce, ps);
+}
+
+static __inline int
+_citrus_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce,
+		      _citrus_csid_t * __restrict csid,
+		      _citrus_index_t * __restrict idx,
+		      const char ** __restrict s, size_t n,
+		      void * __restrict ps, size_t * __restrict nresult)
+{
+	_DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_mbtocs);
+	return (*ce->ce_ops->eo_mbtocs)(ce, csid, idx, s, n, ps, nresult);
+}
+
+static __inline int
+_citrus_stdenc_cstomb(struct _citrus_stdenc * __restrict ce,
+		      char * __restrict s, size_t n,
+		      _citrus_csid_t csid, _citrus_index_t idx,
+		      void * __restrict ps, size_t * __restrict nresult)
+{
+	_DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_cstomb);
+	return (*ce->ce_ops->eo_cstomb)(ce, s, n, csid, idx, ps, nresult);
+}
+
+static __inline int
+_citrus_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce,
+		      _citrus_wc_t * __restrict wc,
+		      const char ** __restrict s, size_t n,
+		      void * __restrict ps, size_t * __restrict nresult)
+{
+	_DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_mbtocs);
+	return (*ce->ce_ops->eo_mbtowc)(ce, wc, s, n, ps, nresult);
+}
+
+static __inline int
+_citrus_stdenc_wctomb(struct _citrus_stdenc * __restrict ce,
+		      char * __restrict s, size_t n, _citrus_wc_t wc,
+		      void * __restrict ps, size_t * __restrict nresult)
+{
+	_DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_cstomb);
+	return (*ce->ce_ops->eo_wctomb)(ce, s, n, wc, ps, nresult);
+}
+
+static __inline int
+_citrus_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce,
+			       char * __restrict s, size_t n,
+			       void * __restrict ps,
+			       size_t * __restrict nresult)
+{
+	_DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_put_state_reset);
+	return (*ce->ce_ops->eo_put_state_reset)(ce, s, n, ps, nresult);
+}
+
+static __inline size_t
+_citrus_stdenc_get_state_size(struct _citrus_stdenc *ce)
+{
+	_DIAGASSERT(ce && ce->ce_traits);
+	return ce->ce_traits->et_state_size;
+}
+
+static __inline size_t
+_citrus_stdenc_get_mb_cur_max(struct _citrus_stdenc *ce)
+{
+	_DIAGASSERT(ce && ce->ce_traits);
+	return ce->ce_traits->et_mb_cur_max;
+}
+
+static __inline int
+_citrus_stdenc_get_state_desc(struct _citrus_stdenc * __restrict ce,
+			      void * __restrict ps,
+			      int id,
+			      struct _citrus_stdenc_state_desc * __restrict d)
+{
+
+	_DIAGASSERT(ce && ce->ce_ops && ce->ce_ops->eo_get_state_desc);
+
+	return (*ce->ce_ops->eo_get_state_desc)(ce, ps, id, d);
+}
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_stdenc_local.h src/sys/kiconv/citrus_stdenc_local.h
--- src.orig/sys/kiconv/citrus_stdenc_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_stdenc_local.h	2011-06-03 14:38:55.000000000 +0900
@@ -0,0 +1,153 @@
+/*	$NetBSD: citrus_stdenc_local.h,v 1.4 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_STDENC_LOCAL_H_
+#define _CITRUS_STDENC_LOCAL_H_
+
+#define _CITRUS_STDENC_GETOPS_FUNC_BASE(n)			\
+int n(struct _citrus_stdenc_ops *, size_t, uint32_t)
+#define _CITRUS_STDENC_GETOPS_FUNC(_e_)					\
+_CITRUS_STDENC_GETOPS_FUNC_BASE(_citrus_##_e_##_stdenc_getops)
+typedef _CITRUS_STDENC_GETOPS_FUNC_BASE((*_citrus_stdenc_getops_t));
+
+
+#define _CITRUS_STDENC_DECLS(_e_)					\
+static int	_citrus_##_e_##_stdenc_init				\
+	(struct _citrus_stdenc * __restrict, const void * __restrict,	\
+	 size_t, struct _citrus_stdenc_traits * __restrict);		\
+static void	_citrus_##_e_##_stdenc_uninit(struct _citrus_stdenc *);	\
+static int	_citrus_##_e_##_stdenc_init_state			\
+	(struct _citrus_stdenc * __restrict, void * __restrict);	\
+static int	_citrus_##_e_##_stdenc_mbtocs				\
+	(struct _citrus_stdenc * __restrict,				\
+	 _citrus_csid_t * __restrict, _citrus_index_t * __restrict,	\
+	 const char ** __restrict, size_t,				\
+	 void * __restrict, size_t * __restrict);			\
+static int	_citrus_##_e_##_stdenc_cstomb				\
+	(struct _citrus_stdenc * __restrict, char * __restrict,		\
+	 size_t, _citrus_csid_t, _citrus_index_t,			\
+	 void * __restrict, size_t * __restrict);			\
+static int	_citrus_##_e_##_stdenc_mbtowc				\
+	(struct _citrus_stdenc * __restrict,				\
+	 _citrus_wc_t * __restrict,					\
+	 const char ** __restrict, size_t,				\
+	 void * __restrict, size_t * __restrict);			\
+static int	_citrus_##_e_##_stdenc_wctomb				\
+	(struct _citrus_stdenc * __restrict, char * __restrict, size_t,	\
+	 _citrus_wc_t, void * __restrict, size_t * __restrict);		\
+static int	_citrus_##_e_##_stdenc_put_state_reset			\
+	(struct _citrus_stdenc * __restrict, char * __restrict, size_t,	\
+	 void * __restrict, size_t * __restrict);			\
+static int	_citrus_##_e_##_stdenc_get_state_desc			\
+	(struct _citrus_stdenc * __restrict, void * __restrict, int,	\
+	 struct _citrus_stdenc_state_desc * __restrict)
+
+#define _CITRUS_STDENC_DEF_OPS(_e_)					\
+struct _citrus_stdenc_ops _citrus_##_e_##_stdenc_ops = {		\
+	/* eo_abi_version */	_CITRUS_STDENC_ABI_VERSION,		\
+	/* eo_init */		&_citrus_##_e_##_stdenc_init,		\
+	/* eo_uninit */		&_citrus_##_e_##_stdenc_uninit,		\
+	/* eo_init_state */	&_citrus_##_e_##_stdenc_init_state,	\
+	/* eo_mbtocs */		&_citrus_##_e_##_stdenc_mbtocs,		\
+	/* eo_cstomb */		&_citrus_##_e_##_stdenc_cstomb,		\
+	/* eo_mbtowc */		&_citrus_##_e_##_stdenc_mbtowc,		\
+	/* eo_wctomb */		&_citrus_##_e_##_stdenc_wctomb,		\
+	/* eo_put_state_reset */&_citrus_##_e_##_stdenc_put_state_reset,\
+	/* eo_get_state_desc */	&_citrus_##_e_##_stdenc_get_state_desc	\
+}
+
+typedef int	(*_citrus_stdenc_init_t)
+	(struct _citrus_stdenc * __reatrict, const void * __restrict , size_t,
+	 struct _citrus_stdenc_traits * __restrict);
+typedef void	(*_citrus_stdenc_uninit_t)(struct _citrus_stdenc * __restrict);
+typedef int	(*_citrus_stdenc_init_state_t)
+	(struct _citrus_stdenc * __restrict, void * __restrict);
+typedef int	(*_citrus_stdenc_mbtocs_t)
+	(struct _citrus_stdenc * __restrict,
+	 _citrus_csid_t * __restrict, _citrus_index_t * __restrict,
+	 const char ** __restrict, size_t,
+	 void * __restrict, size_t * __restrict);
+typedef int	(*_citrus_stdenc_cstomb_t)
+	(struct _citrus_stdenc *__restrict, char * __restrict, size_t,
+	 _citrus_csid_t, _citrus_index_t, void * __restrict,
+	 size_t * __restrict);
+typedef int	(*_citrus_stdenc_mbtowc_t)
+	(struct _citrus_stdenc * __restrict,
+	 _citrus_wc_t * __restrict,
+	 const char ** __restrict, size_t,
+	 void * __restrict, size_t * __restrict);
+typedef int	(*_citrus_stdenc_wctomb_t)
+	(struct _citrus_stdenc *__restrict, char * __restrict, size_t,
+	 _citrus_wc_t, void * __restrict, size_t * __restrict);
+typedef int	(*_citrus_stdenc_put_state_reset_t)
+	(struct _citrus_stdenc *__restrict, char * __restrict, size_t,
+	 void * __restrict, size_t * __restrict);
+typedef int	(*_citrus_stdenc_get_state_desc_t)
+	(struct _citrus_stdenc * __restrict, void * __restrict, int,
+	 struct _citrus_stdenc_state_desc * __restrict);
+/*
+ * ABI version change log
+ *   0x00000001
+ *     initial version
+ */
+#define _CITRUS_STDENC_ABI_VERSION	0x00000002
+struct _citrus_stdenc_ops {
+	uint32_t			eo_abi_version;
+	/* version 0x00000001 */
+	_citrus_stdenc_init_t		eo_init;
+	_citrus_stdenc_uninit_t		eo_uninit;
+	_citrus_stdenc_init_state_t	eo_init_state;
+	_citrus_stdenc_mbtocs_t		eo_mbtocs;
+	_citrus_stdenc_cstomb_t		eo_cstomb;
+	_citrus_stdenc_mbtowc_t		eo_mbtowc;
+	_citrus_stdenc_wctomb_t		eo_wctomb;
+	_citrus_stdenc_put_state_reset_t eo_put_state_reset;
+	/* version 0x00000002 */
+	_citrus_stdenc_get_state_desc_t	eo_get_state_desc;
+};
+
+struct _citrus_stdenc_traits {
+	/* version 0x00000001 */
+	size_t				et_state_size;
+	size_t				et_mb_cur_max;
+};
+
+struct _citrus_stdenc {
+	/* public */
+	/* version 0x00000001 */
+	struct _citrus_stdenc_ops	*ce_ops;
+	void				*ce_closure;
+	/* private */
+	_citrus_module_t		ce_module;
+	struct _citrus_stdenc_traits	*ce_traits;
+};
+
+#define _CITRUS_DEFAULT_STDENC_NAME		"NONE"
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_stdenc_template.h src/sys/kiconv/citrus_stdenc_template.h
--- src.orig/sys/kiconv/citrus_stdenc_template.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_stdenc_template.h	2011-06-02 19:19:10.000000000 +0900
@@ -0,0 +1,202 @@
+/*	$NetBSD: citrus_stdenc_template.h,v 1.4 2008/02/09 14:56:20 junyoung Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * CAUTION: THIS IS NOT STANDALONE FILE
+ *
+ * function templates of iconv standard encoding handler for each encodings.
+ *
+ */
+
+/*
+ * macros
+ */
+
+#undef _TO_EI
+#undef _CE_TO_EI
+#undef _TO_STATE
+#define _TO_EI(_cl_)	((_ENCODING_INFO*)(_cl_))
+#define _CE_TO_EI(_ce_)	(_TO_EI((_ce_)->ce_closure))
+#define _TO_STATE(_ps_)	((_ENCODING_STATE*)(_ps_))
+
+/* ----------------------------------------------------------------------
+ * templates for public functions
+ */
+
+int
+_FUNCNAME(stdenc_getops)(struct _citrus_stdenc_ops *ops, size_t lenops,
+			 uint32_t expected_version)
+{
+	if (expected_version<_CITRUS_STDENC_ABI_VERSION || lenops<sizeof(*ops))
+		return (EINVAL);
+
+	memcpy(ops, &_FUNCNAME(stdenc_ops), sizeof(_FUNCNAME(stdenc_ops)));
+
+	return (0);
+}
+
+static int
+_FUNCNAME(stdenc_init)(struct _citrus_stdenc * __restrict ce,
+		       const void * __restrict var, size_t lenvar,
+		       struct _citrus_stdenc_traits * __restrict et)
+{
+	int ret;
+	_ENCODING_INFO *ei;
+
+	ei = NULL;
+	if (sizeof(_ENCODING_INFO) > 0)
+		ei = malloc(sizeof(_ENCODING_INFO), M_KICONV, M_ZERO|M_WAITOK);
+
+	ret = _FUNCNAME(encoding_module_init)(ei, var, lenvar);
+	if (ret) {
+		free((void *)ei, M_KICONV);
+		return ret;
+	}
+
+	ce->ce_closure = ei;
+	et->et_state_size = sizeof(_ENCODING_STATE);
+	et->et_mb_cur_max = _ENCODING_MB_CUR_MAX(_CE_TO_EI(ce));
+
+	return 0;
+}
+
+static void
+_FUNCNAME(stdenc_uninit)(struct _citrus_stdenc * __restrict ce)
+{
+	if (ce) {
+		_FUNCNAME(encoding_module_uninit)(_CE_TO_EI(ce));
+		free(ce->ce_closure, M_KICONV);
+	}
+}
+
+static int
+_FUNCNAME(stdenc_init_state)(struct _citrus_stdenc * __restrict ce,
+			     void * __restrict ps)
+{
+	_FUNCNAME(init_state)(_CE_TO_EI(ce), _TO_STATE(ps));
+
+	return 0;
+}
+
+static int
+_FUNCNAME(stdenc_mbtocs)(struct _citrus_stdenc * __restrict ce,
+			 _citrus_csid_t * __restrict csid,
+			 _citrus_index_t * __restrict idx,
+			 const char ** __restrict s, size_t n,
+			 void * __restrict ps, size_t * __restrict nresult)
+{
+	int ret;
+	wchar_t wc;
+
+	_DIAGASSERT(nresult != NULL);
+
+	ret = _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), &wc, s, n,
+				      _TO_STATE(ps), nresult);
+
+	if (!ret && *nresult != (size_t)-2)
+		_FUNCNAME(stdenc_wctocs)(_CE_TO_EI(ce), csid, idx, wc);
+
+	return ret;
+}
+
+static int
+_FUNCNAME(stdenc_cstomb)(struct _citrus_stdenc * __restrict ce,
+			 char * __restrict s, size_t n,
+			 _citrus_csid_t csid, _citrus_index_t idx,
+			 void * __restrict ps, size_t * __restrict nresult)
+{
+	int ret;
+	wchar_t wc;
+
+	_DIAGASSERT(nresult != NULL);
+
+	wc = 0;
+
+	if (csid != _CITRUS_CSID_INVALID) {
+		ret = _FUNCNAME(stdenc_cstowc)(_CE_TO_EI(ce), &wc, csid, idx);
+		if (ret)
+			return ret;
+	}
+
+	return _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc, _TO_STATE(ps),
+				       nresult);
+}
+
+static int
+_FUNCNAME(stdenc_mbtowc)(struct _citrus_stdenc * __restrict ce,
+			 _citrus_wc_t * __restrict wc,
+			 const char ** __restrict s, size_t n,
+			 void * __restrict ps, size_t * __restrict nresult)
+{
+	return _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), wc, s, n,
+				       _TO_STATE(ps), nresult);
+}
+
+static int
+_FUNCNAME(stdenc_wctomb)(struct _citrus_stdenc * __restrict ce,
+			  char * __restrict s, size_t n, _citrus_wc_t wc,
+			  void * __restrict ps, size_t * __restrict nresult)
+{
+	return _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc, _TO_STATE(ps),
+				       nresult);
+}
+
+static int
+_FUNCNAME(stdenc_put_state_reset)(struct _citrus_stdenc * __restrict ce,
+				  char * __restrict s, size_t n,
+				  void * __restrict ps,
+				  size_t * __restrict nresult)
+{
+#if _ENCODING_IS_STATE_DEPENDENT
+	return _FUNCNAME(put_state_reset)(_CE_TO_EI(ce), s, n, _TO_STATE(ps),
+					  nresult);
+#else
+	*nresult = 0;
+	return 0;
+#endif
+}
+
+static int
+_FUNCNAME(stdenc_get_state_desc)(struct _citrus_stdenc * __restrict ce,
+				 void * __restrict ps,
+				 int id,
+				 struct _citrus_stdenc_state_desc * __restrict d)
+{
+	int ret;
+
+	switch (id) {
+	case _STDENC_SDID_GENERIC:
+		ret = _FUNCNAME(stdenc_get_state_desc_generic)(
+			_CE_TO_EI(ce), _TO_STATE(ps), &d->u.generic.state);
+		break;
+	default:
+		ret = EOPNOTSUPP;
+	}
+
+	return ret;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/citrus_types.h src/sys/kiconv/citrus_types.h
--- src.orig/sys/kiconv/citrus_types.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/citrus_types.h	2011-06-03 14:22:56.000000000 +0900
@@ -0,0 +1,41 @@
+/*	$NetBSD: citrus_types.h,v 1.3 2003/10/27 00:12:42 lukem Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_TYPES_H_
+#define _CITRUS_TYPES_H_
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+typedef uint32_t	_citrus_wc_t;
+typedef uint32_t	_citrus_index_t;
+typedef uint32_t	_citrus_csid_t;
+#define _CITRUS_CSID_INVALID	((_citrus_csid_t)-1)
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/ctype_.c src/sys/kiconv/ctype_.c
--- src.orig/sys/kiconv/ctype_.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/ctype_.c	2011-06-03 15:11:04.000000000 +0900
@@ -0,0 +1,92 @@
+/*	$NetBSD$	*/
+/*	NetBSD: ctype_.c,v 1.19 2010/12/14 02:28:57 joerg Exp	*/
+
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+/*static char *sccsid = "from: @(#)ctype_.c	5.6 (Berkeley) 6/1/90";*/
+#else
+__RCSID("NetBSD: ctype_.c,v 1.19 2010/12/14 02:28:57 joerg Exp");
+#endif
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/ctype_bits.h>
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <stdio.h>
+#endif
+#include "ctype_local.h"
+
+#if EOF != -1
+#error "EOF != -1"
+#endif
+
+#define	_U	_CTYPE_U
+#define	_L	_CTYPE_L
+#define	_N	_CTYPE_N
+#define	_S	_CTYPE_S
+#define	_P	_CTYPE_P
+#define	_C	_CTYPE_C
+#define	_X	_CTYPE_X
+#define	_B	_CTYPE_B
+
+const unsigned char _C_ctype_[1 + _CTYPE_NUM_CHARS] = {
+	0,
+	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
+	_C,	_C|_S,	_C|_S,	_C|_S,	_C|_S,	_C|_S,	_C,	_C,
+	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
+	_C,	_C,	_C,	_C,	_C,	_C,	_C,	_C,
+	_S|_B,	_P,	_P,	_P,	_P,	_P,	_P,	_P,
+	_P,	_P,	_P,	_P,	_P,	_P,	_P,	_P,
+	_N,	_N,	_N,	_N,	_N,	_N,	_N,	_N,
+	_N,	_N,	_P,	_P,	_P,	_P,	_P,	_P,
+	_P,	_U|_X,	_U|_X,	_U|_X,	_U|_X,	_U|_X,	_U|_X,	_U,
+	_U,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
+	_U,	_U,	_U,	_U,	_U,	_U,	_U,	_U,
+	_U,	_U,	_U,	_P,	_P,	_P,	_P,	_P,
+	_P,	_L|_X,	_L|_X,	_L|_X,	_L|_X,	_L|_X,	_L|_X,	_L,
+	_L,	_L,	_L,	_L,	_L,	_L,	_L,	_L,
+	_L,	_L,	_L,	_L,	_L,	_L,	_L,	_L,
+	_L,	_L,	_L,	_P,	_P,	_P,	_P,	_C
+};
+
+const unsigned char *_ctype_ = &_C_ctype_[0];
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/ctype_local.h src/sys/kiconv/ctype_local.h
--- src.orig/sys/kiconv/ctype_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/ctype_local.h	2011-06-03 14:15:25.000000000 +0900
@@ -0,0 +1,40 @@
+/* $NetBSD: ctype_local.h,v 1.4 2010/06/13 04:14:57 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 2010 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#ifndef _CTYPE_LOCAL_H_
+#define _CTYPE_LOCAL_H_
+
+#include <machine/limits.h>
+
+#define _CTYPE_NUM_CHARS	(1 << CHAR_BIT)
+#define _CTYPE_CACHE_SIZE	(1 << 8)
+
+extern const unsigned char _C_ctype_[];
+extern const short _C_toupper_[];
+extern const short _C_tolower_[];
+
+#endif /*_CTYPE_LOCAL_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/files.kiconv src/sys/kiconv/files.kiconv
--- src.orig/sys/kiconv/files.kiconv	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/files.kiconv	2011-06-04 22:15:02.000000000 +0900
@@ -0,0 +1,117 @@
+# $NetBSD$
+
+#
+# in-kernel iconv
+#
+
+defflag	KICONV
+defflag	KICONV_MODULE: KICONV
+
+file	kiconv/kiconv.c				kiconv
+file	kiconv/citrus_bcs.c			kiconv
+file	kiconv/citrus_bcs_strtol.c		kiconv
+file	kiconv/citrus_bcs_strtoul.c		kiconv
+file	kiconv/citrus_csmapper.c		kiconv
+file	kiconv/citrus_ctype.c			kiconv
+file	kiconv/citrus_ctype_fallback.c		kiconv
+file	kiconv/citrus_db.c			kiconv
+file	kiconv/citrus_db_hash.c			kiconv
+file	kiconv/citrus_esdb.c			kiconv
+file	kiconv/citrus_hash.c			kiconv
+file	kiconv/citrus_iconv.c			kiconv
+file	kiconv/citrus_lc_ctype.c		kiconv
+file	kiconv/citrus_lookup.c			kiconv
+file	kiconv/citrus_mapper.c			kiconv
+file	kiconv/citrus_memstream.c		kiconv
+file	kiconv/citrus_mmap.c			kiconv
+file	kiconv/citrus_module.c			kiconv
+file	kiconv/citrus_none.c			kiconv
+file	kiconv/citrus_prop.c			kiconv
+file	kiconv/citrus_stdenc.c			kiconv
+
+file	kiconv/ctype_.c				kiconv
+file	kiconv/locale.c				kiconv
+file	kiconv/rune.c				kiconv
+file	kiconv/runetable.c			kiconv
+file	kiconv/tolower_.c			kiconv
+file	kiconv/toupper_.c			kiconv
+file	kiconv/_wctrans.c			kiconv
+file	kiconv/_wctype.c			kiconv
+
+#
+# encoding modules
+#
+defflag	KICONV_BIG5: KICONV_MODULE
+defflag	KICONV_DECHANYU: KICONV_MODULE
+defflag	KICONV_EUC: KICONV_MODULE
+defflag	KICONV_EUCTW: KICONV_MODULE
+defflag	KICONV_GBK2K: KICONV_MODULE
+defflag	KICONV_HZ: KICONV_MODULE
+defflag	KICONV_ISO2022: KICONV_MODULE
+defflag	KICONV_JOHAB: KICONV_MODULE
+defflag	KICONV_MSKANJI: KICONV_MODULE
+defflag	KICONV_UES: KICONV_MODULE
+defflag	KICONV_UTF1632: KICONV_MODULE
+defflag	KICONV_UTF7: KICONV_MODULE
+defflag	KICONV_UTF8: KICONV_MODULE
+defflag	KICONV_VIQR: KICONV_MODULE
+defflag	KICONV_ZW: KICONV_MODULE
+defflag	KICONV_UTF16: KICONV_UTF1632
+defflag	KICONV_UTF32: KICONV_UTF1632
+defflag	KICONV_ALL_ENCODING: KICONV_BIG5, KICONV_DECHANYU, KICONV_EUC,
+	                     KICONV_EUCTW, KICONV_GBK2K, KICONV_HZ,
+	                     KICONV_ISO2022, KICONV_JOHAB, KICONV_MSKANJI,
+	                     KICONV_UES, KICONV_UTF1632, KICONV_UTF7,
+	                     KICONV_UTF8, KICONV_VIQR, KICONV_ZW
+
+file	kiconv/modules/citrus_big5.c		kiconv & kiconv_big5
+file	kiconv/modules/citrus_dechanyu.c	kiconv & kiconv_dechanyu
+file	kiconv/modules/citrus_euc.c		kiconv & kiconv_euc
+file	kiconv/modules/citrus_euctw.c		kiconv & kiconv_euctw
+file	kiconv/modules/citrus_gbk2k.c		kiconv & kiconv_bgk2k
+file	kiconv/modules/citrus_hz.c		kiconv & kiconv_hz
+file	kiconv/modules/citrus_iso2022.c		kiconv & kiconv_iso2022
+file	kiconv/modules/citrus_johab.c		kiconv & kiconv_johab
+file	kiconv/modules/citrus_mskanji.c		kiconv & kiconv_mskanji
+file	kiconv/modules/citrus_ues.c		kiconv & kiconv_ues
+file	kiconv/modules/citrus_utf1632.c		kiconv & kiconv_utf1632
+file	kiconv/modules/citrus_utf7.c		kiconv & kiconv_utf7
+file	kiconv/modules/citrus_utf8.c		kiconv & kiconv_utf8
+file	kiconv/modules/citrus_viqr.c		kiconv & kiconv_viqr
+file	kiconv/modules/citrus_zw.c		kiconv & kiconv_zw
+
+#
+# iconv module
+#
+defflag	KICONV_ICONV_NONE: KICONV_MODULE
+defflag	KICONV_ICONV_STD: KICONV_MODULE
+defflag	KICONV_ALL_ICONV: KICONV_ICONV_NONE, KICONV_ICONV_STD
+
+file	kiconv/modules/citrus_iconv_none.c	kiconv & kiconv_iconv_none
+file	kiconv/modules/citrus_iconv_std.c	kiconv & kiconv_iconv_std
+
+#
+# mapper module
+#
+defflag	KICONV_MAPPER_646: KICONV_MODULE
+defflag	KICONV_MAPPER_NONE: KICONV_MODULE
+defflag	KICONV_MAPPER_SERIAL: KICONV_MODULE
+defflag	KICONV_MAPPER_PARALLEL: KICONV_MODULE
+defflag	KICONV_MAPPER_STD: KICONV_MODULE
+defflag	KICONV_MAPPER_ZONE: KICONV_MODULE
+defflag	KICONV_ALL_MAPPER: KICONV_MAPPER_646, KICONV_MAPPER_NONE,
+	                   KICONV_MAPPER_SERIAL, KICONV_MAPPER_PARALLEL,
+	                   KICONV_MAPPER_STD, KICONV_MAPPER_ZONE
+
+file	kiconv/modules/citrus_mapper_646.c	kiconv & kiconv_mapper_646
+file	kiconv/modules/citrus_mapper_none.c	kiconv & kiconv_mapper_none
+file	kiconv/modules/citrus_mapper_serial.c	kiconv & (kiconv_mapper_serial | kiconv_mapper_parallel)
+file	kiconv/modules/citrus_mapper_std.c	kiconv & kiconv_mapper_std
+file	kiconv/modules/citrus_mapper_zone.c	kiconv & kiconv_mapper_zone
+
+#
+# compile options
+#
+makeoptions kiconv		CPPFLAGS+="-I${S}/kiconv"
+makeoptions kiconv		CPPFLAGS+="-I${NETBSDSRCDIR}/common/lib/libc/stdlib"
+makeoptions kiconv_module	CPPFLAGS+="-I${S}/kiconv/modules"
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/generic_lc_template.h src/sys/kiconv/generic_lc_template.h
--- src.orig/sys/kiconv/generic_lc_template.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/generic_lc_template.h	2011-06-03 16:48:14.000000000 +0900
@@ -0,0 +1,38 @@
+/* $NetBSD: generic_lc_template.h,v 1.3 2009/03/09 02:22:25 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _GENERIC_LC_TEMPLATE_H_
+#define _GENERIC_LC_TEMPLATE_H_
+
+#define _LOCALE_CATEGORY_ENTRY(name)			\
+const _klocale_category_t name##desc = {		\
+    .category = _CATEGORY_ID,				\
+    .setlocale = &name##setlocale,			\
+}
+
+#endif /*_GENERIC_LC_TEMPLATE_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/generic_lc_template_decl.h src/sys/kiconv/generic_lc_template_decl.h
--- src.orig/sys/kiconv/generic_lc_template_decl.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/generic_lc_template_decl.h	2011-06-03 16:28:19.000000000 +0900
@@ -0,0 +1,35 @@
+/* $NetBSD: generic_lc_template_decl.h,v 1.2 2009/01/11 02:46:28 christos Exp $ */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _GENERIC_LC_TEMPLATE_DECL_H_
+#define _GENERIC_LC_TEMPLATE_DECL_H_
+
+static const char * _PREFIX(setlocale)(const char * __restrict,
+    struct _klocale_impl_t * __restrict);
+
+#endif /*_GENERIC_LC_TEMPLATE_DECL_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/kiconv.c src/sys/kiconv/kiconv.c
--- src.orig/sys/kiconv/kiconv.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/kiconv.c	2011-07-12 09:43:06.000000000 +0900
@@ -0,0 +1,536 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by NONAKA Kimihiro.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+#include <sys/fcntl.h>
+#include <sys/pool.h>
+#include <sys/module.h>
+
+#define	_KICONV_LOCAL
+#include <kiconv/kiconv.h>
+
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_esdb.h"
+#include "citrus_hash.h"
+#include "citrus_iconv.h"
+#include "citrus_ctype.h"
+
+#include "setlocale_local.h"
+
+#include "runetype_local.h"
+#include "runetype_file.h"
+#include "multibyte.h"
+#include "rune.h"
+#include "_wctype_local.h"
+#include "_wctrans_local.h"
+
+
+/*----------------------------------------------------------------------------
+ * iconv
+ */
+#define	ISBADF(_h_)	(!(_h_) || (_h_) == (kiconv_t)-1)
+
+kiconv_t
+_kiconv_open(const char *out, const char *in, int *errnop)
+{
+	struct _citrus_iconv *handle;
+	int error;
+
+	if (in == NULL)
+		in = _DEFAULT_ENCODING;
+	if (out == NULL)
+		out = _DEFAULT_ENCODING;
+
+	error = _citrus_iconv_open(&handle, _PATH_ICONV, in, out);
+	if (error) {
+		if (errnop)
+			*errnop = (error == ENOENT) ? EINVAL : error;
+		return (kiconv_t)-1;
+	}
+	return (kiconv_t)(void *)handle;
+}
+
+int
+_kiconv_close(kiconv_t handle, int *errnop)
+{
+
+	if (ISBADF(handle)) {
+		if (errnop)
+			*errnop = EBADF;
+		return -1;
+	}
+
+	_citrus_iconv_close((struct _citrus_iconv *)(void *)handle);
+	return 0;
+}
+
+size_t
+_kiconv_conv(kiconv_t handle, const char **in, size_t *szin, char **out,
+    size_t *szout, uint32_t flags, size_t *invalids, int *errnop)
+{
+	int error;
+	size_t ret;
+
+	if (ISBADF(handle)) {
+		if (errnop)
+			*errnop = EBADF;
+		return (size_t)-1;
+	}
+
+	error = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle,
+	    in, szin, out, szout, flags, &ret);
+	if (invalids)
+		*invalids = ret;
+	if (error) {
+		if (errnop)
+			*errnop = error;
+		ret = (size_t)-1;
+	}
+
+	return ret;
+}
+
+/*----------------------------------------------------------------------------
+ * locale
+ */
+klocale_t
+_kiconv_newlocale(const char *locale, int *errnop)
+{
+	extern const _klocale_category_t _citrus_LC_CTYPE_desc;
+	const _klocale_category_t *l = &_citrus_LC_CTYPE_desc;
+	struct _klocale_impl_t *dst;
+
+	if (locale == NULL)
+		locale = _DEFAULT_LOCALE;
+
+	dst = malloc(sizeof(*dst), M_KICONV, M_WAITOK);
+	*dst = *_locale_to_impl(NULL);
+	(*l->setlocale)(locale, dst);
+
+	if (errnop)
+		*errnop = 0;
+	return (klocale_t)dst;
+}
+
+int
+_kiconv_freelocale(klocale_t locale, int *errnop)
+{
+	struct _klocale_impl_t *impl;
+
+	if (locale == NULL) {
+		if (errnop)
+			*errnop = EINVAL;
+		return -1;
+	}
+	impl = (struct _klocale_impl_t *)locale;
+	if (impl == *_current_locale())
+		*_current_locale() = &_global_locale;
+	free(impl, M_KICONV);
+	return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * wchar
+ */
+#define _RUNE_LOCALE(locale) \
+    ((_RuneLocale *)(_locale_to_impl(locale))->part_impl[(size_t)LC_CTYPE])
+
+#define _CITRUS_CTYPE(locale) \
+    (_RUNE_LOCALE(locale)->rl_citrus_ctype)
+
+size_t
+_kiconv_mbrlen(const char *s, size_t n, mbstate_t *ps, klocale_t locale,
+    int *errnop)
+{
+	size_t ret;
+	int err0;
+
+	_fixup_ps(_RUNE_LOCALE(locale), ps, s == NULL);
+
+	err0 = _citrus_ctype_mbrlen(_ps_to_ctype(ps), s, n,
+				     _ps_to_private(ps), &ret);
+	if (err0 && errnop)
+		*errnop = err0;
+
+	return ret;
+}
+
+int
+_kiconv_mbsinit(const mbstate_t *ps, klocale_t locale, int *errnop)
+{
+	int ret;
+	int err0;
+	_RuneLocale *rl;
+
+	if (ps == NULL)
+		return 1;
+
+	if (_ps_to_runelocale(ps) == NULL)
+		rl = _RUNE_LOCALE(locale);
+	else
+		rl = _ps_to_runelocale(ps);
+
+	/* mbsinit should cause no error... */
+	err0 = _citrus_ctype_mbsinit(rl->rl_citrus_ctype,
+				      _ps_to_private_const(ps), &ret);
+	if (err0 && errnop)
+		*errnop = err0;
+
+	return ret;
+}
+
+size_t
+_kiconv_mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps,
+    klocale_t locale, int *errnop)
+{
+	size_t ret;
+	int err0;
+
+	_fixup_ps(_RUNE_LOCALE(locale), ps, s == NULL);
+
+	err0 = _citrus_ctype_mbrtowc(_ps_to_ctype(ps), pwc, s, n,
+				       _ps_to_private(ps), &ret);
+	if (err0 && errnop)
+		*errnop = err0;
+
+	return ret;
+}
+
+size_t
+_kiconv_mbsrtowcs(wchar_t *pwcs, const char **s, size_t n, mbstate_t *ps,
+    klocale_t locale, int *errnop)
+{
+	size_t ret;
+	int err0;
+
+	_fixup_ps(_RUNE_LOCALE(locale), ps, s == NULL);
+
+	err0 = _citrus_ctype_mbsrtowcs(_ps_to_ctype(ps), pwcs, s, n,
+					_ps_to_private(ps), &ret);
+	if (err0 && errnop)
+		*errnop = err0;
+
+	return ret;
+}
+
+size_t
+_kiconv_wcrtomb(char *s, wchar_t wc, mbstate_t *ps, klocale_t locale,
+    int *errnop)
+{
+	size_t ret;
+	int err0;
+
+	_fixup_ps(_RUNE_LOCALE(locale), ps, s == NULL);
+
+	err0 = _citrus_ctype_wcrtomb(_ps_to_ctype(ps), s, wc,
+				       _ps_to_private(ps), &ret);
+	if (err0 && errnop)
+		*errnop = err0;
+
+	return ret;
+}
+
+size_t
+_kiconv_wcsrtombs(char *s, const wchar_t **ppwcs, size_t n, mbstate_t *ps,
+    klocale_t locale, int *errnop)
+{
+	size_t ret;
+	int err0;
+
+	_fixup_ps(_RUNE_LOCALE(locale), ps, s == NULL);
+
+	err0 = _citrus_ctype_wcsrtombs(_ps_to_ctype(ps), s, ppwcs, n,
+					_ps_to_private(ps), &ret);
+	if (err0 && errnop)
+		*errnop = err0;
+
+	return ret;
+}
+
+wint_t
+_kiconv_btowc(int c, klocale_t locale, int *errnop)
+{
+	wint_t ret;
+	int err0;
+
+	err0 = _citrus_ctype_btowc(_CITRUS_CTYPE(locale), c, &ret);
+	if (err0 && errnop)
+		*errnop = err0;
+
+	return ret;
+}
+
+int
+_kiconv_wctob(wint_t wc, klocale_t locale, int *errnop)
+{
+	int ret;
+	int err0;
+
+	err0 = _citrus_ctype_wctob(_CITRUS_CTYPE(locale), wc, &ret);
+	if (err0 && errnop)
+		*errnop = err0;
+
+	return ret;
+}
+
+int
+_kiconv_wcwidth(wchar_t wc, klocale_t locale)
+{
+	_RuneLocale const *rl;
+	_RuneType x;
+
+	_DIAGASSERT(locale != NULL);
+
+	if (wc == L'\0')
+		return 0;
+	rl = _RUNE_LOCALE(locale);
+	x = _runetype_priv(rl, wc);
+	if (x & _RUNETYPE_R)
+		return ((u_int)x & _RUNETYPE_SWM) >> _RUNETYPE_SWS;
+	return -1;
+}
+
+int
+_kiconv_wcswidth(const wchar_t *wcs, size_t wn, klocale_t locale)
+{
+	_RuneLocale const *rl;
+	_RuneType x;
+	int width;
+
+	_DIAGASSERT(wcs != NULL);
+	_DIAGASSERT(locale != NULL);
+
+	rl = _RUNE_LOCALE(locale);
+	width = 0;
+	for (width = 0; wn > 0 && *wcs != L'\0'; wcs++, --wn) {
+		x = _runetype_priv(rl, *wcs);
+		if ((x & _RUNETYPE_R) == 0)
+			return -1;
+		width += ((u_int)x & _RUNETYPE_SWM) >> _RUNETYPE_SWS;
+	}
+	return width;
+}
+
+/*----------------------------------------------------------------------------
+ * wctype
+ */
+#define _RUNE_ISWCTYPE_FUNC(name, index)		\
+int							\
+_kiconv_isw##name(wint_t wc, klocale_t locale)		\
+{							\
+	_RuneLocale const *rl;				\
+	_WCTypeEntry const *te;				\
+							\
+	rl = _RUNE_LOCALE(locale);			\
+	te = &rl->rl_wctype[index];			\
+	return _iswctype_priv(rl, wc, te);		\
+}
+_RUNE_ISWCTYPE_FUNC(alnum,  _WCTYPE_INDEX_ALNUM)
+_RUNE_ISWCTYPE_FUNC(alpha,  _WCTYPE_INDEX_ALPHA)
+_RUNE_ISWCTYPE_FUNC(blank,  _WCTYPE_INDEX_BLANK)
+_RUNE_ISWCTYPE_FUNC(cntrl,  _WCTYPE_INDEX_CNTRL)
+_RUNE_ISWCTYPE_FUNC(digit,  _WCTYPE_INDEX_DIGIT)
+_RUNE_ISWCTYPE_FUNC(graph,  _WCTYPE_INDEX_GRAPH)
+_RUNE_ISWCTYPE_FUNC(lower,  _WCTYPE_INDEX_LOWER)
+_RUNE_ISWCTYPE_FUNC(print,  _WCTYPE_INDEX_PRINT)
+_RUNE_ISWCTYPE_FUNC(punct,  _WCTYPE_INDEX_PUNCT)
+_RUNE_ISWCTYPE_FUNC(space,  _WCTYPE_INDEX_SPACE)
+_RUNE_ISWCTYPE_FUNC(upper,  _WCTYPE_INDEX_UPPER)
+_RUNE_ISWCTYPE_FUNC(xdigit, _WCTYPE_INDEX_XDIGIT)
+
+#define _RUNE_TOWCTRANS_FUNC(name, index)		\
+wint_t							\
+_kiconv_tow##name(wint_t wc, klocale_t locale)		\
+{							\
+	_RuneLocale const *rl;				\
+	_WCTransEntry const *te;			\
+							\
+	rl = _RUNE_LOCALE(locale);			\
+	te = &rl->rl_wctrans[index];			\
+	return _towctrans_priv(rl, wc, te);		\
+}
+_RUNE_TOWCTRANS_FUNC(upper, _WCTRANS_INDEX_UPPER)
+_RUNE_TOWCTRANS_FUNC(lower, _WCTRANS_INDEX_LOWER)
+
+wctype_t
+_kiconv_wctype(const char *charclass, klocale_t locale)
+{
+	_RuneLocale const *rl;
+	size_t i;
+
+	rl = _RUNE_LOCALE(locale);
+	for (i = 0; i < _WCTYPE_NINDEXES; ++i) {
+		if (!strcmp(rl->rl_wctype[i].te_name, charclass))
+			return (wctype_t)(intptr_t)&rl->rl_wctype[i];
+	}
+	return (wctype_t)NULL;
+}
+
+wctrans_t
+_kiconv_wctrans(const char *charmap, klocale_t locale)
+{
+	_RuneLocale const *rl;
+	size_t i;
+
+	rl = _RUNE_LOCALE(locale);
+	if (rl->rl_wctrans[_WCTRANS_INDEX_LOWER].te_name == NULL)
+		_wctrans_init(__UNCONST(rl));
+	for (i = 0; i < _WCTRANS_NINDEXES; ++i) {
+		if (!strcmp(rl->rl_wctrans[i].te_name, charmap))
+			return (wctrans_t)(intptr_t)&rl->rl_wctype[i];
+	}
+	return (wctrans_t)NULL;
+}
+
+int
+_kiconv_iswctype(wint_t wc, wctype_t charclass, klocale_t locale)
+{
+	_RuneLocale const *rl;
+	_WCTypeEntry const *te;
+
+	_DIAGASSERT(locale != NULL);
+
+	if (charclass == NULL)
+		return 0;
+
+	rl = _RUNE_LOCALE(locale);
+	te = (_WCTypeEntry const *)charclass;
+	return _iswctype_priv(rl, wc, te);
+}
+
+wint_t
+_kiconv_towctrans(wint_t wc, wctrans_t charmap, klocale_t locale)
+{
+	_RuneLocale const *rl;
+	_WCTransEntry const *te;
+
+	_DIAGASSERT(locale != NULL);
+
+	if (charmap == NULL)
+		return wc;
+
+	rl = _RUNE_LOCALE(locale);
+	te = (_WCTransEntry const *)charmap;
+	return _towctrans_priv(rl, wc, te);
+}
+
+/*----------------------------------------------------------------------------
+ * kiconv ops
+ */
+static struct kiconv_ops kiconv_ops = {
+	.iconv_open = _kiconv_open,
+	.iconv_close = _kiconv_close,
+	.iconv = _kiconv_conv,
+
+	.newlocale = _kiconv_newlocale,
+	.freelocale = _kiconv_freelocale,
+
+	.mbrlen = _kiconv_mbrlen,
+	.mbsinit = _kiconv_mbsinit,
+	.mbrtowc = _kiconv_mbrtowc,
+	.mbsrtowcs = _kiconv_mbsrtowcs,
+	.wcrtomb = _kiconv_wcrtomb,
+	.wcsrtombs = _kiconv_wcsrtombs,
+	.btowc = _kiconv_btowc,
+	.wctob = _kiconv_wctob,
+	.wcwidth = _kiconv_wcwidth,
+	.wcswidth = _kiconv_wcswidth,
+
+	.iswalnum = _kiconv_iswalnum,
+	.iswalpha = _kiconv_iswalpha,
+	.iswblank = _kiconv_iswblank,
+	.iswcntrl = _kiconv_iswcntrl,
+	.iswdigit = _kiconv_iswdigit,
+	.iswgraph = _kiconv_iswgraph,
+	.iswlower = _kiconv_iswlower,
+	.iswprint = _kiconv_iswprint,
+	.iswpunct = _kiconv_iswpunct,
+	.iswspace = _kiconv_iswspace,
+	.iswupper = _kiconv_iswupper,
+	.iswxdigit = _kiconv_iswxdigit,
+	.towupper = _kiconv_towupper,
+	.towlower = _kiconv_towlower,
+	.wctype = _kiconv_wctype,
+	.wctrans = _kiconv_wctrans,
+	.iswctype = _kiconv_iswctype,
+	.towctrans = _kiconv_towctrans,
+};
+
+/*-----------------------------------------------------------------------------
+ * module
+ */
+#include <sys/rwlock.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+
+extern krwlock_t kiconv_csmapper_lock;
+extern krwlock_t kiconv_mapper_lock;
+extern krwlock_t kiconv_iconv_lock;
+extern kmutex_t _citrus_LC_CTYPE_mutex;
+
+MODULE(MODULE_CLASS_MISC, kiconv, NULL);
+
+static int
+kiconv_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		rw_init(&kiconv_csmapper_lock);
+		rw_init(&kiconv_mapper_lock);
+		rw_init(&kiconv_iconv_lock);
+		mutex_init(&_citrus_LC_CTYPE_mutex, MUTEX_DEFAULT, IPL_NONE);
+		kiconv_attach_ops(&kiconv_ops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_ops(&kiconv_ops);
+		/* XXX:XXXNONAKA MEMORY LEAK!!! must purge cache!!! */
+		mutex_destroy(&_citrus_LC_CTYPE_mutex);
+		rw_destroy(&kiconv_csmapper_lock);
+		rw_destroy(&kiconv_mapper_lock);
+		rw_destroy(&kiconv_iconv_lock);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/kiconv.h src/sys/kiconv/kiconv.h
--- src.orig/sys/kiconv/kiconv.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/kiconv.h	2011-07-12 09:42:47.000000000 +0900
@@ -0,0 +1,203 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by NONAKA Kimihiro.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef	_KICONV_KICONV_H_
+#define	_KICONV_KICONV_H_
+
+#include <sys/malloc.h>
+#include <sys/pool.h>
+#include <sys/kiconv.h>
+
+#ifdef KICONV_DEBUG
+extern int kiconv_debug;
+#define	KICONV_DBG(s)		printf s
+#define	KICONV_DBGN(n,s)	if (kiconv_debug >= (n)) printf s
+#else
+#define	KICONV_DBG(s)		do {} while (/*CONSTCOND*/0)
+#define	KICONV_DBGN(n,s)	do {} while (/*CONSTCOND*/0)
+#endif
+
+/* kiconv interface */
+struct kiconv_ops {
+	kiconv_t	(*iconv_open)(const char *, const char *, int *);
+	int		(*iconv_close)(kiconv_t, int *);
+	size_t		(*iconv)(kiconv_t, const char **, size_t *, char **,
+			    size_t *, uint32_t, size_t *, int *);
+	int		(*iconv_get_list)(char ***, size_t *, int *);
+	void		(*iconv_free_list)(char **, size_t);
+
+	klocale_t	(*newlocale)(const char *, int *);
+	int		(*freelocale)(klocale_t, int *);
+
+	int		(*mbsinit)(const mbstate_t *, klocale_t, int *);
+	size_t		(*mbrlen)(const char * __restrict, size_t,
+			    mbstate_t * __restrict, klocale_t, int *);
+	size_t		(*mbrtowc)(wchar_t * __restrict,
+			    const char * __restrict, size_t, mbstate_t *,
+			    klocale_t, int *);
+	size_t		(*mbsrtowcs)(wchar_t * __restrict,
+			    const char ** __restrict, size_t,
+			    mbstate_t * __restrict, klocale_t, int *);
+	size_t		(*wcrtomb)(char * __restrict, wchar_t wc,
+			    mbstate_t * __restrict, klocale_t, int *);
+	size_t		(*wcsrtombs)(char * __restrict,
+			    const wchar_t ** __restrict, size_t,
+			    mbstate_t * __restrict, klocale_t, int *);
+	wint_t		(*btowc)(int, klocale_t, int *);
+	int		(*wctob)(wint_t, klocale_t, int *);
+	int		(*wcwidth)(wchar_t, klocale_t);
+	int		(*wcswidth)(const wchar_t *, size_t, klocale_t);
+
+	int		(*iswalnum)(wint_t, klocale_t);
+	int		(*iswalpha)(wint_t, klocale_t);
+	int		(*iswblank)(wint_t, klocale_t);
+	int		(*iswcntrl)(wint_t, klocale_t);
+	int		(*iswdigit)(wint_t, klocale_t);
+	int		(*iswgraph)(wint_t, klocale_t);
+	int		(*iswlower)(wint_t, klocale_t);
+	int		(*iswprint)(wint_t, klocale_t);
+	int		(*iswpunct)(wint_t, klocale_t);
+	int		(*iswspace)(wint_t, klocale_t);
+	int		(*iswupper)(wint_t, klocale_t);
+	int		(*iswxdigit)(wint_t, klocale_t);
+	wint_t		(*towupper)(wint_t, klocale_t);
+	wint_t		(*towlower)(wint_t, klocale_t);
+	wctype_t	(*wctype)(const char *, klocale_t);
+	wctrans_t	(*wctrans)(const char *, klocale_t);
+	int		(*iswctype)(wint_t, wctype_t, klocale_t);
+	wint_t		(*towctrans)(wint_t, wctrans_t, klocale_t);
+};
+
+void kiconv_attach_ops(struct kiconv_ops *);
+void kiconv_detach_ops(struct kiconv_ops *);
+
+/* encoding/iconv/mapper module interface */
+struct kiconv_getops {
+	char kg_name[32];
+	void *kg_getops;
+	TAILQ_ENTRY(kiconv_getops) kg_list;
+};
+
+void kiconv_attach_getops(struct kiconv_getops *);
+void kiconv_detach_getops(struct kiconv_getops *);
+struct kiconv_getops *kiconv_find_getops(const char *);
+
+#define	KICONV_GETOPS(name)					\
+static struct kiconv_getops kiconv_##name##_getops = {		\
+	.kg_name = #name,					\
+	.kg_getops = _citrus_##name##_getops,			\
+};
+
+/* kiconv's malloc type */
+MALLOC_DECLARE(M_KICONV);
+
+/* LINE_MAX pool and cache */
+extern pool_cache_t kiconv_linebuf_cache;
+#define KICONV_LINEBUF_GET()     pool_cache_get(kiconv_linebuf_cache, PR_WAITOK)
+#define KICONV_LINEBUF_PUT(pnb)  pool_cache_put(kiconv_linebuf_cache, (pnb))
+
+/* from paths.h */
+#define	_PATH_CSMAPPER	"/usr/share/i18n/csmapper"
+#define	_PATH_ESDB	"/usr/share/i18n/esdb"
+#define	_PATH_ICONV	"/usr/share/i18n/iconv"
+#define	_PATH_LOCALE	"/usr/share/locale"
+
+/* XXX */
+static __inline char *
+strdup(const char *src)
+{
+	size_t sz;
+	char *dst;
+
+	KASSERT(src != NULL);
+
+	sz = strlen(src) + 1;
+	dst = malloc(sz, M_KICONV, M_WAITOK);
+	strlcpy(dst, src, sz);
+
+	return dst;
+}
+
+extern size_t __mb_cur_max;
+extern size_t __mb_len_max_runtime;
+
+#define	_DEFAULT_LOCALE 	"en_US.UTF-8"
+#define	_DEFAULT_ENCODING	"UTF-8"
+
+#ifdef _KICONV_LOCAL
+kiconv_t	_kiconv_open(const char *, const char *, int *);
+int		_kiconv_close(kiconv_t, int *);
+size_t		_kiconv_conv(kiconv_t, const char **, size_t *, char **,
+		    size_t *, uint32_t, size_t *, int *);
+
+klocale_t	_kiconv_newlocale(const char *, int *);
+int		_kiconv_freelocale(klocale_t, int *);
+
+int		_kiconv_mbsinit(const mbstate_t *, klocale_t, int *);
+size_t		_kiconv_mbrlen(const char * __restrict, size_t,
+		    mbstate_t * __restrict, klocale_t, int *);
+size_t		_kiconv_mbrtowc(wchar_t * __restrict,
+		    const char * __restrict, size_t, mbstate_t *,
+		    klocale_t, int *);
+size_t		_kiconv_mbsrtowcs(wchar_t * __restrict,
+		    const char ** __restrict, size_t,
+		    mbstate_t * __restrict, klocale_t, int *);
+size_t		_kiconv_wcrtomb(char * __restrict, wchar_t wc,
+		    mbstate_t * __restrict, klocale_t, int *);
+size_t		_kiconv_wcsrtombs(char * __restrict,
+		    const wchar_t ** __restrict, size_t,
+		    mbstate_t * __restrict, klocale_t, int *);
+wint_t		_kiconv_btowc(int, klocale_t, int *);
+int		_kiconv_wctob(wint_t, klocale_t, int *);
+int		_kiconv_wcwidth(wchar_t, klocale_t);
+int		_kiconv_wcswidth(const wchar_t *, size_t, klocale_t);
+
+int		_kiconv_iswalnum(wint_t, klocale_t);
+int		_kiconv_iswalpha(wint_t, klocale_t);
+int		_kiconv_iswblank(wint_t, klocale_t);
+int		_kiconv_iswcntrl(wint_t, klocale_t);
+int		_kiconv_iswdigit(wint_t, klocale_t);
+int		_kiconv_iswgraph(wint_t, klocale_t);
+int		_kiconv_iswlower(wint_t, klocale_t);
+int		_kiconv_iswprint(wint_t, klocale_t);
+int		_kiconv_iswpunct(wint_t, klocale_t);
+int		_kiconv_iswspace(wint_t, klocale_t);
+int		_kiconv_iswupper(wint_t, klocale_t);
+int		_kiconv_iswxdigit(wint_t, klocale_t);
+wint_t		_kiconv_towupper(wint_t, klocale_t);
+wint_t		_kiconv_towlower(wint_t, klocale_t);
+wctype_t	_kiconv_wctype(const char *, klocale_t);
+wctrans_t	_kiconv_wctrans(const char *, klocale_t);
+int		_kiconv_iswctype(wint_t, wctype_t, klocale_t);
+wint_t		_kiconv_towctrans(wint_t, wctrans_t, klocale_t);
+#endif
+
+#endif	/* _KICONV_KICONV_H_ */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/locale.c src/sys/kiconv/locale.c
--- src.orig/sys/kiconv/locale.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/locale.c	2011-06-04 22:13:29.000000000 +0900
@@ -0,0 +1,76 @@
+/* $NetBSD$ */
+/* NetBSD: current_locale.c,v 1.2 2009/01/11 02:46:28 christos Exp */
+/* NetBSD: global_locale.c,v 1.11 2010/06/19 13:26:52 tnozaki Exp */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: current_locale.c,v 1.2 2009/01/11 02:46:28 christos Exp");
+__RCSID("NetBSD: global_locale.c,v 1.11 2010/06/19 13:26:52 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+
+#include "runetype_local.h"
+#include "setlocale_local.h"
+
+const char *_PathLocale = _PATH_LOCALE;
+size_t __mb_cur_max = 1;
+size_t __mb_len_max_runtime = MB_LEN_MAX;
+
+static struct _klocale_impl_t *__current_locale = &_global_locale;
+
+struct _klocale_impl_t **
+_current_locale(void)
+{
+
+	return &__current_locale;
+}
+
+static struct _klocale_cache_t _global_cache = {
+    .ctype_tab   = (const unsigned char *)&_C_ctype_[0],
+    .tolower_tab = (const short *)&_C_tolower_[0],
+    .toupper_tab = (const short *)&_C_toupper_[0],
+    .mb_cur_max = (size_t)1,
+};
+
+struct _klocale_impl_t _global_locale = {
+    .cache = &_global_cache,
+    .query = { _C_LOCALE },
+    .part_name = {
+	[(size_t)LC_CTYPE] = _C_LOCALE,
+    },
+    .part_impl = {
+	[(size_t)LC_CTYPE] = (_klocale_part_t)
+	    __UNCONST(&_DefaultRuneLocale),
+    },
+};
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/Makefile.inc src/sys/kiconv/modules/Makefile.inc
--- src.orig/sys/kiconv/modules/Makefile.inc	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/Makefile.inc	2011-06-03 14:46:07.000000000 +0900
@@ -0,0 +1,6 @@
+# $NetBSD$
+
+.PATH:	${S}/kiconv/modules
+
+CPPFLAGS+= -I${S}/kiconv
+CPPFLAGS+= -I${S}/kiconv/modules
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_big5.c src/sys/kiconv/modules/citrus_big5.c
--- src.orig/sys/kiconv/modules/citrus_big5.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_big5.c	2011-06-03 21:20:48.000000000 +0900
@@ -0,0 +1,555 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_big5.c,v 1.13 2011/05/23 14:53:46 joerg Exp	*/
+
+/*-
+ * Copyright (c)2002, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_big5.c,v 1.13 2011/05/23 14:53:46 joerg Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_big5.h"
+
+#include "citrus_prop.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+	char ch[2];
+	int chlen;
+} _BIG5State;
+
+typedef struct _BIG5Exclude {
+	TAILQ_ENTRY(_BIG5Exclude) entry;
+	wint_t start, end;
+} _BIG5Exclude;
+
+typedef TAILQ_HEAD(_BIG5ExcludeList, _BIG5Exclude) _BIG5ExcludeList;
+
+typedef struct {
+	int cell[0x100];
+	_BIG5ExcludeList excludes;
+} _BIG5EncodingInfo;
+
+typedef struct {
+	_BIG5EncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_BIG5State	s_mblen;
+		_BIG5State	s_mbrlen;
+		_BIG5State	s_mbrtowc;
+		_BIG5State	s_mbtowc;
+		_BIG5State	s_mbsrtowcs;
+		_BIG5State	s_wcrtomb;
+		_BIG5State	s_wcsrtombs;
+		_BIG5State	s_wctomb;
+	} states;
+} _BIG5CTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_BIG5_##m
+#define _ENCODING_INFO			_BIG5EncodingInfo
+#define _CTYPE_INFO			_BIG5CTypeInfo
+#define _ENCODING_STATE			_BIG5State
+#define _ENCODING_MB_CUR_MAX(_ei_)	2
+#define _ENCODING_IS_STATE_DEPENDENT	0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+
+static __inline void
+/*ARGSUSED*/
+_citrus_BIG5_init_state(_BIG5EncodingInfo * __restrict ei,
+			_BIG5State * __restrict s)
+{
+	memset(s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_BIG5_pack_state(_BIG5EncodingInfo * __restrict ei,
+			void * __restrict pspriv,
+			const _BIG5State * __restrict s)
+{
+	memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_BIG5_unpack_state(_BIG5EncodingInfo * __restrict ei,
+			  _BIG5State * __restrict s,
+			  const void * __restrict pspriv)
+{
+	memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static __inline int
+_citrus_BIG5_check(_BIG5EncodingInfo *ei, u_int c)
+{
+	_DIAGASSERT(ei != NULL);
+
+	return (ei->cell[c & 0xFF] & 0x1) ? 2 : 1;
+}
+
+static __inline int
+_citrus_BIG5_check2(_BIG5EncodingInfo *ei, u_int c)
+{
+	_DIAGASSERT(ei != NULL);
+
+	return (ei->cell[c & 0xFF] & 0x2) ? 1 : 0;
+}
+
+static __inline int
+_citrus_BIG5_check_excludes(_BIG5EncodingInfo *ei, wint_t c)
+{
+	_BIG5Exclude *exclude;
+
+	_DIAGASSERT(ei != NULL);
+
+	TAILQ_FOREACH(exclude, &ei->excludes, entry) {
+		if (c >= exclude->start && c <= exclude->end)
+			return EILSEQ;
+	}
+	return 0;
+}
+
+static int
+_citrus_BIG5_fill_rowcol(void ** __restrict ctx, const char * __restrict s,
+	uint64_t start, uint64_t end)
+{
+	_BIG5EncodingInfo *ei;
+	int i;
+	uint64_t n;
+
+	_DIAGASSERT(ctx != NULL && *ctx != NULL);
+
+	if (start > 0xFF || end > 0xFF)
+		return EINVAL;
+	ei = (_BIG5EncodingInfo *)*ctx;
+	i = strcmp("row", s) ? 1 : 0;
+	i = 1 << i;
+	for (n = start; n <= end; ++n)
+		ei->cell[n & 0xFF] |= i;
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_BIG5_fill_excludes(void ** __restrict ctx, const char * __restrict s,
+	uint64_t start, uint64_t end)
+{
+	_BIG5EncodingInfo *ei;
+	_BIG5Exclude *exclude;
+
+	_DIAGASSERT(ctx != NULL && *ctx != NULL);
+
+	if (start > 0xFFFF || end > 0xFFFF)
+		return EINVAL;
+	ei = (_BIG5EncodingInfo *)*ctx;
+	exclude = TAILQ_LAST(&ei->excludes, _BIG5ExcludeList);
+	if (exclude != NULL && (wint_t)start <= exclude->end)
+		return EINVAL;
+	exclude = (void *)malloc(sizeof(*exclude), M_KICONV, M_WAITOK);
+	exclude->start = (wint_t)start;
+	exclude->end = (wint_t)end;
+	TAILQ_INSERT_TAIL(&ei->excludes, exclude, entry);
+
+	return 0;
+}
+
+static const _citrus_prop_hint_t root_hints[] = {
+    _CITRUS_PROP_HINT_NUM("row", &_citrus_BIG5_fill_rowcol),
+    _CITRUS_PROP_HINT_NUM("col", &_citrus_BIG5_fill_rowcol),
+    _CITRUS_PROP_HINT_NUM("excludes", &_citrus_BIG5_fill_excludes),
+    _CITRUS_PROP_HINT_END
+};
+
+static void
+/*ARGSUSED*/
+_citrus_BIG5_encoding_module_uninit(_BIG5EncodingInfo *ei)
+{
+	_BIG5Exclude *exclude;
+
+	_DIAGASSERT(ei != NULL);
+
+	while ((exclude = TAILQ_FIRST(&ei->excludes)) != NULL) {
+		TAILQ_REMOVE(&ei->excludes, exclude, entry);
+		free(exclude, M_WAITOK);
+	}
+}
+
+static int
+/*ARGSUSED*/
+_citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei,
+				  const void * __restrict var, size_t lenvar)
+{
+	int err;
+	const char *s;
+	_BIG5EncodingInfo *tmp = ei, **ctx = &tmp; /* XXX: gcc */
+
+	_DIAGASSERT(ei != NULL);
+
+	memset((void *)ei, 0, sizeof(*ei));
+	TAILQ_INIT(&ei->excludes);
+
+	if (lenvar > 0 && var != NULL) {
+		s = _bcs_skip_ws_len((const char *)var, &lenvar);
+		if (lenvar > 0 && *s != '\0') {
+			err = _citrus_prop_parse_variable(
+			    root_hints, (void *)ei, s, lenvar);
+			if (err == 0)
+				return 0;
+
+			_citrus_BIG5_encoding_module_uninit(ei);
+			memset((void *)ei, 0, sizeof(*ei));
+			TAILQ_INIT(&ei->excludes);
+		}
+	}
+
+	/* fallback Big5-1984, for backward compatibility. */
+	_citrus_BIG5_fill_rowcol((void **)ctx, "row", 0xA1, 0xFE);
+	_citrus_BIG5_fill_rowcol((void **)ctx, "col", 0x40, 0x7E);
+	_citrus_BIG5_fill_rowcol((void **)ctx, "col", 0xA1, 0xFE);
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_BIG5_mbrtowc_priv(_BIG5EncodingInfo * __restrict ei,
+			  wchar_t * __restrict pwc,
+			  const char ** __restrict s, size_t n,
+			  _BIG5State * __restrict psenc,
+			  size_t * __restrict nresult)
+{
+	wchar_t wchar;
+	int c;
+	int chlenbak;
+	const char *s0;
+
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(s != NULL && *s != NULL);
+
+	s0 = *s;
+
+	if (s0 == NULL) {
+		_citrus_BIG5_init_state(ei, psenc);
+		*nresult = 0;
+		return (0);
+	}
+
+	chlenbak = psenc->chlen;
+
+	/* make sure we have the first byte in the buffer */
+	switch (psenc->chlen) {
+	case 0:
+		if (n < 1)
+			goto restart;
+		psenc->ch[0] = *s0++;
+		psenc->chlen = 1;
+		n--;
+		break;
+	case 1:
+		break;
+	default:
+		/* illegal state */
+		goto ilseq;
+	}
+
+	c = _citrus_BIG5_check(ei, psenc->ch[0] & 0xff);
+	if (c == 0)
+		goto ilseq;
+	while (psenc->chlen < c) {
+		if (n < 1) {
+			goto restart;
+		}
+		psenc->ch[psenc->chlen] = *s0++;
+		psenc->chlen++;
+		n--;
+	}
+
+	switch (c) {
+	case 1:
+		wchar = psenc->ch[0] & 0xff;
+		break;
+	case 2:
+		if (!_citrus_BIG5_check2(ei, psenc->ch[1] & 0xff))
+			goto ilseq;
+		wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
+		break;
+	default:
+		/* illegal state */
+		goto ilseq;
+	}
+
+	if (_citrus_BIG5_check_excludes(ei, (wint_t)wchar) != 0)
+		goto ilseq;
+
+	*s = s0;
+	psenc->chlen = 0;
+	if (pwc)
+		*pwc = wchar;
+	if (!wchar)
+		*nresult = 0;
+	else
+		*nresult = c - chlenbak;
+
+	return (0);
+
+ilseq:
+	psenc->chlen = 0;
+	*nresult = (size_t)-1;
+	return (EILSEQ);
+
+restart:
+	*s = s0;
+	*nresult = (size_t)-2;
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei,
+			  char * __restrict s,
+			  size_t n, wchar_t wc, _BIG5State * __restrict psenc,
+			  size_t * __restrict nresult)
+{
+	size_t l, ret;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(s != NULL);
+
+	/* check invalid sequence */
+	if (wc & ~0xffff ||
+	    _citrus_BIG5_check_excludes(ei, (wint_t)wc) != 0) {
+		ret = EILSEQ;
+		goto err;
+	}
+
+	if (wc & 0x8000) {
+		if (_citrus_BIG5_check(ei, (wc >> 8) & 0xff) != 2 ||
+		    !_citrus_BIG5_check2(ei, wc & 0xff)) {
+			ret = EILSEQ;
+			goto err;
+		}
+		l = 2;
+	} else {
+		if (wc & ~0xff || !_citrus_BIG5_check(ei, wc & 0xff)) {
+			ret = EILSEQ;
+			goto err;
+		}
+		l = 1;
+	}
+
+	if (n < l) {
+		/* bound check failure */
+		ret = E2BIG;
+		goto err;
+	}
+
+	if (l == 2) {
+		s[0] = (wc >> 8) & 0xff;
+		s[1] = wc & 0xff;
+	} else
+		s[0] = wc & 0xff;
+
+	*nresult = l;
+
+	return 0;
+
+err:
+	*nresult = (size_t)-1;
+	return ret;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_BIG5_stdenc_wctocs(_BIG5EncodingInfo * __restrict ei,
+			   _csid_t * __restrict csid,
+			   _index_t * __restrict idx, wchar_t wc)
+{
+
+	_DIAGASSERT(csid != NULL && idx != NULL);
+
+	*csid = (wc < 0x100) ? 0 : 1;
+	*idx = (_index_t)wc;
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_BIG5_stdenc_cstowc(_BIG5EncodingInfo * __restrict ei,
+			   wchar_t * __restrict wc,
+			   _csid_t csid, _index_t idx)
+{
+	_DIAGASSERT(wc != NULL);
+
+	switch (csid) {
+	case 0:
+	case 1:
+		*wc = (wchar_t)idx;
+		break;
+	default:
+		return EILSEQ;
+	}
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_BIG5_stdenc_get_state_desc_generic(_BIG5EncodingInfo * __restrict ei,
+					   _BIG5State * __restrict psenc,
+					   int * __restrict rstate)
+{
+
+	if (psenc->chlen == 0)
+		*rstate = _STDENC_SDGEN_INITIAL;
+	else
+		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(BIG5);
+_CITRUS_CTYPE_DEF_OPS(BIG5);
+
+#include "citrus_ctype_template.h"
+
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(BIG5);
+_CITRUS_STDENC_DEF_OPS(BIG5);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(BIG5_ctype);
+KICONV_GETOPS(BIG5_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_BIG5, "kiconv");
+
+static int
+kiconv_BIG5_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_BIG5_ctype_getops);
+		kiconv_attach_getops(&kiconv_BIG5_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_BIG5_stdenc_getops);
+		kiconv_detach_getops(&kiconv_BIG5_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_big5.h src/sys/kiconv/modules/citrus_big5.h
--- src.orig/sys/kiconv/modules/citrus_big5.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_big5.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/*	$NetBSD: citrus_big5.h,v 1.2 2003/06/25 09:51:41 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_BIG5_H_
+#define _CITRUS_BIG5_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(BIG5);
+_CITRUS_STDENC_GETOPS_FUNC(BIG5);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_dechanyu.c src/sys/kiconv/modules/citrus_dechanyu.c
--- src.orig/sys/kiconv/modules/citrus_dechanyu.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_dechanyu.c	2011-06-03 21:20:51.000000000 +0900
@@ -0,0 +1,485 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_dechanyu.c,v 1.3 2008/06/14 16:01:07 tnozaki Exp */
+
+/*-
+ * Copyright (c)2007 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_dechanyu.c,v 1.3 2008/06/14 16:01:07 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_dechanyu.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+	int chlen;
+	char ch[4];
+} _DECHanyuState;
+
+typedef struct {
+	int dummy;
+} _DECHanyuEncodingInfo;
+
+typedef struct {
+	_DECHanyuEncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_DECHanyuState	s_mblen;
+		_DECHanyuState	s_mbrlen;
+		_DECHanyuState	s_mbrtowc;
+		_DECHanyuState	s_mbtowc;
+		_DECHanyuState	s_mbsrtowcs;
+		_DECHanyuState	s_wcrtomb;
+		_DECHanyuState	s_wcsrtombs;
+		_DECHanyuState	s_wctomb;
+	} states;
+} _DECHanyuCTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.__CONCAT(s_,_func_)
+
+#define _FUNCNAME(m)			__CONCAT(_citrus_DECHanyu_,m)
+#define _ENCODING_INFO			_DECHanyuEncodingInfo
+#define _CTYPE_INFO			_DECHanyuCTypeInfo
+#define _ENCODING_STATE			_DECHanyuState
+#define _ENCODING_MB_CUR_MAX(_ei_)		4
+#define _ENCODING_IS_STATE_DEPENDENT		0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_DECHanyu_init_state(_DECHanyuEncodingInfo * __restrict ei,
+	_DECHanyuState * __restrict psenc)
+{
+	/* ei may be null */
+	_DIAGASSERT(psenc != NULL);
+
+	psenc->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_DECHanyu_pack_state(_DECHanyuEncodingInfo * __restrict ei,
+	void * __restrict pspriv,
+	const _DECHanyuState * __restrict psenc)
+{
+	/* ei may be null */
+	_DIAGASSERT(pspriv != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_DECHanyu_unpack_state(_DECHanyuEncodingInfo * __restrict ei,
+	_DECHanyuState * __restrict psenc,
+	const void * __restrict pspriv)
+{
+	/* ei may be null */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(pspriv != NULL);
+
+	memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static void
+/*ARGSUSED*/
+_citrus_DECHanyu_encoding_module_uninit(_DECHanyuEncodingInfo *ei)
+{
+	/* ei may be null */
+}
+
+static int
+/*ARGSUSED*/
+_citrus_DECHanyu_encoding_module_init(_DECHanyuEncodingInfo * __restrict ei,
+	const void * __restrict var, size_t lenvar)
+{
+	/* ei may be null */
+	return 0;
+}
+
+static __inline int
+is_singlebyte(int c)
+{
+	return c <= 0x7F;
+}
+
+static __inline int
+is_leadbyte(int c)
+{
+	return c >= 0xA1 && c <= 0xFE;
+}
+
+static __inline int
+is_trailbyte(int c)
+{
+	c &= ~0x80;
+	return c >= 0x21 && c <= 0x7E;
+}
+
+static __inline int
+is_hanyu1(int c)
+{
+	return c == 0xC2;
+}
+
+static __inline int
+is_hanyu2(int c)
+{
+	return c == 0xCB;
+}
+
+#define HANYUBIT	0xC2CB0000
+
+static __inline int
+is_94charset(int c)
+{
+	return c >= 0x21 && c <= 0x7E;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_DECHanyu_mbrtowc_priv(_DECHanyuEncodingInfo * __restrict ei,
+	wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
+	_DECHanyuState * __restrict psenc, size_t * __restrict nresult)
+{
+	const char *s0;
+	int ch;
+	wchar_t wc;
+
+	/* ei may be unused */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (*s == NULL) {
+		_citrus_DECHanyu_init_state(ei, psenc);
+		*nresult = _ENCODING_IS_STATE_DEPENDENT;
+		return 0;
+	} 
+	s0 = *s;
+
+	wc = (wchar_t)0;
+	switch (psenc->chlen) {
+	case 0:
+		if (n-- < 1)
+			goto restart;
+		ch = *s0++ & 0xFF;
+		if (is_singlebyte(ch) != 0) {
+			if (pwc != NULL)
+				*pwc = (wchar_t)ch;
+			*nresult = (size_t)((ch == 0) ? 0 : 1);
+			*s = s0;
+			return 0;
+		}
+		if (is_leadbyte(ch) == 0)
+			goto ilseq;
+		psenc->ch[psenc->chlen++] = ch;
+		break;
+	case 1:
+		ch = psenc->ch[0] & 0xFF;
+		if (is_leadbyte(ch) == 0)
+			return EINVAL;
+		break;
+	case 2: case 3:
+		ch = psenc->ch[0] & 0xFF;
+		if (is_hanyu1(ch) != 0) {
+			ch = psenc->ch[1] & 0xFF;
+			if (is_hanyu2(ch) != 0) {
+				wc |= (wchar_t)HANYUBIT;
+				break;
+			}
+		}
+	/*FALLTHROUGH*/
+	default:
+		return EINVAL;
+	}
+
+	switch (psenc->chlen) {
+	case 1:
+		if (is_hanyu1(ch) != 0) {
+			if (n-- < 1)
+				goto restart;
+			ch = *s0++ & 0xFF;
+			if (is_hanyu2(ch) == 0)
+				goto ilseq;
+			psenc->ch[psenc->chlen++] = ch;
+			wc |= (wchar_t)HANYUBIT;
+			if (n-- < 1)
+				goto restart;
+			ch = *s0++ & 0xFF;
+			if (is_leadbyte(ch) == 0)
+				goto ilseq;
+			psenc->ch[psenc->chlen++] = ch;
+		}
+		break;
+	case 2:
+		if (n-- < 1)
+			goto restart;
+		ch = *s0++ & 0xFF;
+		if (is_leadbyte(ch) == 0)
+			goto ilseq;
+		psenc->ch[psenc->chlen++] = ch;
+		break;
+	case 3:
+		ch = psenc->ch[2] & 0xFF;
+		if (is_leadbyte(ch) == 0)
+			return EINVAL;
+	}
+	if (n-- < 1)
+		goto restart;
+	wc |= (wchar_t)(ch << 8);
+	ch = *s0++ & 0xFF;
+	if (is_trailbyte(ch) == 0)
+		goto ilseq;
+	wc |= (wchar_t)ch;
+	if (pwc != NULL)
+		*pwc = wc;
+	*nresult = (size_t)(s0 - *s);
+	*s = s0;
+	psenc->chlen = 0;
+
+	return 0;
+
+restart:
+	*nresult = (size_t)-2;
+	*s = s0;
+	return 0;
+
+ilseq:
+	*nresult = (size_t)-1;
+	return EILSEQ;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_DECHanyu_wcrtomb_priv(_DECHanyuEncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, wchar_t wc,
+	_DECHanyuState * __restrict psenc, size_t * __restrict nresult)
+{
+	int ch;
+
+	/* ei may be unused */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (psenc->chlen != 0)
+		return EINVAL;
+
+	/* XXX: assume wchar_t as int */
+	if ((uint32_t)wc <= 0x7F) {
+		ch = wc & 0xFF;
+	} else {
+		if ((uint32_t)wc > 0xFFFF) {
+			if ((wc & ~0xFFFF) != HANYUBIT)
+				goto ilseq;
+			psenc->ch[psenc->chlen++] = (wc >> 24) & 0xFF;
+			psenc->ch[psenc->chlen++] = (wc >> 16) & 0xFF;
+			wc &= 0xFFFF;
+		}
+		ch = (wc >> 8) & 0xFF;
+		if (!is_leadbyte(ch))
+			goto ilseq;
+		psenc->ch[psenc->chlen++] = ch;
+		ch = wc & 0xFF;
+		if (is_trailbyte(ch) == 0)
+			goto ilseq;
+	}
+	psenc->ch[psenc->chlen++] = ch;
+	if (n < psenc->chlen) {
+		*nresult = (size_t)-1;
+		return E2BIG;
+	}
+	memcpy(s, psenc->ch, psenc->chlen);
+	*nresult = psenc->chlen;
+	psenc->chlen = 0;
+
+	return 0;
+
+ilseq:
+	*nresult = (size_t)-1;
+	return EILSEQ;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_DECHanyu_stdenc_wctocs(_DECHanyuEncodingInfo * __restrict ei,
+	_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+	int plane;
+	wchar_t mask;
+
+	/* ei may be unused */
+	_DIAGASSERT(csid != NULL);
+	_DIAGASSERT(idx != NULL);
+
+	plane = 0;
+	mask = 0x7F;
+	/* XXX: assume wchar_t as int */
+	if ((uint32_t)wc > 0x7F) {
+		if ((uint32_t)wc > 0xFFFF) {
+			if ((wc & ~0xFFFF) != HANYUBIT)
+				return EILSEQ;
+			plane += 2;
+		}
+		if (is_leadbyte((wc >> 8) & 0xFF) == 0 ||
+		    is_trailbyte(wc & 0xFF) == 0)
+			return EILSEQ;
+		plane += (wc & 0x80) ? 1 : 2;
+		mask |= 0x7F00;
+	}
+	*csid = plane;
+	*idx = (_index_t)(wc & mask);
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_DECHanyu_stdenc_cstowc(_DECHanyuEncodingInfo * __restrict ei,
+	wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+	/* ei may be unused */
+	_DIAGASSERT(wc != NULL);
+
+	if (csid == 0) {
+		if (idx > 0x7F)
+			return EILSEQ;
+	} else if (csid <= 4) {
+		if (is_94charset(idx >> 8) == 0)
+			return EILSEQ;
+		if (is_94charset(idx & 0xFF) == 0)
+			return EILSEQ;
+		if (csid % 2)
+			idx |= 0x80;
+		idx |= 0x8000;
+		if (csid > 2)
+			idx |= HANYUBIT;
+	} else
+		return EILSEQ;
+	*wc = (wchar_t)idx;
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_DECHanyu_stdenc_get_state_desc_generic(
+	_DECHanyuEncodingInfo * __restrict ei,
+	_DECHanyuState * __restrict psenc, int * __restrict rstate)
+{
+	/* ei may be unused */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(rstate != NULL);
+
+	*rstate = (psenc->chlen == 0)
+	    ? _STDENC_SDGEN_INITIAL
+	    : _STDENC_SDGEN_INCOMPLETE_CHAR;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(DECHanyu);
+_CITRUS_CTYPE_DEF_OPS(DECHanyu);
+
+#include "citrus_ctype_template.h"
+
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(DECHanyu);
+_CITRUS_STDENC_DEF_OPS(DECHanyu);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(DECHanyu_ctype);
+KICONV_GETOPS(DECHanyu_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_DECHanyu, "kiconv");
+
+static int
+kiconv_DECHanyu_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_DECHanyu_ctype_getops);
+		kiconv_attach_getops(&kiconv_DECHanyu_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_DECHanyu_stdenc_getops);
+		kiconv_detach_getops(&kiconv_DECHanyu_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_dechanyu.h src/sys/kiconv/modules/citrus_dechanyu.h
--- src.orig/sys/kiconv/modules/citrus_dechanyu.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_dechanyu.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/* $NetBSD: citrus_dechanyu.h,v 1.1 2007/04/01 18:52:32 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DECHANYU_H_
+#define _CITRUS_DECHANYU_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(DECHanyu);
+_CITRUS_STDENC_GETOPS_FUNC(DECHanyu);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_euc.c src/sys/kiconv/modules/citrus_euc.c
--- src.orig/sys/kiconv/modules/citrus_euc.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_euc.c	2011-06-03 21:20:55.000000000 +0900
@@ -0,0 +1,480 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_euc.c,v 1.14 2009/01/11 02:46:24 christos Exp	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_euc.c,v 1.14 2009/01/11 02:46:24 christos Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <sys/types.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_euc.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+	char ch[3];
+	int chlen;
+} _EUCState;
+
+typedef struct {
+	unsigned	count[4];
+	wchar_t		bits[4];
+	wchar_t		mask;
+	unsigned	mb_cur_max;
+} _EUCEncodingInfo;
+
+typedef struct {
+	_EUCEncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_EUCState	s_mblen;
+		_EUCState	s_mbrlen;
+		_EUCState	s_mbrtowc;
+		_EUCState	s_mbtowc;
+		_EUCState	s_mbsrtowcs;
+		_EUCState	s_wcrtomb;
+		_EUCState	s_wcsrtombs;
+		_EUCState	s_wctomb;
+	} states;
+} _EUCCTypeInfo;
+
+#define	_SS2	0x008e
+#define	_SS3	0x008f
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_EUC_##m
+#define _ENCODING_INFO			_EUCEncodingInfo
+#define _CTYPE_INFO			_EUCCTypeInfo
+#define _ENCODING_STATE			_EUCState
+#define _ENCODING_MB_CUR_MAX(_ei_)	(_ei_)->mb_cur_max
+#define _ENCODING_IS_STATE_DEPENDENT	0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+
+static __inline int
+_citrus_EUC_cs(unsigned int c)
+{
+	c &= 0xff;
+
+	return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
+}
+
+static __inline int
+_citrus_EUC_parse_variable(_EUCEncodingInfo *ei,
+			   const void *var, size_t lenvar)
+{
+	const char *v;
+	char *e;
+	int x;
+
+	/* parse variable string */
+	if (!var)
+		return (EFTYPE);
+
+	v = (const char *) var;
+
+	while (*v == ' ' || *v == '\t')
+		++v;
+
+	ei->mb_cur_max = 1;
+	for (x = 0; x < 4; ++x) {
+		ei->count[x] = (int)_bcs_strtol(v, &e, 0);
+		if (v == e || !(v = e) || ei->count[x]<1 || ei->count[x]>4) {
+			return (EFTYPE);
+		}
+		if (ei->mb_cur_max < ei->count[x])
+			ei->mb_cur_max = ei->count[x];
+		while (*v == ' ' || *v == '\t')
+			++v;
+		ei->bits[x] = (int)_bcs_strtol(v, &e, 0);
+		if (v == e || !(v = e)) {
+			return (EFTYPE);
+		}
+		while (*v == ' ' || *v == '\t')
+			++v;
+	}
+	ei->mask = (int)_bcs_strtol(v, &e, 0);
+	if (v == e || !(v = e)) {
+		return (EFTYPE);
+	}
+
+	return 0;
+}
+
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUC_init_state(_EUCEncodingInfo *ei, _EUCState *s)
+{
+	memset(s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUC_pack_state(_EUCEncodingInfo *ei, void *pspriv, const _EUCState *s)
+{
+	memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUC_unpack_state(_EUCEncodingInfo *ei, _EUCState *s,
+			 const void *pspriv)
+{
+	memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+_citrus_EUC_mbrtowc_priv(_EUCEncodingInfo *ei, wchar_t *pwc, const char **s,
+			 size_t n, _EUCState *psenc, size_t *nresult)
+{
+	wchar_t wchar;
+	int c, cs, len;
+	int chlenbak;
+	const char *s0, *s1 = NULL;
+
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(s != NULL);
+
+	s0 = *s;
+
+	if (s0 == NULL) {
+		_citrus_EUC_init_state(ei, psenc);
+		*nresult = 0; /* state independent */
+		return (0);
+	}
+
+	chlenbak = psenc->chlen;
+
+	/* make sure we have the first byte in the buffer */
+	switch (psenc->chlen) {
+	case 0:
+		if (n < 1)
+			goto restart;
+		psenc->ch[0] = *s0++;
+		psenc->chlen = 1;
+		n--;
+		break;
+	case 1:
+	case 2:
+		break;
+	default:
+		/* illgeal state */
+		goto encoding_error;
+	}
+
+	c = ei->count[cs = _citrus_EUC_cs(psenc->ch[0] & 0xff)];
+	if (c == 0)
+		goto encoding_error;
+	while (psenc->chlen < c) {
+		if (n < 1)
+			goto restart;
+		psenc->ch[psenc->chlen] = *s0++;
+		psenc->chlen++;
+		n--;
+	}
+	*s = s0;
+
+	switch (cs) {
+	case 3:
+	case 2:
+		/* skip SS2/SS3 */
+		len = c - 1;
+		s1 = &psenc->ch[1];
+		break;
+	case 1:
+	case 0:
+		len = c;
+		s1 = &psenc->ch[0];
+		break;
+	default:
+		goto encoding_error;
+	}
+	wchar = 0;
+	while (len-- > 0)
+		wchar = (wchar << 8) | (*s1++ & 0xff);
+	wchar = (wchar & ~ei->mask) | ei->bits[cs];
+
+	psenc->chlen = 0;
+	if (pwc)
+		*pwc = wchar;
+
+	if (!wchar) {
+		*nresult = 0;
+	} else {
+		*nresult = (size_t)(c - chlenbak);
+	}
+
+	return 0;
+
+encoding_error:
+	psenc->chlen = 0;
+	*nresult = (size_t)-1;
+	return (EILSEQ);
+
+restart:
+	*nresult = (size_t)-2;
+	*s = s0;
+	return (0);
+}
+
+static int
+_citrus_EUC_wcrtomb_priv(_EUCEncodingInfo *ei, char *s, size_t n, wchar_t wc,
+			 _EUCState *psenc, size_t *nresult)
+{
+	wchar_t m, nm;
+	int cs, i, ret;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(s != NULL);
+
+	m = wc & ei->mask;
+	nm = wc & ~m;
+
+	for (cs = 0;
+	     cs < sizeof(ei->count)/sizeof(ei->count[0]);
+	     cs++) {
+		if (m == ei->bits[cs])
+			break;
+	}
+	/* fallback case - not sure if it is necessary */
+	if (cs == sizeof(ei->count)/sizeof(ei->count[0]))
+		cs = 1;
+
+	i = ei->count[cs];
+	if (n < i) {
+		ret = E2BIG;
+		goto err;
+	}
+	m = (cs) ? 0x80 : 0x00;
+	switch (cs) {
+	case 2:
+		*s++ = _SS2;
+		i--;
+		break;
+	case 3:
+		*s++ = _SS3;
+		i--;
+		break;
+	}
+
+	while (i-- > 0)
+		*s++ = ((nm >> (i << 3)) & 0xff) | m;
+
+	*nresult = (size_t)ei->count[cs];
+	return 0;
+
+err:
+	*nresult = (size_t)-1;
+	return ret;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUC_stdenc_wctocs(_EUCEncodingInfo * __restrict ei,
+			  _csid_t * __restrict csid,
+			  _index_t * __restrict idx, wchar_t wc)
+{
+	wchar_t m, nm;
+
+	_DIAGASSERT(ei != NULL && csid != NULL && idx != NULL);
+
+	m = wc & ei->mask;
+	nm = wc & ~m;
+
+	*csid = (_citrus_csid_t)m;
+	*idx  = (_citrus_index_t)nm;
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUC_stdenc_cstowc(_EUCEncodingInfo * __restrict ei,
+			  wchar_t * __restrict wc,
+			  _csid_t csid, _index_t idx)
+{
+
+	_DIAGASSERT(ei != NULL && wc != NULL);
+
+	if ((csid & ~ei->mask) != 0 || (idx & ei->mask) != 0)
+		return (EINVAL);
+
+	*wc = (wchar_t)csid | (wchar_t)idx;
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUC_stdenc_get_state_desc_generic(_EUCEncodingInfo * __restrict ei,
+					  _EUCState * __restrict psenc,
+					  int * __restrict rstate)
+{
+
+	if (psenc->chlen == 0)
+		*rstate = _STDENC_SDGEN_INITIAL;
+	else
+		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_EUC_encoding_module_init(_EUCEncodingInfo * __restrict ei,
+				 const void * __restrict var, size_t lenvar)
+{
+
+	_DIAGASSERT(ei != NULL);
+
+	return (_citrus_EUC_parse_variable(ei, var, lenvar));
+}
+
+static void
+/*ARGSUSED*/
+_citrus_EUC_encoding_module_uninit(_EUCEncodingInfo * __restrict ei)
+{
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(EUC);
+_CITRUS_CTYPE_DEF_OPS(EUC);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(EUC);
+_CITRUS_STDENC_DEF_OPS(EUC);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(EUC_ctype);
+KICONV_GETOPS(EUC_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_EUC, "kiconv");
+
+static int
+kiconv_EUC_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_EUC_ctype_getops);
+		kiconv_attach_getops(&kiconv_EUC_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_EUC_stdenc_getops);
+		kiconv_detach_getops(&kiconv_EUC_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_euc.h src/sys/kiconv/modules/citrus_euc.h
--- src.orig/sys/kiconv/modules/citrus_euc.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_euc.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/*	$NetBSD: citrus_euc.h,v 1.2 2003/06/25 09:51:42 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_EUC_H_
+#define _CITRUS_EUC_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(EUC);
+_CITRUS_STDENC_GETOPS_FUNC(EUC);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_euctw.c src/sys/kiconv/modules/citrus_euctw.c
--- src.orig/sys/kiconv/modules/citrus_euctw.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_euctw.c	2011-06-03 21:20:58.000000000 +0900
@@ -0,0 +1,472 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_euctw.c,v 1.11 2008/06/14 16:01:07 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	$Citrus: xpg4dl/FreeBSD/lib/libc/locale/euctw.c,v 1.13 2001/06/21 01:51:44 yamt Exp $
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_euctw.c,v 1.11 2008/06/14 16:01:07 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <sys/types.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_euctw.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+	char ch[4];
+	int chlen;
+} _EUCTWState;
+
+typedef struct {
+	int dummy;
+} _EUCTWEncodingInfo;
+typedef struct {
+	_EUCTWEncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_EUCTWState	s_mblen;
+		_EUCTWState	s_mbrlen;
+		_EUCTWState	s_mbrtowc;
+		_EUCTWState	s_mbtowc;
+		_EUCTWState	s_mbsrtowcs;
+		_EUCTWState	s_wcrtomb;
+		_EUCTWState	s_wcsrtombs;
+		_EUCTWState	s_wctomb;
+	} states;
+} _EUCTWCTypeInfo;
+
+#define	_SS2	0x008e
+#define	_SS3	0x008f
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_EUCTW_##m
+#define _ENCODING_INFO			_EUCTWEncodingInfo
+#define _CTYPE_INFO			_EUCTWCTypeInfo
+#define _ENCODING_STATE			_EUCTWState
+#define _ENCODING_MB_CUR_MAX(_ei_)	4
+#define _ENCODING_IS_STATE_DEPENDENT	0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+static __inline int
+_citrus_EUCTW_cs(u_int c)
+{
+	c &= 0xff;
+
+	return ((c & 0x80) ? (c == _SS2 ? 2 : 1) : 0);
+}
+
+static __inline int
+_citrus_EUCTW_count(int cs)
+{
+	switch (cs) {
+	case 0:
+		return 1;
+	case 1:
+		return 2;
+	case 2:
+		return 4;
+	case 3:
+		panic("kiconv_EUCTW: invalid count");
+		/*NOTREACHED*/
+	}
+	return 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUCTW_init_state(_EUCTWEncodingInfo * __restrict ei,
+			 _EUCTWState * __restrict s)
+{
+	memset(s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUCTW_pack_state(_EUCTWEncodingInfo * __restrict ei,
+			 void * __restrict pspriv,
+			 const _EUCTWState * __restrict s)
+{
+	memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUCTW_unpack_state(_EUCTWEncodingInfo * __restrict ei,
+			   _EUCTWState * __restrict s,
+			   const void * __restrict pspriv)
+{
+	memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_EUCTW_encoding_module_init(_EUCTWEncodingInfo * __restrict ei,
+				   const void * __restrict var, size_t lenvar)
+{
+
+	_DIAGASSERT(ei != NULL);
+
+	memset((void *)ei, 0, sizeof(*ei));
+
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_EUCTW_encoding_module_uninit(_EUCTWEncodingInfo *ei)
+{
+}
+
+static int
+_citrus_EUCTW_mbrtowc_priv(_EUCTWEncodingInfo * __restrict ei,
+			   wchar_t * __restrict pwc,
+			   const char ** __restrict s,
+			   size_t n, _EUCTWState * __restrict psenc,
+			   size_t * __restrict nresult)
+{
+	wchar_t wchar;
+	int c, cs;
+	int chlenbak;
+	const char *s0;
+
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(s != NULL);
+
+	s0 = *s;
+
+	if (s0 == NULL) {
+		_citrus_EUCTW_init_state(ei, psenc);
+		*nresult = 0; /* state independent */
+		return (0);
+	}
+
+	chlenbak = psenc->chlen;
+
+	/* make sure we have the first byte in the buffer */
+	switch (psenc->chlen) {
+	case 0:
+		if (n < 1)
+			goto restart;
+		psenc->ch[0] = *s0++;
+		psenc->chlen = 1;
+		n--;
+		break;
+	case 1:
+	case 2:
+		break;
+	default:
+		/* illgeal state */
+		goto ilseq;
+	}
+
+	c = _citrus_EUCTW_count(cs = _citrus_EUCTW_cs(psenc->ch[0] & 0xff));
+	if (c == 0)
+		goto ilseq;
+	while (psenc->chlen < c) {
+		if (n < 1)
+			goto ilseq;
+		psenc->ch[psenc->chlen] = *s0++;
+		psenc->chlen++;
+		n--;
+	}
+
+	wchar = 0;
+	switch (cs) {
+	case 0:
+		if (psenc->ch[0] & 0x80)
+			goto ilseq;
+		wchar = psenc->ch[0] & 0xff;
+		break;
+	case 1:
+		if (!(psenc->ch[0] & 0x80) || !(psenc->ch[1] & 0x80))
+			goto ilseq;
+		wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
+		wchar |= 'G' << 24;
+		break;
+	case 2:
+		if ((u_char)psenc->ch[1] < 0xa1 || 0xa7 < (u_char)psenc->ch[1])
+			goto ilseq;
+		if (!(psenc->ch[2] & 0x80) || !(psenc->ch[3] & 0x80))
+			goto ilseq;
+		wchar = ((psenc->ch[2] & 0xff) << 8) | (psenc->ch[3] & 0xff);
+		wchar |= ('G' + psenc->ch[1] - 0xa1) << 24;
+		break;
+	default:
+		goto ilseq;
+	}
+
+	*s = s0;
+	psenc->chlen = 0;
+
+	if (pwc)
+		*pwc = wchar;
+
+	if (!wchar)
+		*nresult = 0;
+	else
+		*nresult = c - chlenbak;
+
+	return (0);
+
+ilseq:
+	psenc->chlen = 0;
+	*nresult = (size_t)-1;
+	return (EILSEQ);
+
+restart:
+	*s = s0;
+	*nresult = (size_t)-1;
+	return (0);
+}
+
+static int
+_citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei,
+			   char * __restrict s, size_t n, wchar_t wc,
+			   _EUCTWState * __restrict psenc,
+			   size_t * __restrict nresult)
+{
+	wchar_t cs = wc & 0x7f000080;
+	wchar_t v;
+	int i, len, clen, ret;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(s != NULL);
+
+	clen = 1;
+	if (wc & 0x00007f00)
+		clen = 2;
+	if ((wc & 0x007f0000) && !(wc & 0x00800000))
+		clen = 3;
+
+	if (clen == 1 && cs == 0x00000000) {
+		/* ASCII */
+		len = 1;
+		if (n < len) {
+			ret = E2BIG;
+			goto err;
+		}
+		v = wc & 0x0000007f;
+	} else if (clen == 2 && cs == ('G' << 24)) {
+		/* CNS-11643-1 */
+		len = 2;
+		if (n < len) {
+			ret = E2BIG;
+			goto err;
+		}
+		v = wc & 0x00007f7f;
+		v |= 0x00008080;
+	} else if (clen == 2 && 'H' <= (cs >> 24) && (cs >> 24) <= 'M') {
+		/* CNS-11643-[2-7] */
+		len = 4;
+		if (n < len) {
+			ret = E2BIG;
+			goto err;
+		}
+		*s++ = _SS2;
+		*s++ = (cs >> 24) - 'H' + 0xa2;
+		v = wc & 0x00007f7f;
+		v |= 0x00008080;
+	} else {
+		ret = EILSEQ;
+		goto err;
+	}
+
+	i = clen;
+	while (i-- > 0)
+		*s++ = (v >> (i << 3)) & 0xff;
+
+	*nresult = len;
+	return 0;
+
+err:
+	*nresult = (size_t)-1;
+	return ret;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUCTW_stdenc_wctocs(_EUCTWEncodingInfo * __restrict ei,
+			    _csid_t * __restrict csid,
+			    _index_t * __restrict idx, wchar_t wc)
+{
+
+	_DIAGASSERT(ei != NULL && csid != NULL && idx != NULL);
+
+	*csid = (_csid_t)(wc >> 24) & 0xFF;
+	*idx  = (_index_t)(wc & 0x7F7F);
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUCTW_stdenc_cstowc(_EUCTWEncodingInfo * __restrict ei,
+			    wchar_t * __restrict wc,
+			    _csid_t csid, _index_t idx)
+{
+
+	_DIAGASSERT(ei != NULL && wc != NULL);
+
+	if (csid==0) {
+		if ((idx & ~0x7F) != 0)
+			return (EINVAL);
+		*wc = (wchar_t)idx;
+	} else {
+		if (csid < 'G' || csid > 'M' || (idx & ~0x7F7F) != 0)
+			return (EINVAL);
+		*wc = (wchar_t)idx | ((wchar_t)csid<<24);
+	}
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUCTW_stdenc_get_state_desc_generic(_EUCTWEncodingInfo * __restrict ei,
+					    _EUCTWState * __restrict psenc,
+					    int * __restrict rstate)
+{
+
+	if (psenc->chlen == 0)
+		*rstate = _STDENC_SDGEN_INITIAL;
+	else
+		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(EUCTW);
+_CITRUS_CTYPE_DEF_OPS(EUCTW);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(EUCTW);
+_CITRUS_STDENC_DEF_OPS(EUCTW);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(EUCTW_ctype);
+KICONV_GETOPS(EUCTW_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_EUCTW, "kiconv");
+
+static int
+kiconv_EUCTW_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_EUCTW_ctype_getops);
+		kiconv_attach_getops(&kiconv_EUCTW_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_EUCTW_stdenc_getops);
+		kiconv_detach_getops(&kiconv_EUCTW_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_euctw.h src/sys/kiconv/modules/citrus_euctw.h
--- src.orig/sys/kiconv/modules/citrus_euctw.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_euctw.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/*	$NetBSD: citrus_euctw.h,v 1.2 2003/06/25 09:51:42 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_EUCTW_H_
+#define _CITRUS_EUCTW_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(EUCTW);
+_CITRUS_STDENC_GETOPS_FUNC(EUCTW);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_gbk2k.c src/sys/kiconv/modules/citrus_gbk2k.c
--- src.orig/sys/kiconv/modules/citrus_gbk2k.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_gbk2k.c	2011-06-03 21:21:14.000000000 +0900
@@ -0,0 +1,514 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_gbk2k.c,v 1.7 2008/06/14 16:01:07 tnozaki Exp */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_gbk2k.c,v 1.7 2008/06/14 16:01:07 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <sys/types.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_gbk2k.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct _GBK2KState {
+	char ch[4];
+	int chlen;
+} _GBK2KState;
+
+typedef struct {
+	int mb_cur_max;
+} _GBK2KEncodingInfo;
+
+typedef struct {
+	_GBK2KEncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_GBK2KState	s_mblen;
+		_GBK2KState	s_mbrlen;
+		_GBK2KState	s_mbrtowc;
+		_GBK2KState	s_mbtowc;
+		_GBK2KState	s_mbsrtowcs;
+		_GBK2KState	s_wcrtomb;
+		_GBK2KState	s_wcsrtombs;
+		_GBK2KState	s_wctomb;
+	} states;
+} _GBK2KCTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_GBK2K_##m
+#define _ENCODING_INFO			_GBK2KEncodingInfo
+#define _CTYPE_INFO			_GBK2KCTypeInfo
+#define _ENCODING_STATE			_GBK2KState
+#define _ENCODING_MB_CUR_MAX(_ei_)	(_ei_)->mb_cur_max
+#define _ENCODING_IS_STATE_DEPENDENT	0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_GBK2K_init_state(_GBK2KEncodingInfo * __restrict ei,
+			 _GBK2KState * __restrict s)
+{
+	memset(s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_GBK2K_pack_state(_GBK2KEncodingInfo * __restrict ei,
+			 void * __restrict pspriv,
+			 const _GBK2KState * __restrict s)
+{
+	memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_GBK2K_unpack_state(_GBK2KEncodingInfo * __restrict ei,
+			   _GBK2KState * __restrict s,
+			   const void * __restrict pspriv)
+{
+	memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static  __inline int
+_mb_singlebyte(int c)
+{
+	c &= 0xff;
+	return (c <= 0x7f);
+}
+
+static __inline int
+_mb_leadbyte(int c)
+{
+	c &= 0xff;
+	return (0x81 <= c && c <= 0xfe);
+}
+
+static __inline int
+_mb_trailbyte(int c)
+{
+	c &= 0xff;
+	return ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfe));
+}
+
+static __inline int
+_mb_surrogate(int c)
+{
+	c &= 0xff;
+	return (0x30 <= c && c <= 0x39);
+}
+
+static __inline int
+_mb_count(wchar_t v)
+{
+	u_int32_t c;
+
+	c = (u_int32_t)v; /* XXX */
+	if (!(c & 0xffffff00))
+		return (1);
+	if (!(c & 0xffff0000))
+		return (2);
+	return (4);
+}
+
+#define	_PSENC		(psenc->ch[psenc->chlen - 1])
+#define	_PUSH_PSENC(c)	(psenc->ch[psenc->chlen++] = (c))
+
+static int
+_citrus_GBK2K_mbrtowc_priv(_GBK2KEncodingInfo * __restrict ei,
+			   wchar_t * __restrict pwc,
+			   const char ** __restrict s, size_t n,
+			   _GBK2KState * __restrict psenc,
+			   size_t * __restrict nresult)
+{
+	int chlenbak, len;
+	const char *s0, *s1;
+	wchar_t wc;
+
+	_DIAGASSERT(ei != NULL);
+	/* pwc may be NULL */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	s0 = *s;
+
+	if (s0 == NULL) {
+		/* _citrus_GBK2K_init_state(ei, psenc); */
+		psenc->chlen = 0;
+		*nresult = 0;
+		return (0);
+	}
+
+	chlenbak = psenc->chlen;
+
+	switch (psenc->chlen) {
+	case 3:
+		if (!_mb_leadbyte (_PSENC))
+			goto invalid;
+	/* FALLTHROUGH */
+	case 2:
+		if (!_mb_surrogate(_PSENC) || _mb_trailbyte(_PSENC))
+			goto invalid;
+	/* FALLTHROUGH */
+	case 1:
+		if (!_mb_leadbyte (_PSENC))
+			goto invalid;
+	/* FALLTHOROUGH */
+	case 0:
+		break;
+	default:
+		goto invalid;
+	}
+
+	for (;;) {
+		if (n-- < 1)
+			goto restart;
+
+		_PUSH_PSENC(*s0++);
+
+		switch (psenc->chlen) {
+		case 1:
+			if (_mb_singlebyte(_PSENC))
+				goto convert;
+			if (_mb_leadbyte  (_PSENC))
+				continue;
+			goto ilseq;
+		case 2:
+			if (_mb_trailbyte (_PSENC))
+				goto convert;
+			if (ei->mb_cur_max == 4 &&
+			    _mb_surrogate (_PSENC))
+				continue;
+			goto ilseq;
+		case 3:
+			if (_mb_leadbyte  (_PSENC))
+				continue;
+			goto ilseq;
+		case 4:
+			if (_mb_surrogate (_PSENC))
+				goto convert;
+			goto ilseq;
+		}
+	}
+
+convert:
+	len = psenc->chlen;
+	s1  = &psenc->ch[0];
+	wc  = 0;
+	while (len-- > 0)
+		wc = (wc << 8) | (*s1++ & 0xff);
+
+	if (pwc != NULL)
+		*pwc = wc;
+	*s = s0;
+	*nresult = (wc == 0) ? 0 : psenc->chlen - chlenbak; 
+	/* _citrus_GBK2K_init_state(ei, psenc); */
+	psenc->chlen = 0;
+
+	return (0);
+
+restart:
+	*s = s0;
+	*nresult = (size_t)-2;
+
+	return (0);
+
+invalid:
+	return (EINVAL);
+
+ilseq:
+	*nresult = (size_t)-1;
+	return (EILSEQ);
+}
+
+static int
+_citrus_GBK2K_wcrtomb_priv(_GBK2KEncodingInfo * __restrict ei,
+			   char * __restrict s, size_t n, wchar_t wc,
+			   _GBK2KState * __restrict psenc,
+			   size_t * __restrict nresult)
+{
+	int len, ret;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	if (psenc->chlen != 0) {
+		ret = EINVAL;
+		goto err;
+	}
+
+	len = _mb_count(wc);
+	if (n < len) {
+		ret = E2BIG;
+		goto err;
+	}
+
+	switch (len) {
+	case 1:
+		if (!_mb_singlebyte(_PUSH_PSENC(wc     ))) {
+			ret = EILSEQ;
+			goto err;
+		}
+		break;
+	case 2:
+		if (!_mb_leadbyte  (_PUSH_PSENC(wc >> 8)) ||
+		    !_mb_trailbyte (_PUSH_PSENC(wc     ))) {
+			ret = EILSEQ;
+			goto err;
+		}
+		break;
+	case 4:
+		if (ei->mb_cur_max != 4 ||
+		    !_mb_leadbyte  (_PUSH_PSENC(wc >> 24)) ||
+		    !_mb_surrogate (_PUSH_PSENC(wc >> 16)) ||
+		    !_mb_leadbyte  (_PUSH_PSENC(wc >>  8)) ||
+		    !_mb_surrogate (_PUSH_PSENC(wc      ))) {
+			ret = EILSEQ;
+			goto err;
+		}
+		break;
+	}
+
+	_DIAGASSERT(len == psenc->chlen);
+
+	memcpy(s, psenc->ch, psenc->chlen);
+	*nresult = psenc->chlen;
+	/* _citrus_GBK2K_init_state(ei, psenc); */
+	psenc->chlen = 0;
+
+	return (0);
+
+err:
+	*nresult = (size_t)-1;
+	return ret;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_GBK2K_stdenc_wctocs(_GBK2KEncodingInfo * __restrict ei,
+			    _csid_t * __restrict csid,
+			    _index_t * __restrict idx, wchar_t wc)
+{
+	u_int8_t ch, cl;
+
+	_DIAGASSERT(csid != NULL && idx != NULL);
+
+	if ((u_int32_t)wc<0x80) {
+		/* ISO646 */
+		*csid = 0;
+		*idx = (_index_t)wc;
+	} else if ((u_int32_t)wc>=0x10000) {
+		/* GBKUCS : XXX */
+		*csid = 3;
+		*idx = (_index_t)wc;
+	} else {
+		ch = (u_int8_t)(wc >> 8);
+		cl = (u_int8_t)wc;
+		if (ch>=0xA1 && cl>=0xA1) {
+			/* EUC G1 */
+			*csid = 1;
+			*idx = (_index_t)wc & 0x7F7FU;
+		} else {
+			/* extended area (0x8140-) */
+			*csid = 2;
+			*idx = (_index_t)wc;
+		}
+	}
+		
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_GBK2K_stdenc_cstowc(_GBK2KEncodingInfo * __restrict ei,
+			    wchar_t * __restrict wc,
+			    _csid_t csid, _index_t idx)
+{
+
+	_DIAGASSERT(wc != NULL);
+
+	switch (csid) {
+	case 0:
+		/* ISO646 */
+		*wc = (wchar_t)idx;
+		break;
+	case 1:
+		/* EUC G1 */
+		*wc = (wchar_t)idx | 0x8080U;
+		break;
+	case 2:
+		/* extended area */
+		*wc = (wchar_t)idx;
+		break;
+	case 3:
+		/* GBKUCS : XXX */
+		if (ei->mb_cur_max != 4)
+			return EINVAL;
+		*wc = (wchar_t)idx;
+		break;
+	default:
+		return EILSEQ;
+	}
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_GBK2K_stdenc_get_state_desc_generic(_GBK2KEncodingInfo * __restrict ei,
+					    _GBK2KState * __restrict psenc,
+					    int * __restrict rstate)
+{
+
+	if (psenc->chlen == 0)
+		*rstate = _STDENC_SDGEN_INITIAL;
+	else
+		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_GBK2K_encoding_module_init(_GBK2KEncodingInfo * __restrict ei,
+				   const void * __restrict var, size_t lenvar)
+{
+	const char *p;
+
+	_DIAGASSERT(ei != NULL);
+
+	p = var;
+#define MATCH(x, act)                                           \
+do {                                                            \
+        if (lenvar >= (sizeof(#x)-1) &&                         \
+            _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) {       \
+                act;                                            \
+                lenvar -= sizeof(#x)-1;                         \
+                p += sizeof(#x)-1;                              \
+        }                                                       \
+} while (/*CONSTCOND*/0)
+	memset((void *)ei, 0, sizeof(*ei));
+	ei->mb_cur_max = 4;
+	while (lenvar>0) {
+		switch (_bcs_tolower(*p)) {
+		case '2':
+			MATCH("2byte", ei->mb_cur_max = 2);
+			break;
+		}
+		p++;
+		lenvar--;
+	}
+
+	return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_GBK2K_encoding_module_uninit(_GBK2KEncodingInfo *ei)
+{
+}
+
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(GBK2K);
+_CITRUS_CTYPE_DEF_OPS(GBK2K);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(GBK2K);
+_CITRUS_STDENC_DEF_OPS(GBK2K);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(GBK2K_ctype);
+KICONV_GETOPS(GBK2K_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_GBK2K, "kiconv");
+
+static int
+kiconv_GBK2K_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_GBK2K_ctype_getops);
+		kiconv_attach_getops(&kiconv_GBK2K_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_GBK2K_stdenc_getops);
+		kiconv_detach_getops(&kiconv_GBK2K_ctype_getops);
+		return 0;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_gbk2k.h src/sys/kiconv/modules/citrus_gbk2k.h
--- src.orig/sys/kiconv/modules/citrus_gbk2k.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_gbk2k.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/* $NetBSD: citrus_gbk2k.h,v 1.2 2003/06/25 09:51:43 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_GBK2K_H_
+#define _CITRUS_GBK2K_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(GBK2K);
+_CITRUS_STDENC_GETOPS_FUNC(GBK2K);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_hz.c src/sys/kiconv/modules/citrus_hz.c
--- src.orig/sys/kiconv/modules/citrus_hz.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_hz.c	2011-06-03 21:21:17.000000000 +0900
@@ -0,0 +1,766 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_hz.c,v 1.2 2008/06/14 16:01:07 tnozaki Exp */
+
+/*-
+ * Copyright (c)2004, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_hz.c,v 1.2 2008/06/14 16:01:07 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+
+#undef	SET
+#else
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <wchar.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+
+#include "citrus_hz.h"
+#include "citrus_prop.h"
+
+/*
+ * wchar_t mapping:
+ *
+ * CTRL/ASCII	00000000 00000000 00000000 gxxxxxxx
+ * GB2312	00000000 00000000 0xxxxxxx gxxxxxxx
+ * 94/96*n (~M)	0mmmmmmm 0xxxxxxx 0xxxxxxx gxxxxxxx
+ */
+
+#define ESCAPE_CHAR	'~'
+
+typedef enum {
+	CTRL = 0, ASCII = 1, GB2312 = 2, CS94 = 3, CS96 = 4
+} charset_t;
+
+typedef struct {
+	int start, end, width;
+} range_t;
+
+static const range_t ranges[] = {
+#define RANGE(start, end) { start, end, (end - start) + 1 }
+/* CTRL   */ RANGE(0x00, 0x1F),
+/* ASCII  */ RANGE(0x20, 0x7F),
+/* GB2312 */ RANGE(0x21, 0x7E),
+/* CS94   */ RANGE(0x21, 0x7E),
+/* CS96   */ RANGE(0x20, 0x7F),
+#undef RANGE
+};
+
+typedef struct escape_t escape_t;
+typedef struct {
+	charset_t charset;
+	size_t length;
+#define ROWCOL_MAX	3
+	escape_t *escape;
+} graphic_t;
+
+typedef TAILQ_HEAD(escape_list, escape_t) escape_list;
+struct escape_t {
+	TAILQ_ENTRY(escape_t) entry;
+	int ch;
+	graphic_t *left, *right;
+	escape_list *set;
+};
+
+#define GL(escape)	((escape)->left)
+#define GR(escape)	((escape)->right)
+#define SET(escape)	((escape)->set)
+#define ESC(escape)	((escape)->ch)
+#define INIT(escape)	(TAILQ_FIRST(SET(escape)))
+
+static __inline escape_t *
+find_escape(escape_list *set, int ch)
+{
+	escape_t *escape;
+
+	_DIAGASSERT(set != NULL);
+
+	TAILQ_FOREACH(escape, set, entry) {
+		if (ESC(escape) == ch)
+			break;
+	}
+
+	return escape;
+}
+
+typedef struct {
+	escape_list e0, e1;
+	graphic_t *ascii, *gb2312;
+} _HZEncodingInfo;
+
+#define E0SET(ei)	(&(ei)->e0)
+#define E1SET(ei)	(&(ei)->e1)
+#define INIT0(ei)	(TAILQ_FIRST(E0SET(ei)))
+#define INIT1(ei)	(TAILQ_FIRST(E1SET(ei)))
+
+typedef struct {
+	int chlen;
+	char ch[ROWCOL_MAX];
+	escape_t *inuse;
+} _HZState;
+
+typedef struct {
+	_HZEncodingInfo		ei;
+	struct {
+		/* for future multi-locale facility */
+		_HZState	s_mblen;
+		_HZState	s_mbrlen;
+		_HZState	s_mbrtowc;
+		_HZState	s_mbtowc;
+		_HZState	s_mbsrtowcs;
+		_HZState	s_wcrtomb;
+		_HZState	s_wcsrtombs;
+		_HZState	s_wctomb;
+	} states;
+} _HZCTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_HZ_##m
+#define _ENCODING_INFO			_HZEncodingInfo
+#define _CTYPE_INFO			_HZCTypeInfo
+#define _ENCODING_STATE			_HZState
+#define _ENCODING_MB_CUR_MAX(_ei_)	MB_LEN_MAX
+#define _ENCODING_IS_STATE_DEPENDENT		1
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	((_ps_)->inuse == NULL)
+
+static __inline void
+_citrus_HZ_init_state(_HZEncodingInfo * __restrict ei,
+	_HZState * __restrict psenc)
+{
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	psenc->chlen = 0;
+	psenc->inuse = INIT0(ei);
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_HZ_pack_state(_HZEncodingInfo * __restrict ei,
+	void *__restrict pspriv, const _HZState * __restrict psenc)
+{
+	/* ei may be unused */
+	_DIAGASSERT(pspriv != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_HZ_unpack_state(_HZEncodingInfo * __restrict ei,
+	_HZState * __restrict psenc, const void * __restrict pspriv)
+{
+	/* ei may be unused */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(pspriv != NULL);
+
+	memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static int
+_citrus_HZ_mbrtowc_priv(_HZEncodingInfo * __restrict ei,
+	wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
+	_HZState * __restrict psenc, size_t * __restrict nresult)
+{
+	const char *s0;
+	wchar_t wc;
+	int bit, head, tail, len, ch;
+	graphic_t *graphic;
+	escape_t *candidate, *init;
+	const range_t *range;
+
+	_DIAGASSERT(ei != NULL);
+	/* pwc may be null */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (*s == NULL) {
+		_citrus_HZ_init_state(ei, psenc);
+		*nresult = 1;
+		return 0;
+	}
+	s0 = *s;
+	if (psenc->chlen < 0 || psenc->inuse == NULL)
+		return EINVAL;
+
+	wc = (wchar_t)0;
+	bit = head = tail = 0;
+	graphic = NULL;
+	for (len = 0; len <= MB_LEN_MAX; /**/) {
+		if (psenc->chlen == tail) {
+			if (n-- < 1) {
+				*s = s0;
+				*nresult = (size_t)-2;
+				return 0;
+			}
+			psenc->ch[psenc->chlen++] = *s0++;
+			++len;
+		}
+		ch = (unsigned char)psenc->ch[tail++];
+		if (tail == 1) {
+			if ((ch & ~0x80) <= 0x1F) {
+				if (psenc->inuse != INIT0(ei))
+					break;
+				wc = (wchar_t)ch;
+				goto done;
+			}
+			if (ch & 0x80) {
+				graphic = GR(psenc->inuse);
+				bit = 0x80;
+				ch &= ~0x80;
+			} else {
+				graphic = GL(psenc->inuse);
+				if (ch == ESCAPE_CHAR)
+					continue;
+				bit = 0x0;
+			}
+			if (graphic == NULL)
+				break;
+		} else if (tail == 2 && psenc->ch[0] == ESCAPE_CHAR) {
+			if (tail < psenc->chlen)
+				return EINVAL;
+			if (ch == ESCAPE_CHAR) {
+				++head;
+			} else if (ch == '\n') {
+				if (psenc->inuse != INIT0(ei))
+					break;
+				tail = psenc->chlen = 0;
+				continue;
+			} else {
+				candidate = NULL;
+				init = INIT0(ei);
+				_DIAGASSERT(init != NULL);
+				if (psenc->inuse == init) {
+					init = INIT1(ei);
+				} else if (INIT(psenc->inuse) == init) {
+					if (ESC(init) != ch)
+						break;
+					candidate = init;
+				}
+				if (candidate == NULL) {
+					candidate = find_escape(
+					    SET(psenc->inuse), ch);
+					if (candidate == NULL) {
+						if (init == NULL ||
+						    ESC(init) != ch)
+							break;
+						candidate = init;
+					}
+				}
+				psenc->inuse = candidate;
+				tail = psenc->chlen = 0;
+				continue;
+			}
+		} else if (ch & 0x80) {
+			if (graphic != GR(psenc->inuse))
+				break;
+			ch &= ~0x80;
+		} else {
+			if (graphic != GL(psenc->inuse))
+				break;
+		}
+		_DIAGASSERT(graphic != NULL);
+		range = &ranges[(size_t)graphic->charset];
+		if (range->start > ch || range->end < ch)
+			break;
+		wc <<= 8;
+		wc |= ch;
+		if (graphic->length == (tail - head)) {
+			if (graphic->charset > GB2312)
+				bit |= ESC(psenc->inuse) << 24;
+			wc |= bit;
+			goto done;
+		}
+	}
+	*nresult = (size_t)-1;
+	return EILSEQ;
+done:
+	if (tail < psenc->chlen)
+		return EINVAL;
+	*s = s0;
+	if (pwc != NULL)
+		*pwc = wc;
+	psenc->chlen = 0;
+	*nresult = (wc == 0) ? 0 : len;
+
+	return 0;
+}
+
+static int
+_citrus_HZ_wcrtomb_priv(_HZEncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, wchar_t wc,
+	_HZState * __restrict psenc, size_t * __restrict nresult)
+{
+	int bit, ch;
+	escape_t *candidate, *init;
+	graphic_t *graphic;
+	size_t len;
+	const range_t *range;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (psenc->chlen != 0 || psenc->inuse == NULL)
+		return EINVAL;
+	if (wc & 0x80) {
+		bit = 0x80;
+		wc &= ~0x80;
+	} else {
+		bit = 0x0;
+	}
+	if ((uint32_t)wc <= 0x1F) {
+		candidate = INIT0(ei);
+		graphic = (bit == 0)
+		    ? candidate->left : candidate->right;
+		if (graphic == NULL)
+			goto ilseq;
+		range = &ranges[(size_t)CTRL];
+		len = 1;
+	} else if ((uint32_t)wc <= 0x7F) {
+		graphic = ei->ascii;
+		if (graphic == NULL)
+			goto ilseq;
+		candidate = graphic->escape;
+		range = &ranges[(size_t)graphic->charset];
+		len = graphic->length;
+	} else if ((uint32_t)wc <= 0x7F7F) {
+		graphic = ei->gb2312;
+		if (graphic == NULL)
+			goto ilseq;
+		candidate = graphic->escape;
+		range = &ranges[(size_t)graphic->charset];
+		len = graphic->length;
+	} else {
+		ch = (wc >> 24) & 0xFF;
+		candidate = find_escape(E0SET(ei), ch);
+		if (candidate == NULL) {
+			candidate = find_escape(E1SET(ei), ch);
+			if (candidate == NULL)
+				goto ilseq;
+		}
+		wc &= ~0xFF000000;
+		graphic = (bit == 0)
+		    ? candidate->left : candidate->right;
+		if (graphic == NULL)
+			goto ilseq;
+		range = &ranges[(size_t)graphic->charset];
+		len = graphic->length;
+	}
+	if (psenc->inuse != candidate) {
+		init = INIT0(ei);
+		if (SET(psenc->inuse) == SET(candidate)) {
+			if (INIT(psenc->inuse) != init ||
+			    psenc->inuse == init || candidate == init)
+				init = NULL;
+		} else if (candidate == (init = INIT(candidate))) {
+			init = NULL;
+		}
+		if (init != NULL) {
+			if (n < 2)
+				return E2BIG;
+			n -= 2;
+			psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
+			psenc->ch[psenc->chlen++] = ESC(init);
+		}
+		if (n < 2)
+			return E2BIG;
+		n -= 2;
+		psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
+		psenc->ch[psenc->chlen++] = ESC(candidate);
+		psenc->inuse = candidate;
+	}
+	if (n < len)
+		return E2BIG;
+	while (len-- > 0) {
+		ch = (wc >> (len * 8)) & 0xFF;
+		if (range->start > ch || range->end < ch)
+			goto ilseq;
+		psenc->ch[psenc->chlen++] = ch | bit;
+	}
+	memcpy(s, psenc->ch, psenc->chlen);
+	*nresult = psenc->chlen;
+	psenc->chlen = 0;
+
+	return 0;
+
+ilseq:
+	*nresult = (size_t)-1;
+	return EILSEQ;
+}
+
+static __inline int
+_citrus_HZ_put_state_reset(_HZEncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, _HZState * __restrict psenc,
+	size_t * __restrict nresult)
+{
+	escape_t *candidate;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (psenc->chlen != 0 || psenc->inuse == NULL)
+		return EINVAL;
+	candidate = INIT0(ei);
+	if (psenc->inuse != candidate) {
+		if (n < 2)
+			return E2BIG;
+		n -= 2;
+		psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
+		psenc->ch[psenc->chlen++] = ESC(candidate);
+	}
+	if (n < 1)
+		return E2BIG;
+	if (psenc->chlen > 0)
+		memcpy(s, psenc->ch, psenc->chlen);
+	*nresult = psenc->chlen;
+	_citrus_HZ_init_state(ei, psenc);
+
+	return 0;
+}
+
+static __inline int
+_citrus_HZ_stdenc_get_state_desc_generic(_HZEncodingInfo * __restrict ei,
+	_HZState * __restrict psenc, int * __restrict rstate)
+{
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(rstate != NULL);
+
+	if (psenc->chlen < 0 || psenc->inuse == NULL)
+		return EINVAL;
+	*rstate = (psenc->chlen == 0)
+	    ? ((psenc->inuse == INIT0(ei))
+	        ? _STDENC_SDGEN_INITIAL
+	        : _STDENC_SDGEN_STABLE)
+	    : ((psenc->ch[0] == ESCAPE_CHAR)
+	        ? _STDENC_SDGEN_INCOMPLETE_SHIFT
+	        : _STDENC_SDGEN_INCOMPLETE_CHAR);
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_HZ_stdenc_wctocs(_HZEncodingInfo * __restrict ei,
+	_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+	int bit;
+
+	_DIAGASSERT(csid != NULL);
+	_DIAGASSERT(idx != NULL);
+
+	if (wc & 0x80) {
+		bit = 0x80;
+		wc &= ~0x80;
+	} else {
+		bit = 0x0;
+	}
+	if ((uint32_t)wc <= 0x7F) {
+		*csid = (_csid_t)bit;
+		*idx = (_index_t)wc;
+	} else if ((uint32_t)wc <= 0x7F7F) {
+		*csid = (_csid_t)(bit | 0x8000);
+		*idx = (_index_t)wc;
+	} else {
+		*csid = (_index_t)(wc & ~0x00FFFF7F);
+		*idx = (_csid_t)(wc & 0x00FFFF7F);
+	}
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_HZ_stdenc_cstowc(_HZEncodingInfo * __restrict ei,
+	wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(wc != NULL);
+
+	*wc = (wchar_t)idx;
+	switch (csid) {
+	case 0x80:
+	case 0x8080:
+		*wc |= (wchar_t)0x80;
+	/*FALLTHROUGH*/
+	case 0x0:
+	case 0x8000:
+		break;
+	default:
+		*wc |= (wchar_t)csid;
+	}
+
+	return 0;
+}
+
+static void
+_citrus_HZ_encoding_module_uninit(_HZEncodingInfo *ei)
+{
+	escape_t *escape;
+
+	_DIAGASSERT(ei != NULL);
+	while ((escape = TAILQ_FIRST(E0SET(ei))) != NULL) {
+		TAILQ_REMOVE(E0SET(ei), escape, entry);
+		free(GL(escape), M_KICONV);
+		free(GR(escape), M_KICONV);
+		free(escape, M_KICONV);
+	}
+	while ((escape = TAILQ_FIRST(E1SET(ei))) != NULL) {
+		TAILQ_REMOVE(E1SET(ei), escape, entry);
+		free(GL(escape), M_KICONV);
+		free(GR(escape), M_KICONV);
+		free(escape, M_KICONV);
+	}
+}
+
+static int
+_citrus_HZ_parse_char(void **context, const char *name, const char *s)
+{
+	void **p;
+	escape_t *escape;
+
+	_DIAGASSERT(context != NULL && *context != NULL);
+	_DIAGASSERT(name != NULL);
+	_DIAGASSERT(s != NULL);
+
+	p = (void **)*context;
+	escape = (escape_t *)p[0];
+	if (escape->ch != '\0')
+		return EINVAL;
+	escape->ch = *s++;
+	if (escape->ch == ESCAPE_CHAR || *s != '\0')
+		return EINVAL;
+
+	return 0;
+}
+
+static int
+_citrus_HZ_parse_graphic(void **context, const char *name, const char *s)
+{
+	void **p;
+	_HZEncodingInfo *ei;
+	escape_t *escape;
+	graphic_t *graphic;
+
+	_DIAGASSERT(context != NULL && *context != NULL);
+	_DIAGASSERT(name != NULL);
+	_DIAGASSERT(s != NULL);
+
+	p = (void **)*context;
+	escape = (escape_t *)p[0];
+	ei = (_HZEncodingInfo *)p[1];
+	graphic = malloc(sizeof(*graphic), M_KICONV, M_WAITOK|M_ZERO);
+	if (strcmp("GL", name) == 0) {
+		if (GL(escape) != NULL)
+			goto release;
+		GL(escape) = graphic;
+	} else if (strcmp("GR", name) == 0) {
+		if (GR(escape) != NULL)
+			goto release;
+		GR(escape) = graphic;
+	} else {
+release:
+		free(graphic, M_KICONV);
+		return EINVAL;
+	}
+	graphic->escape = escape;
+	if (_bcs_strncasecmp("ASCII", s, 5) == 0) {
+		if (s[5] != '\0')
+			return EINVAL;
+		graphic->charset = ASCII;
+		graphic->length = 1;
+		ei->ascii = graphic;
+		return 0;
+	} else if (_bcs_strncasecmp("GB2312", s, 6) == 0) {
+		if (s[6] != '\0')
+			return EINVAL;
+		graphic->charset = GB2312;
+		graphic->length = 2;
+		ei->gb2312 = graphic;
+		return 0;
+	} else if (strncmp("94*", s, 3) == 0) {
+		graphic->charset = CS94;
+	} else if (strncmp("96*", s, 3) == 0) {
+		graphic->charset = CS96;
+	} else {
+		return EINVAL;
+	}
+	s += 3;
+	switch(*s) {
+	case '1': case '2': case '3':
+		graphic->length = (size_t)(*s - '0');
+		if (*++s == '\0')
+			break;
+	/*FALLTHROUGH*/
+	default:
+		return EINVAL;
+	}
+	return 0;
+}
+
+static const _citrus_prop_hint_t escape_hints[] = {
+_CITRUS_PROP_HINT_STR("CH", &_citrus_HZ_parse_char),
+_CITRUS_PROP_HINT_STR("GL", &_citrus_HZ_parse_graphic),
+_CITRUS_PROP_HINT_STR("GR", &_citrus_HZ_parse_graphic),
+_CITRUS_PROP_HINT_END
+};
+
+static int
+_citrus_HZ_parse_escape(void **context, const char *name, const char *s)
+{
+	_HZEncodingInfo *ei;
+	escape_t *escape;
+	void *p[2];
+
+	_DIAGASSERT(context != NULL);
+	_DIAGASSERT(name != NULL);
+	_DIAGASSERT(s != NULL);
+
+	ei = (_HZEncodingInfo *)*context;
+	escape = malloc(sizeof(*escape), M_KICONV, M_WAITOK|M_ZERO);
+	if (strcmp("0", name) == 0) {
+		escape->set = E0SET(ei);
+		TAILQ_INSERT_TAIL(E0SET(ei), escape, entry);
+	} else if (strcmp("1", name) == 0) {
+		escape->set = E1SET(ei);
+		TAILQ_INSERT_TAIL(E1SET(ei), escape, entry);
+	} else {
+		free(escape, M_KICONV);
+		return EINVAL;
+	}
+	p[0] = (void *)escape;
+	p[1] = (void *)ei;
+	return _citrus_prop_parse_variable(
+	    escape_hints, (void *)&p[0], s, strlen(s));
+}
+
+static const _citrus_prop_hint_t root_hints[] = {
+_CITRUS_PROP_HINT_STR("0", &_citrus_HZ_parse_escape),
+_CITRUS_PROP_HINT_STR("1", &_citrus_HZ_parse_escape),
+_CITRUS_PROP_HINT_END
+};
+
+static int
+_citrus_HZ_encoding_module_init(_HZEncodingInfo * __restrict ei,
+	const void * __restrict var, size_t lenvar)
+{
+	int errnum;
+
+	_DIAGASSERT(ei != NULL);
+
+	memset(ei, 0, sizeof(*ei));
+	TAILQ_INIT(E0SET(ei));
+	TAILQ_INIT(E1SET(ei));
+	errnum = _citrus_prop_parse_variable(
+	    root_hints, (void *)ei, var, lenvar);
+	if (errnum != 0)
+		_citrus_HZ_encoding_module_uninit(ei);
+	return errnum;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(HZ);
+_CITRUS_CTYPE_DEF_OPS(HZ);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(HZ);
+_CITRUS_STDENC_DEF_OPS(HZ);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(HZ_ctype);
+KICONV_GETOPS(HZ_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_HZ, "kiconv");
+
+static int
+kiconv_HZ_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_HZ_ctype_getops);
+		kiconv_attach_getops(&kiconv_HZ_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_HZ_stdenc_getops);
+		kiconv_detach_getops(&kiconv_HZ_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_hz.h src/sys/kiconv/modules/citrus_hz.h
--- src.orig/sys/kiconv/modules/citrus_hz.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_hz.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/* $NetBSD: citrus_hz.h,v 1.1 2006/11/22 23:38:27 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_HZ_H_
+#define _CITRUS_HZ_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(HZ);
+_CITRUS_STDENC_GETOPS_FUNC(HZ);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_iconv_none.c src/sys/kiconv/modules/citrus_iconv_none.c
--- src.orig/sys/kiconv/modules/citrus_iconv_none.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_iconv_none.c	2011-06-03 21:21:20.000000000 +0900
@@ -0,0 +1,169 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_iconv_none.c,v 1.3 2011/05/23 14:45:44 joerg Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_iconv_none.c,v 1.3 2011/05/23 14:45:44 joerg Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/queue.h>
+#endif
+
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_hash.h"
+#include "citrus_iconv.h"
+#include "citrus_iconv_none.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_ICONV_DECLS(iconv_none);
+_CITRUS_ICONV_DEF_OPS(iconv_none);
+
+
+/* ---------------------------------------------------------------------- */
+
+int
+_citrus_iconv_none_iconv_getops(struct _citrus_iconv_ops *ops, size_t lenops,
+				uint32_t expected_version)
+{
+	if (expected_version<_CITRUS_ICONV_ABI_VERSION || lenops<sizeof(*ops))
+		return (EINVAL);
+
+	memcpy(ops, &_citrus_iconv_none_iconv_ops,
+	       sizeof(_citrus_iconv_none_iconv_ops));
+
+	return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_init_shared(
+	struct _citrus_iconv_shared * __restrict ci,
+	const char * __restrict curdir,
+	const char * __restrict in, const char * __restrict out,
+	const void * __restrict var, size_t lenvar)
+{
+	ci->ci_closure = NULL;
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_uninit_shared(struct _citrus_iconv_shared *ci)
+{
+}
+
+static int
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_init_context(struct _citrus_iconv *cv)
+{
+	cv->cv_closure = NULL;
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_uninit_context(struct _citrus_iconv *cv)
+{
+}
+
+static int
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_convert(struct _citrus_iconv * __restrict ci,
+				 const char * __restrict * __restrict in,
+				 size_t * __restrict inbytes,
+				 char * __restrict * __restrict out,
+				 size_t * __restrict outbytes,
+				 u_int32_t flags, size_t * __restrict invalids)
+{
+	int e2big;
+	size_t len;
+
+	len = *inbytes;
+	e2big = 0;
+	if (*outbytes<len) {
+		e2big = 1;
+		len = *outbytes;
+	}
+	memcpy(*out, *in, len);
+	in += len;
+	*inbytes -= len;
+	out+=len;
+	*outbytes -= len;
+	*invalids = 0;
+	if (e2big) {
+		return (E2BIG);
+	}
+
+	return (0);
+}
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(iconv_none_iconv);
+
+MODULE(MODULE_CLASS_MISC, kiconv_iconv_none, "kiconv");
+
+static int
+kiconv_iconv_none_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_iconv_none_iconv_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_iconv_none_iconv_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_iconv_none.h src/sys/kiconv/modules/citrus_iconv_none.h
--- src.orig/sys/kiconv/modules/citrus_iconv_none.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_iconv_none.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,36 @@
+/*	$NetBSD: citrus_iconv_none.h,v 1.1 2003/06/25 09:51:43 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_NONE_H_
+#define _CITRUS_ICONV_NONE_H_
+
+__BEGIN_DECLS
+_CITRUS_ICONV_GETOPS_FUNC(iconv_none);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_iconv_std.c src/sys/kiconv/modules/citrus_iconv_std.c
--- src.orig/sys/kiconv/modules/citrus_iconv_std.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_iconv_std.c	2011-06-04 17:20:39.000000000 +0900
@@ -0,0 +1,607 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_iconv_std.c,v 1.15 2006/11/13 19:08:19 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_iconv_std.c,v 1.15 2006/11/13 19:08:19 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <machine/endian.h>
+#include <sys/queue.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_region.h"
+#include "citrus_mmap.h"
+#include "citrus_hash.h"
+#include "citrus_iconv.h"
+#include "citrus_stdenc.h"
+#include "citrus_mapper.h"
+#include "citrus_csmapper.h"
+#include "citrus_memstream.h"
+#include "citrus_iconv_std.h"
+#include "citrus_esdb.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_ICONV_DECLS(iconv_std);
+_CITRUS_ICONV_DEF_OPS(iconv_std);
+
+
+/* ---------------------------------------------------------------------- */
+
+int
+_citrus_iconv_std_iconv_getops(struct _citrus_iconv_ops *ops, size_t lenops,
+			       u_int32_t expected_version)
+{
+	if (expected_version<_CITRUS_ICONV_ABI_VERSION || lenops<sizeof(*ops))
+		return (EINVAL);
+
+	memcpy(ops, &_citrus_iconv_std_iconv_ops,
+	       sizeof(_citrus_iconv_std_iconv_ops));
+
+	return (0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * convenience routines for stdenc.
+ */
+static __inline void
+save_encoding_state(struct _citrus_iconv_std_encoding *se)
+{
+	if (se->se_ps)
+		memcpy(se->se_pssaved, se->se_ps,
+		       _stdenc_get_state_size(se->se_handle));
+}
+
+static __inline void
+restore_encoding_state(struct _citrus_iconv_std_encoding *se)
+{
+	if (se->se_ps)
+		memcpy(se->se_ps, se->se_pssaved,
+		       _stdenc_get_state_size(se->se_handle));
+}
+
+static __inline void
+init_encoding_state(struct _citrus_iconv_std_encoding *se)
+{
+	if (se->se_ps)
+		_stdenc_init_state(se->se_handle, se->se_ps);
+}
+
+static __inline int
+mbtocsx(struct _citrus_iconv_std_encoding *se,
+	_csid_t *csid, _index_t *idx, const char **s, size_t n,
+	size_t *nresult)
+{
+	return _stdenc_mbtocs(se->se_handle, csid, idx, s, n, se->se_ps,
+			      nresult);
+}
+
+static __inline int
+cstombx(struct _citrus_iconv_std_encoding *se,
+	char *s, size_t n, _csid_t csid, _index_t idx, size_t *nresult)
+{
+	return _stdenc_cstomb(se->se_handle, s, n, csid, idx, se->se_ps,
+			      nresult);
+}
+
+static __inline int
+wctombx(struct _citrus_iconv_std_encoding *se,
+	char *s, size_t n, _wc_t wc, size_t *nresult)
+{
+	return _stdenc_wctomb(se->se_handle, s, n, wc, se->se_ps, nresult);
+}
+
+static __inline int
+put_state_resetx(struct _citrus_iconv_std_encoding *se,
+		 char *s, size_t n, size_t *nresult)
+{
+	return _stdenc_put_state_reset(se->se_handle, s, n, se->se_ps, nresult);
+}
+
+static __inline int
+get_state_desc_gen(struct _citrus_iconv_std_encoding *se, int *rstate)
+{
+	int ret;
+	struct _stdenc_state_desc ssd;
+
+	ret = _stdenc_get_state_desc(se->se_handle, se->se_ps,
+				     _STDENC_SDID_GENERIC, &ssd);
+	if (!ret)
+		*rstate = ssd.u.generic.state;
+
+	return ret;
+}
+
+/*
+ * init encoding context
+ */
+static int
+init_encoding(struct _citrus_iconv_std_encoding *se, struct _stdenc *cs,
+	      void *ps1, void *ps2)
+{
+	int ret = -1;
+
+	se->se_handle = cs;
+	se->se_ps = ps1;
+	se->se_pssaved = ps2;
+
+	if (se->se_ps)
+		ret = _stdenc_init_state(cs, se->se_ps);
+	if (!ret && se->se_pssaved)
+		ret = _stdenc_init_state(cs, se->se_pssaved);
+
+	return ret;
+}
+
+static int
+open_csmapper(struct _csmapper **rcm, const char *src, const char *dst,
+	      unsigned long *rnorm)
+{
+	int ret;
+	struct _csmapper *cm;
+
+	ret = _csmapper_open(&cm, src, dst, 0, rnorm);
+	if (ret)
+		return ret;
+	if (_csmapper_get_src_max(cm) != 1 || _csmapper_get_dst_max(cm) != 1 ||
+	    _csmapper_get_state_size(cm) != 0) {
+		_csmapper_close(cm);
+		return EINVAL;
+	}
+
+	*rcm = cm;
+
+	return 0;
+}
+
+static void
+close_dsts(struct _citrus_iconv_std_dst_list *dl)
+{
+	struct _citrus_iconv_std_dst *sd;
+
+	while ((sd=TAILQ_FIRST(dl)) != NULL) {
+		TAILQ_REMOVE(dl, sd, sd_entry);
+		_csmapper_close(sd->sd_mapper);
+		free(sd, M_KICONV);
+	}
+}
+
+static int
+open_dsts(struct _citrus_iconv_std_dst_list *dl,
+	  const struct _esdb_charset *ec, const struct _esdb *dbdst)
+{
+	int i, ret;
+	struct _citrus_iconv_std_dst *sd, *sdtmp;
+	unsigned long norm;
+
+	sd = malloc(sizeof(*sd), M_KICONV, M_WAITOK);
+
+	for (i=0; i<dbdst->db_num_charsets; i++) {
+		ret = open_csmapper(&sd->sd_mapper, ec->ec_csname,
+				    dbdst->db_charsets[i].ec_csname, &norm);
+		if (ret == 0) {
+			sd->sd_csid = dbdst->db_charsets[i].ec_csid;
+			sd->sd_norm = norm;
+			/* insert this mapper by sorted order. */
+			TAILQ_FOREACH(sdtmp, dl, sd_entry) {
+				if (sdtmp->sd_norm > norm) {
+					TAILQ_INSERT_BEFORE(sdtmp, sd,
+							    sd_entry);
+					sd = NULL;
+					break;
+				}
+			}
+			if (sd)
+				TAILQ_INSERT_TAIL(dl, sd, sd_entry);
+			sd = malloc(sizeof(*sd), M_KICONV, M_WAITOK);
+		} else if (ret != ENOENT) {
+			close_dsts(dl);
+			free(sd, M_KICONV);
+			return ret;
+		}
+	}
+	free(sd, M_KICONV);
+	return 0;
+}
+
+static void
+close_srcs(struct _citrus_iconv_std_src_list *sl)
+{
+	struct _citrus_iconv_std_src *ss;
+
+	while ((ss=TAILQ_FIRST(sl)) != NULL) {
+		TAILQ_REMOVE(sl, ss, ss_entry);
+		close_dsts(&ss->ss_dsts);
+		free(ss, M_KICONV);
+	}
+}
+
+static int
+open_srcs(struct _citrus_iconv_std_src_list *sl,
+	  const struct _esdb *dbsrc, const struct _esdb *dbdst)
+{
+	int i, ret, count = 0;
+	struct _citrus_iconv_std_src *ss;
+
+	ss = malloc(sizeof(*ss), M_KICONV, M_WAITOK);
+
+	TAILQ_INIT(&ss->ss_dsts);
+
+	for (i=0; i<dbsrc->db_num_charsets; i++) {
+		ret = open_dsts(&ss->ss_dsts, &dbsrc->db_charsets[i], dbdst);
+		if (ret)
+			goto err;
+		if (!TAILQ_EMPTY(&ss->ss_dsts)) {
+			ss->ss_csid = dbsrc->db_charsets[i].ec_csid;
+			TAILQ_INSERT_TAIL(sl, ss, ss_entry);
+			ss = malloc(sizeof(*ss), M_KICONV, M_WAITOK);
+			count++;
+			TAILQ_INIT(&ss->ss_dsts);
+		}
+	}
+	free(ss, M_KICONV);
+
+	return count ? 0 : ENOENT;
+
+err:
+	free(ss, M_KICONV);
+	close_srcs(sl);
+	return ret;
+}
+
+/* do convert a character */
+#define E_NO_CORRESPONDING_CHAR ENOENT /* XXX */
+static int
+/*ARGSUSED*/
+do_conv(const struct _citrus_iconv_std_shared *is,
+	struct _citrus_iconv_std_context *sc, _csid_t *csid, _index_t *idx)
+{
+	_index_t tmpidx;
+	int ret;
+	struct _citrus_iconv_std_src *ss;
+	struct _citrus_iconv_std_dst *sd;
+
+	TAILQ_FOREACH(ss, &is->is_srcs, ss_entry) {
+		if (ss->ss_csid == *csid) {
+			TAILQ_FOREACH(sd, &ss->ss_dsts, sd_entry) {
+				ret = _csmapper_convert(sd->sd_mapper,
+							&tmpidx, *idx, NULL);
+				switch (ret) {
+				case _MAPPER_CONVERT_SUCCESS:
+					*csid = sd->sd_csid;
+					*idx = tmpidx;
+					return 0;
+				case _MAPPER_CONVERT_NONIDENTICAL:
+					break;
+				case _MAPPER_CONVERT_SRC_MORE:
+					/*FALLTHROUGH*/
+				case _MAPPER_CONVERT_DST_MORE:
+					/*FALLTHROUGH*/
+				case _MAPPER_CONVERT_FATAL:
+					return EINVAL;
+				case _MAPPER_CONVERT_ILSEQ:
+					return EILSEQ;
+				}
+			}
+			break;
+		}
+	}
+
+	return E_NO_CORRESPONDING_CHAR;
+}
+/* ---------------------------------------------------------------------- */
+
+static int
+/*ARGSUSED*/
+_citrus_iconv_std_iconv_init_shared(struct _citrus_iconv_shared *ci,
+				    const char * __restrict curdir,
+				    const char * __restrict src,
+				    const char * __restrict dst,
+				    const void * __restrict var, size_t lenvar)
+{
+	int ret;
+	struct _citrus_iconv_std_shared *is;
+	struct _citrus_esdb esdbsrc, esdbdst;
+
+	is = malloc(sizeof(*is), M_KICONV, M_WAITOK);
+
+	ret = _citrus_esdb_open(&esdbsrc, src);
+	if (ret)
+		goto err1;
+	ret = _citrus_esdb_open(&esdbdst, dst);
+	if (ret)
+		goto err2;
+	ret = _stdenc_open(&is->is_src_encoding, esdbsrc.db_encname,
+			   esdbsrc.db_variable, esdbsrc.db_len_variable);
+	if (ret)
+		goto err3;
+	ret = _stdenc_open(&is->is_dst_encoding, esdbdst.db_encname,
+			   esdbdst.db_variable, esdbdst.db_len_variable);
+	if (ret)
+		goto err4;
+	is->is_use_invalid = esdbdst.db_use_invalid;
+	is->is_invalid = esdbdst.db_invalid;
+
+	TAILQ_INIT(&is->is_srcs);
+	ret = open_srcs(&is->is_srcs, &esdbsrc, &esdbdst);
+	if (ret)
+		goto err5;
+
+	_esdb_close(&esdbsrc);
+	_esdb_close(&esdbdst);
+	ci->ci_closure = is;
+
+	return 0;
+
+err5:
+	_stdenc_close(is->is_dst_encoding);
+err4:
+	_stdenc_close(is->is_src_encoding);
+err3:
+	_esdb_close(&esdbdst);
+err2:
+	_esdb_close(&esdbsrc);
+err1:
+	free(is, M_KICONV);
+	return ret;
+}
+
+static void
+_citrus_iconv_std_iconv_uninit_shared(struct _citrus_iconv_shared *ci)
+{
+	struct _citrus_iconv_std_shared *is = ci->ci_closure;
+
+	if (is == NULL)
+		return;
+
+	_stdenc_close(is->is_src_encoding);
+	_stdenc_close(is->is_dst_encoding);
+	close_srcs(&is->is_srcs);
+	free(is, M_KICONV);
+}
+
+static int
+_citrus_iconv_std_iconv_init_context(struct _citrus_iconv *cv)
+{
+	const struct _citrus_iconv_std_shared *is = cv->cv_shared->ci_closure;
+	struct _citrus_iconv_std_context *sc;
+	size_t szpssrc, szpsdst, sz;
+	char *ptr;
+
+	szpssrc = _stdenc_get_state_size(is->is_src_encoding);
+	szpsdst = _stdenc_get_state_size(is->is_dst_encoding);
+
+	sz = (szpssrc + szpsdst)*2 + sizeof(struct _citrus_iconv_std_context);
+	sc = malloc(sz, M_KICONV, M_WAITOK);
+
+	ptr = (char *)&sc[1];
+	if (szpssrc)
+		init_encoding(&sc->sc_src_encoding, is->is_src_encoding,
+			      ptr, ptr+szpssrc);
+	else
+		init_encoding(&sc->sc_src_encoding, is->is_src_encoding,
+			      NULL, NULL);
+	ptr += szpssrc*2;
+	if (szpsdst)
+		init_encoding(&sc->sc_dst_encoding, is->is_dst_encoding,
+			      ptr, ptr+szpsdst);
+	else
+		init_encoding(&sc->sc_dst_encoding, is->is_dst_encoding,
+			      NULL, NULL);
+
+	cv->cv_closure = (void *)sc;
+
+	return 0;
+}
+
+static void
+_citrus_iconv_std_iconv_uninit_context(struct _citrus_iconv *cv)
+{
+	free(cv->cv_closure, M_KICONV);
+}
+
+static int
+_citrus_iconv_std_iconv_convert(struct _citrus_iconv * __restrict cv,
+				const char * __restrict * __restrict in,
+				size_t * __restrict inbytes,
+				char * __restrict * __restrict out,
+				size_t * __restrict outbytes, u_int32_t flags,
+				size_t * __restrict invalids)
+{
+	const struct _citrus_iconv_std_shared *is = cv->cv_shared->ci_closure;
+	struct _citrus_iconv_std_context *sc = cv->cv_closure;
+	_index_t idx;
+	_csid_t csid;
+	int ret, state = 0;
+	size_t szrin, szrout;
+	size_t inval;
+	const char *tmpin;
+
+	inval = 0;
+	if (in==NULL || *in==NULL) {
+		/* special cases */
+		if (out!=NULL && *out!=NULL) {
+			/* init output state and store the shift sequence */
+			save_encoding_state(&sc->sc_src_encoding);
+			save_encoding_state(&sc->sc_dst_encoding);
+			szrout = 0;
+
+			ret = put_state_resetx(&sc->sc_dst_encoding,
+					       *out, *outbytes,
+					       &szrout);
+			if (ret)
+				goto err;
+
+			if (szrout == (size_t)-2) {
+				/* too small to store the character */
+				ret = EINVAL;
+				goto err;
+			}
+			*out += szrout;
+			*outbytes -= szrout;
+		} else
+			/* otherwise, discard the shift sequence */
+			init_encoding_state(&sc->sc_dst_encoding);
+		init_encoding_state(&sc->sc_src_encoding);
+		*invalids = 0;
+		return 0;
+	}
+
+	/* 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;
+		}
+
+		/* save the encoding states for the error recovery */
+		save_encoding_state(&sc->sc_src_encoding);
+		save_encoding_state(&sc->sc_dst_encoding);
+
+		/* mb -> csid/index */
+		tmpin = *in;
+		szrin = szrout = 0;
+		ret = mbtocsx(&sc->sc_src_encoding, &csid, &idx,
+			      &tmpin, *inbytes, &szrin);
+		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;
+		}
+		/* convert the character */
+		ret = do_conv(is, sc, &csid, &idx);
+		if (ret) {
+			if (ret == E_NO_CORRESPONDING_CHAR) {
+				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;
+				}
+				goto next;
+			} else {
+				goto err;
+			}
+		}
+		/* csid/index -> mb */
+		ret = cstombx(&sc->sc_dst_encoding,
+			      *out, *outbytes, csid, idx, &szrout);
+		if (ret)
+			goto err;
+next:
+		_DIAGASSERT(*inbytes>=szrin && *outbytes>=szrout);
+		*inbytes -= tmpin-*in; /* szrin is insufficient on \0. */
+		*in = tmpin;
+		*outbytes -= szrout;
+		*out += szrout;
+	}
+	*invalids = inval;
+
+	return 0;
+
+err:
+	restore_encoding_state(&sc->sc_src_encoding);
+	restore_encoding_state(&sc->sc_dst_encoding);
+	*invalids = inval;
+
+	return ret;
+}
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(iconv_std_iconv);
+
+MODULE(MODULE_CLASS_MISC, kiconv_iconv_std, "kiconv");
+
+static int
+kiconv_iconv_std_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_iconv_std_iconv_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_iconv_std_iconv_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_iconv_std.h src/sys/kiconv/modules/citrus_iconv_std.h
--- src.orig/sys/kiconv/modules/citrus_iconv_std.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_iconv_std.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,36 @@
+/*	$NetBSD: citrus_iconv_std.h,v 1.1 2003/06/25 09:51:44 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_STD_H_
+#define _CITRUS_ICONV_STD_H_
+
+#include "citrus_iconv_std_local.h"
+
+_CITRUS_ICONV_GETOPS_FUNC(iconv_std);
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_iconv_std_local.h src/sys/kiconv/modules/citrus_iconv_std_local.h
--- src.orig/sys/kiconv/modules/citrus_iconv_std_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_iconv_std_local.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,81 @@
+/*	$NetBSD: citrus_iconv_std_local.h,v 1.2 2003/07/01 09:42:16 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_STD_LOCAL_H_
+#define _CITRUS_ICONV_STD_LOCAL_H_
+
+/*
+ * encoding
+ */
+struct _citrus_iconv_std_encoding {
+	struct _citrus_stdenc	*se_handle;
+	void			*se_ps;
+	void			*se_pssaved;
+};
+
+/*
+ * dst
+ */
+struct _citrus_iconv_std_dst {
+	TAILQ_ENTRY(_citrus_iconv_std_dst)	sd_entry;
+	_citrus_csid_t				sd_csid;
+	unsigned long				sd_norm;
+	struct _citrus_csmapper			*sd_mapper;
+};
+TAILQ_HEAD(_citrus_iconv_std_dst_list, _citrus_iconv_std_dst);
+
+/*
+ * src
+ */
+struct _citrus_iconv_std_src {
+	TAILQ_ENTRY(_citrus_iconv_std_src)	ss_entry;
+	_citrus_csid_t				ss_csid;
+	struct _citrus_iconv_std_dst_list	ss_dsts;
+};
+TAILQ_HEAD(_citrus_iconv_std_src_list, _citrus_iconv_std_src);
+
+/*
+ * iconv_std handle
+ */
+struct _citrus_iconv_std_shared {
+	struct _citrus_stdenc			*is_src_encoding;
+	struct _citrus_stdenc			*is_dst_encoding;
+	struct _citrus_iconv_std_src_list	is_srcs;
+	int					is_use_invalid;
+	_citrus_wc_t				is_invalid;
+};
+
+/*
+ * iconv_std context
+ */
+struct _citrus_iconv_std_context {
+	struct _citrus_iconv_std_encoding	sc_src_encoding;
+	struct _citrus_iconv_std_encoding	sc_dst_encoding;
+};
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_iso2022.c src/sys/kiconv/modules/citrus_iso2022.c
--- src.orig/sys/kiconv/modules/citrus_iso2022.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_iso2022.c	2011-10-19 02:19:11.000000000 +0900
@@ -0,0 +1,1393 @@
+/*	$NetBSD$	*/
+/*	NetBSDNetBSD: citrus_iso2022.c,v 1.22 2011/10/10 22:45:45 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)1999, 2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	$Citrus: xpg4dl/FreeBSD/lib/libc/locale/iso2022.c,v 1.23 2001/06/21 01:51:44 yamt Exp $
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_iso2022.c,v 1.22 2011/10/10 22:45:45 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <sys/types.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_iso2022.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+
+/*
+ * wchar_t mappings:
+ * ASCII (ESC ( B)		00000000 00000000 00000000 0xxxxxxx
+ * iso-8859-1 (ESC , A)		00000000 00000000 00000000 1xxxxxxx
+ * 94 charset (ESC ( F)		0fffffff 00000000 00000000 0xxxxxxx
+ * 94 charset (ESC ( M F)	0fffffff 1mmmmmmm 00000000 0xxxxxxx
+ * 96 charset (ESC , F)		0fffffff 00000000 00000000 1xxxxxxx
+ * 96 charset (ESC , M F)	0fffffff 1mmmmmmm 00000000 1xxxxxxx
+ * 94x94 charset (ESC $ ( F)	0fffffff 00000000 0xxxxxxx 0xxxxxxx
+ * 96x96 charset (ESC $ , F)	0fffffff 00000000 0xxxxxxx 1xxxxxxx
+ * 94x94 charset (ESC & V ESC $ ( F)
+ *				0fffffff 1vvvvvvv 0xxxxxxx 0xxxxxxx
+ * 94x94x94 charset (ESC $ ( F)	0fffffff 0xxxxxxx 0xxxxxxx 0xxxxxxx
+ * 96x96x96 charset (ESC $ , F)	0fffffff 0xxxxxxx 0xxxxxxx 1xxxxxxx
+ * reserved for UCS4 co-existence (UCS4 is 31bit encoding thanks to mohta bit)
+ *				1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
+ */
+
+typedef struct {
+	u_char	type;
+#define	CS94		(0U)
+#define	CS96		(1U)
+#define	CS94MULTI	(2U)
+#define	CS96MULTI	(3U)
+
+	u_char	final;
+	u_char	interm;
+	u_char	vers;
+} _ISO2022Charset;
+
+static const _ISO2022Charset ascii    = { CS94, 'B', '\0', '\0' };
+static const _ISO2022Charset iso88591 = { CS96, 'A', '\0', '\0' };
+
+typedef struct {
+	_ISO2022Charset	g[4];
+	/* need 3 bits to hold -1, 0, ..., 3 */
+	int	gl:3,
+		gr:3,
+		singlegl:3,
+		singlegr:3;
+	char ch[7];	/* longest escape sequence (ESC & V ESC $ ( F) */
+	int chlen;
+	int flags;
+#define _ISO2022STATE_FLAG_INITIALIZED	1
+} _ISO2022State;
+
+typedef struct {
+	_ISO2022Charset	*recommend[4];
+	size_t	recommendsize[4];
+	_ISO2022Charset	initg[4];
+	int	maxcharset;
+	int	flags;
+#define	F_8BIT	0x0001
+#define	F_NOOLD	0x0002
+#define	F_SI	0x0010	/*0F*/
+#define	F_SO	0x0020	/*0E*/
+#define	F_LS0	0x0010	/*0F*/
+#define	F_LS1	0x0020	/*0E*/
+#define	F_LS2	0x0040	/*ESC n*/
+#define	F_LS3	0x0080	/*ESC o*/
+#define	F_LS1R	0x0100	/*ESC ~*/
+#define	F_LS2R	0x0200	/*ESC }*/
+#define	F_LS3R	0x0400	/*ESC |*/
+#define	F_SS2	0x0800	/*ESC N*/
+#define	F_SS3	0x1000	/*ESC O*/
+#define	F_SS2R	0x2000	/*8E*/
+#define	F_SS3R	0x4000	/*8F*/
+} _ISO2022EncodingInfo;
+typedef struct {
+	_ISO2022EncodingInfo ei;
+	struct {
+		/* for future multi-locale facility */
+		_ISO2022State	s_mblen;
+		_ISO2022State	s_mbrlen;
+		_ISO2022State	s_mbrtowc;
+		_ISO2022State	s_mbtowc;
+		_ISO2022State	s_mbsrtowcs;
+		_ISO2022State	s_wcrtomb;
+		_ISO2022State	s_wcsrtombs;
+		_ISO2022State	s_wctomb;
+	} states;
+} _ISO2022CTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_ISO2022_##m
+#define _ENCODING_INFO			_ISO2022EncodingInfo
+#define _CTYPE_INFO			_ISO2022CTypeInfo
+#define _ENCODING_STATE			_ISO2022State
+#define _ENCODING_MB_CUR_MAX(_ei_)	MB_LEN_MAX
+#define _ENCODING_IS_STATE_DEPENDENT	1
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	\
+    (!((_ps_)->flags & _ISO2022STATE_FLAG_INITIALIZED))
+
+
+#define _ISO2022INVALID (wchar_t)-1
+
+static __inline int isc0(__uint8_t x) { return ((x & 0x1f) == x); }
+static __inline int isc1(__uint8_t x) { return (0x80 <= x && x <= 0x9f); }
+static __inline int iscntl(__uint8_t x) { return (isc0(x) || isc1(x) || x == 0x7f); }
+static __inline int is94(__uint8_t x) { return (0x21 <= x && x <= 0x7e); }
+static __inline int is96(__uint8_t x) { return (0x20 <= x && x <= 0x7f); }
+static __inline int isecma(__uint8_t x) { return (0x30 <= x && x <= 0x7f); }
+static __inline int isinterm(__uint8_t x) { return (0x20 <= x && x <= 0x2f); }
+static __inline int isthree(__uint8_t x) { return (0x60 <= x && x <= 0x6f); }
+
+static __inline int
+getcs(const char * __restrict p, _ISO2022Charset * __restrict cs)
+{
+
+	_DIAGASSERT(p != NULL);
+	_DIAGASSERT(cs != NULL);
+
+	if (!strncmp(p, "94$", 3) && p[3] && !p[4]) {
+		cs->final = (u_char)(p[3] & 0xff);
+		cs->interm = '\0';
+		cs->vers = '\0';
+		cs->type = CS94MULTI;
+	} else if (!strncmp(p, "96$", 3) && p[3] && !p[4]) {
+		cs->final = (u_char)(p[3] & 0xff);
+		cs->interm = '\0';
+		cs->vers = '\0';
+		cs->type = CS96MULTI;
+	} else if (!strncmp(p, "94", 2) && p[2] && !p[3]) {
+		cs->final = (u_char)(p[2] & 0xff);
+		cs->interm = '\0';
+		cs->vers = '\0';
+		cs->type = CS94;
+	} else if (!strncmp(p, "96", 2) && p[2] && !p[3]) {
+		cs->final = (u_char )(p[2] & 0xff);
+		cs->interm = '\0';
+		cs->vers = '\0';
+		cs->type = CS96;
+	} else {
+		return 1;
+	}
+
+	return 0;
+}
+
+
+#define _NOTMATCH	0
+#define _MATCH		1
+#define _PARSEFAIL	2
+
+static __inline int
+get_recommend(_ISO2022EncodingInfo * __restrict ei,
+	      const char * __restrict token)
+{
+	int i;
+	_ISO2022Charset cs, *p;
+
+	if (!strchr("0123", token[0]) || token[1] != '=')
+		return (_NOTMATCH);
+
+	if (getcs(&token[2], &cs) == 0)
+		;
+	else if (!strcmp(&token[2], "94")) {
+		cs.final = (u_char)(token[4]);
+		cs.interm = '\0';
+		cs.vers = '\0';
+		cs.type = CS94;
+	} else if (!strcmp(&token[2], "96")) {
+		cs.final = (u_char)(token[4]);
+		cs.interm = '\0';
+		cs.vers = '\0';
+		cs.type = CS96;
+	} else if (!strcmp(&token[2], "94$")) {
+		cs.final = (u_char)(token[5]);
+		cs.interm = '\0';
+		cs.vers = '\0';
+		cs.type = CS94MULTI;
+	} else if (!strcmp(&token[2], "96$")) {
+		cs.final = (u_char)(token[5]);
+		cs.interm = '\0';
+		cs.vers = '\0';
+		cs.type = CS96MULTI;
+	} else {
+		return (_PARSEFAIL);
+	}
+
+	i = token[0] - '0';
+	if (!ei->recommend[i]) {
+		ei->recommend[i] = malloc(sizeof(_ISO2022Charset), M_KICONV,
+		    M_WAITOK);
+	} else {
+		p = realloc(ei->recommend[i],
+		    sizeof(_ISO2022Charset) * (ei->recommendsize[i] + 1),
+		    M_KICONV, M_WAITOK);
+		if (!p)
+			return (_PARSEFAIL);
+		ei->recommend[i] = p;
+	}
+	if (!ei->recommend[i])
+		return (_PARSEFAIL);
+	ei->recommendsize[i]++;
+
+	(ei->recommend[i] + (ei->recommendsize[i] - 1))->final = cs.final;
+	(ei->recommend[i] + (ei->recommendsize[i] - 1))->interm = cs.interm;
+	(ei->recommend[i] + (ei->recommendsize[i] - 1))->vers = cs.vers;
+	(ei->recommend[i] + (ei->recommendsize[i] - 1))->type = cs.type;
+
+	return (_MATCH);
+}
+
+static __inline int
+get_initg(_ISO2022EncodingInfo * __restrict ei,
+	  const char * __restrict token)
+{
+	_ISO2022Charset cs;
+
+	if (strncmp("INIT", &token[0], 4) ||
+	    !strchr("0123", token[4]) ||
+	    token[5] != '=')
+		return (_NOTMATCH);
+
+	if (getcs(&token[6], &cs) != 0)
+		return (_PARSEFAIL);
+
+	ei->initg[token[4] - '0'].type = cs.type;
+	ei->initg[token[4] - '0'].final = cs.final;
+	ei->initg[token[4] - '0'].interm = cs.interm;
+	ei->initg[token[4] - '0'].vers = cs.vers;
+
+	return (_MATCH);
+}
+
+static __inline int
+get_max(_ISO2022EncodingInfo * __restrict ei,
+	const char * __restrict token)
+{
+	if (!strcmp(token, "MAX1")) {
+		ei->maxcharset = 1;
+	} else if (!strcmp(token, "MAX2")) {
+		ei->maxcharset = 2;
+	} else if (!strcmp(token, "MAX3")) {
+		ei->maxcharset = 3;
+	} else
+		return (_NOTMATCH);
+
+	return (_MATCH);
+}
+
+
+static __inline int
+get_flags(_ISO2022EncodingInfo * __restrict ei,
+	  const char * __restrict token)
+{
+	int i;
+	static struct {
+		const char	*tag;
+		int		flag;
+	} const tags[] = {
+		{ "DUMMY",	0	},
+		{ "8BIT",	F_8BIT	},
+		{ "NOOLD",	F_NOOLD	},
+		{ "SI",		F_SI	},
+		{ "SO",		F_SO	},
+		{ "LS0",	F_LS0	},
+		{ "LS1",	F_LS1	},
+		{ "LS2",	F_LS2	},
+		{ "LS3",	F_LS3	},
+		{ "LS1R",	F_LS1R	},
+		{ "LS2R",	F_LS2R	},
+		{ "LS3R",	F_LS3R	},
+		{ "SS2",	F_SS2	},
+		{ "SS3",	F_SS3	},
+		{ "SS2R",	F_SS2R	},
+		{ "SS3R",	F_SS3R	},
+		{ NULL,		0 }
+	};
+
+	for (i = 0; tags[i].tag; i++) {
+		if (!strcmp(token, tags[i].tag)) {
+			ei->flags |= tags[i].flag;
+			return (_MATCH);
+		}
+	}
+
+	return (_NOTMATCH);
+}
+
+
+static __inline int
+_citrus_ISO2022_parse_variable(_ISO2022EncodingInfo * __restrict ei,
+			       const void * __restrict var, size_t lenvar)
+{
+	char const *v, *e;
+	char buf[20];
+	int i, len, ret;
+
+	_DIAGASSERT(ei != NULL);
+
+
+	/*
+	 * parse VARIABLE section.
+	 */
+
+	if (!var)
+		return (EFTYPE);
+
+	v = (const char *) var;
+
+	/* initialize structure */
+	ei->maxcharset = 0;
+	for (i = 0; i < 4; i++) {
+		ei->recommend[i] = NULL;
+		ei->recommendsize[i] = 0;
+	}
+	ei->flags = 0;
+
+	while (*v) {
+		while (*v == ' ' || *v == '\t')
+			++v;
+
+		/* find the token */
+		e = v;
+		while (*e && *e != ' ' && *e != '\t')
+			++e;
+
+		len = e-v;
+		if (len == 0)
+			break;
+		if (len>=sizeof(buf))
+			goto parsefail;
+		snprintf(buf, sizeof(buf), "%.*s", len, v);
+
+		if ((ret = get_recommend(ei, buf)) != _NOTMATCH)
+			;
+		else if ((ret = get_initg(ei, buf)) != _NOTMATCH)
+			;
+		else if ((ret = get_max(ei, buf)) != _NOTMATCH)
+			;
+		else if ((ret = get_flags(ei, buf)) != _NOTMATCH)
+			;
+		else
+			ret = _PARSEFAIL;
+		if (ret==_PARSEFAIL)
+			goto parsefail;
+		v = e;
+
+	}
+
+	return (0);
+
+parsefail:
+	free(ei->recommend[0], M_KICONV);
+	free(ei->recommend[1], M_KICONV);
+	free(ei->recommend[2], M_KICONV);
+	free(ei->recommend[3], M_KICONV);
+
+	return (EFTYPE);
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ISO2022_init_state(_ISO2022EncodingInfo * __restrict ei,
+			   _ISO2022State * __restrict s)
+{
+	int i;
+
+	memset(s, 0, sizeof(*s));
+	s->gl = 0;
+	s->gr = (ei->flags & F_8BIT) ? 1 : -1;
+
+	for (i = 0; i < 4; i++) {
+		if (ei->initg[i].final) {
+			s->g[i].type = ei->initg[i].type;
+			s->g[i].final = ei->initg[i].final;
+			s->g[i].interm = ei->initg[i].interm;
+		}
+	}
+	s->singlegl = s->singlegr = -1;
+	s->flags |= _ISO2022STATE_FLAG_INITIALIZED;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ISO2022_pack_state(_ISO2022EncodingInfo * __restrict ei,
+			   void * __restrict pspriv,
+			   const _ISO2022State * __restrict s)
+{
+	memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ISO2022_unpack_state(_ISO2022EncodingInfo * __restrict ei,
+			     _ISO2022State * __restrict s,
+			     const void * __restrict pspriv)
+{
+	memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_ISO2022_encoding_module_init(_ISO2022EncodingInfo * __restrict ei,
+				     const void * __restrict var,
+				     size_t lenvar)
+{
+
+	_DIAGASSERT(ei != NULL);
+
+	return _citrus_ISO2022_parse_variable(ei, var, lenvar);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_ISO2022_encoding_module_uninit(_ISO2022EncodingInfo *ei)
+{
+}
+
+#define	ESC	'\033'
+#define	ECMA	-1
+#define	INTERM	-2
+#define	OECMA	-3
+static const struct seqtable {
+	int type;
+	int csoff;
+	int finaloff;
+	int intermoff;
+	int versoff;
+	int len;
+	int chars[10];
+} seqtable[] = {
+	/* G0 94MULTI special */
+	{ CS94MULTI, -1, 2, -1, -1,	3, { ESC, '$', OECMA }, },
+	/* G0 94MULTI special with version identification */
+	{ CS94MULTI, -1, 5, -1, 2,	6, { ESC, '&', ECMA, ESC, '$', OECMA }, },
+	/* G? 94 */
+	{ CS94, 1, 2, -1, -1,		3, { ESC, CS94, ECMA, }, },
+	/* G? 94 with 2nd intermediate char */
+	{ CS94, 1, 3, 2, -1,		4, { ESC, CS94, INTERM, ECMA, }, },
+	/* G? 96 */
+	{ CS96, 1, 2, -1, -1,		3, { ESC, CS96, ECMA, }, },
+	/* G? 96 with 2nd intermediate char */
+	{ CS96, 1, 3, 2, -1,		4, { ESC, CS96, INTERM, ECMA, }, },
+	/* G? 94MULTI */
+	{ CS94MULTI, 2, 3, -1, -1,	4, { ESC, '$', CS94, ECMA, }, },
+	/* G? 96MULTI */
+	{ CS96MULTI, 2, 3, -1, -1,	4, { ESC, '$', CS96, ECMA, }, },
+	/* G? 94MULTI with version specification */
+	{ CS94MULTI, 5, 6, -1, 2,	7, { ESC, '&', ECMA, ESC, '$', CS94, ECMA, }, },
+	/* LS2/3 */
+	{ -1, -1, -1, -1, -1,		2, { ESC, 'n', }, },
+	{ -1, -1, -1, -1, -1,		2, { ESC, 'o', }, },
+	/* LS1/2/3R */
+	{ -1, -1, -1, -1, -1,		2, { ESC, '~', }, },
+	{ -1, -1, -1, -1, -1,		2, { ESC, /*{*/ '}', }, },
+	{ -1, -1, -1, -1, -1,		2, { ESC, '|', }, },
+	/* SS2/3 */
+	{ -1, -1, -1, -1, -1,		2, { ESC, 'N', }, },
+	{ -1, -1, -1, -1, -1,		2, { ESC, 'O', }, },
+	/* end of records */
+	{ .type = 0, }
+};
+
+static int
+seqmatch(const char * __restrict s, size_t n,
+	 const struct seqtable * __restrict sp)
+{
+	const int *p;
+
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(sp != NULL);
+
+	p = sp->chars;
+	while (p - sp->chars < n && p - sp->chars < sp->len) {
+		switch (*p) {
+		case ECMA:
+			if (!isecma(*s))
+				goto terminate;
+			break;
+		case OECMA:
+			if (*s && strchr("@AB", *s))
+				break;
+			else
+				goto terminate;
+		case INTERM:
+			if (!isinterm(*s))
+				goto terminate;
+			break;
+		case CS94:
+			if (*s && strchr("()*+", *s))
+				break;
+			else
+				goto terminate;
+		case CS96:
+			if (*s && strchr(",-./", *s))
+				break;
+			else
+				goto terminate;
+		default:
+			if (*s != *p)
+				goto terminate;
+			break;
+		}
+
+		p++;
+		s++;
+	}
+
+terminate:
+	return p - sp->chars;
+}
+
+static wchar_t
+_ISO2022_sgetwchar(_ISO2022EncodingInfo * __restrict ei,
+		const char * __restrict string, size_t n,
+		const char ** __restrict result,
+		_ISO2022State * __restrict psenc)
+{
+	wchar_t wchar = 0;
+	int cur;
+	const struct seqtable *sp;
+	int nmatch;
+	int i;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(string != NULL);
+	/* result may be NULL */
+
+	while (1) {
+		/* SI/SO */
+		if (1 <= n && string[0] == '\017') {
+			psenc->gl = 0;
+			string++;
+			n--;
+			continue;
+		}
+		if (1 <= n && string[0] == '\016') {
+			psenc->gl = 1;
+			string++;
+			n--;
+			continue;
+		}
+
+		/* SS2/3R */
+		if (1 <= n && string[0] && strchr("\217\216", string[0])) {
+			psenc->singlegl = psenc->singlegr =
+			    (string[0] - '\216') + 2;
+			string++;
+			n--;
+			continue;
+		}
+
+		/* eat the letter if this is not ESC */
+		if (1 <= n && string[0] != '\033')
+			break;
+
+		/* look for a perfect match from escape sequences */
+		for (sp = &seqtable[0]; sp->len; sp++) {
+			nmatch = seqmatch(string, n, sp);
+			if (sp->len == nmatch && n >= sp->len)
+				break;
+		}
+
+		if (!sp->len)
+			goto notseq;
+
+		if (sp->type != -1) {
+			if (sp->csoff == -1)
+				i = 0;
+			else {
+				switch (sp->type) {
+				case CS94:
+				case CS94MULTI:
+					i = string[sp->csoff] - '(';
+					break;
+				case CS96:
+				case CS96MULTI:
+					i = string[sp->csoff] - ',';
+					break;
+				default:
+					return (_ISO2022INVALID);
+				}
+			}
+			psenc->g[i].type = sp->type;
+			psenc->g[i].final = '\0';
+			psenc->g[i].interm = '\0';
+			psenc->g[i].vers = '\0';
+			/* sp->finaloff must not be -1 */
+			if (sp->finaloff != -1)
+				psenc->g[i].final = string[sp->finaloff];
+			if (sp->intermoff != -1)
+				psenc->g[i].interm = string[sp->intermoff];
+			if (sp->versoff != -1)
+				psenc->g[i].vers = string[sp->versoff];
+
+			string += sp->len;
+			n -= sp->len;
+			continue;
+		}
+
+		/* LS2/3 */
+		if (2 <= n && string[0] == '\033'
+		 && string[1] && strchr("no", string[1])) {
+			psenc->gl = string[1] - 'n' + 2;
+			string += 2;
+			n -= 2;
+			continue;
+		}
+
+		/* LS1/2/3R */
+			/* XXX: { for vi showmatch */
+		if (2 <= n && string[0] == '\033'
+		 && string[1] && strchr("~}|", string[1])) {
+			psenc->gr = 3 - (string[1] - '|');
+			string += 2;
+			n -= 2;
+			continue;
+		}
+
+		/* SS2/3 */
+		if (2 <= n && string[0] == '\033'
+		 && string[1] && strchr("NO", string[1])) {
+			psenc->singlegl = (string[1] - 'N') + 2;
+			string += 2;
+			n -= 2;
+			continue;
+		}
+
+	notseq:
+		/*
+		 * if we've got an unknown escape sequence, eat the ESC at the
+		 * head.  otherwise, wait till full escape sequence comes.
+		 */
+		for (sp = &seqtable[0]; sp->len; sp++) {
+			nmatch = seqmatch(string, n, sp);
+			if (!nmatch)
+				continue;
+
+			/*
+			 * if we are in the middle of escape sequence,
+			 * we still need to wait for more characters to come
+			 */
+			if (n < sp->len) {
+				if (nmatch == n) {
+					if (result)
+						*result = string;
+					return (_ISO2022INVALID);
+				}
+			} else {
+				if (nmatch == sp->len) {
+					/* this case should not happen */
+					goto eat;
+				}
+			}
+		}
+
+		break;
+	}
+
+eat:
+	/* no letter to eat */
+	if (n < 1) {
+		if (result)
+			*result = string;
+		return (_ISO2022INVALID);
+	}
+
+	/* normal chars.  always eat C0/C1 as is. */
+	if (iscntl(*string & 0xff))
+		cur = -1;
+	else if (*string & 0x80) {
+		cur = (psenc->singlegr == -1)
+			? psenc->gr : psenc->singlegr;
+	} else {
+		cur = (psenc->singlegl == -1)
+			? psenc->gl : psenc->singlegl;
+	}
+
+	if (cur == -1) {
+asis:
+		wchar = *string++ & 0xff;
+		if (result)
+			*result = string;
+		/* reset single shift state */
+		psenc->singlegr = psenc->singlegl = -1;
+		return wchar;
+	}
+
+	/* length error check */
+	switch (psenc->g[cur].type) {
+	case CS94MULTI:
+	case CS96MULTI:
+		if (!isthree(psenc->g[cur].final)) {
+			if (2 <= n
+			 && (string[0] & 0x80) == (string[1] & 0x80))
+				break;
+		} else {
+			if (3 <= n
+			 && (string[0] & 0x80) == (string[1] & 0x80)
+			 && (string[0] & 0x80) == (string[2] & 0x80))
+				break;
+		}
+
+		/* we still need to wait for more characters to come */
+		if (result)
+			*result = string;
+		return (_ISO2022INVALID);
+
+	case CS94:
+	case CS96:
+		if (1 <= n)
+			break;
+
+		/* we still need to wait for more characters to come */
+		if (result)
+			*result = string;
+		return (_ISO2022INVALID);
+	}
+
+	/* range check */
+	switch (psenc->g[cur].type) {
+	case CS94:
+		if (!(is94(string[0] & 0x7f)))
+			goto asis;
+	case CS96:
+		if (!(is96(string[0] & 0x7f)))
+			goto asis;
+		break;
+	case CS94MULTI:
+		if (!(is94(string[0] & 0x7f) && is94(string[1] & 0x7f)))
+			goto asis;
+		break;
+	case CS96MULTI:
+		if (!(is96(string[0] & 0x7f) && is96(string[1] & 0x7f)))
+			goto asis;
+		break;
+	}
+
+	/* extract the character. */
+	switch (psenc->g[cur].type) {
+	case CS94:
+		/* special case for ASCII. */
+		if (psenc->g[cur].final == 'B' && !psenc->g[cur].interm) {
+			wchar = *string++;
+			wchar &= 0x7f;
+			break;
+		}
+		wchar = psenc->g[cur].final;
+		wchar = (wchar << 8);
+		wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0);
+		wchar = (wchar << 8);
+		wchar = (wchar << 8) | (*string++ & 0x7f);
+		break;
+	case CS96:
+		/* special case for ISO-8859-1. */
+		if (psenc->g[cur].final == 'A' && !psenc->g[cur].interm) {
+			wchar = *string++;
+			wchar &= 0x7f;
+			wchar |= 0x80;
+			break;
+		}
+		wchar = psenc->g[cur].final;
+		wchar = (wchar << 8);
+		wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0);
+		wchar = (wchar << 8);
+		wchar = (wchar << 8) | (*string++ & 0x7f);
+		wchar |= 0x80;
+		break;
+	case CS94MULTI:
+	case CS96MULTI:
+		wchar = psenc->g[cur].final;
+		wchar = (wchar << 8);
+		if (isthree(psenc->g[cur].final))
+			wchar |= (*string++ & 0x7f);
+		wchar = (wchar << 8) | (*string++ & 0x7f);
+		wchar = (wchar << 8) | (*string++ & 0x7f);
+		if (psenc->g[cur].type == CS96MULTI)
+			wchar |= 0x80;
+		break;
+	}
+
+	if (result)
+		*result = string;
+	/* reset single shift state */
+	psenc->singlegr = psenc->singlegl = -1;
+	return wchar;
+}
+
+
+
+static int
+_citrus_ISO2022_mbrtowc_priv(_ISO2022EncodingInfo * __restrict ei,
+			     wchar_t * __restrict pwc,
+			     const char ** __restrict s,
+			     size_t n, _ISO2022State * __restrict psenc,
+			     size_t * __restrict nresult)
+{
+	wchar_t wchar;
+	const char *s0, *p, *result;
+	int c;
+	int chlenbak;
+
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(s != NULL);
+
+	if (*s == NULL) {
+		_citrus_ISO2022_init_state(ei, psenc);
+		*nresult = _ENCODING_IS_STATE_DEPENDENT;
+		return 0;
+	}
+	s0 = *s;
+	c = 0;
+	chlenbak = psenc->chlen;
+
+	/*
+	 * if we have something in buffer, use that.
+	 * otherwise, skip here
+	 */
+	if (psenc->chlen < 0 || psenc->chlen > sizeof(psenc->ch)) {
+		/* illgeal state */
+		_citrus_ISO2022_init_state(ei, psenc);
+		goto encoding_error;
+	}
+	if (psenc->chlen == 0)
+		goto emptybuf;
+
+	/* buffer is not empty */
+	p = psenc->ch;
+	while (psenc->chlen < sizeof(psenc->ch)) {
+		if (n > 0) {
+			psenc->ch[psenc->chlen++] = *s0++;
+			n--;
+		}
+
+		wchar = _ISO2022_sgetwchar(ei, p, psenc->chlen - (p-psenc->ch),
+					   &result, psenc);
+		c += result - p;
+		if (wchar != _ISO2022INVALID) {
+			if (psenc->chlen > c)
+				memmove(psenc->ch, result, psenc->chlen - c);
+			if (psenc->chlen < c)
+				psenc->chlen = 0;
+			else
+				psenc->chlen -= c;
+			goto output;
+		}
+
+		if (n == 0) {
+			if ((result - p) == psenc->chlen)
+				/* complete shift sequence. */
+				psenc->chlen = 0;
+			goto restart;
+		}
+
+		p = result;
+	}
+
+	/* escape sequence too long? */
+	goto encoding_error;
+
+emptybuf:
+	wchar = _ISO2022_sgetwchar(ei, s0, n, &result, psenc);
+	if (wchar != _ISO2022INVALID) {
+		c += result - s0;
+		psenc->chlen = 0;
+		s0 = result;
+		goto output;
+	}
+	if (result > s0) {
+		c += (result - s0);
+		n -= (result - s0);
+		s0 = result;
+		if (n>0)
+			goto emptybuf;
+		/* complete shift sequence. */
+		goto restart;
+	}
+	n += c;
+	if (n < sizeof(psenc->ch)) {
+		memcpy(psenc->ch, s0 - c, n);
+		psenc->chlen = n;
+		s0 = result;
+		goto restart;
+	}
+
+	/* escape sequence too long? */
+
+encoding_error:
+	psenc->chlen = 0;
+	*nresult = (size_t)-1;
+	return (EILSEQ);
+
+output:
+	*s = s0;
+	if (pwc)
+		*pwc = wchar;
+
+	if (!wchar)
+		*nresult = 0;
+	else
+		*nresult = c - chlenbak;
+
+	return (0);
+
+restart:
+	*s = s0;
+	*nresult = (size_t)-2;
+
+	return (0);
+}
+
+static int
+recommendation(_ISO2022EncodingInfo * __restrict ei,
+	       _ISO2022Charset * __restrict cs)
+{
+	int i, j;
+	_ISO2022Charset *recommend;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(cs != NULL);
+
+	/* first, try a exact match. */
+	for (i = 0; i < 4; i++) {
+		recommend = ei->recommend[i];
+		for (j = 0; j < ei->recommendsize[i]; j++) {
+			if (cs->type != recommend[j].type)
+				continue;
+			if (cs->final != recommend[j].final)
+				continue;
+			if (cs->interm != recommend[j].interm)
+				continue;
+
+			return i;
+		}
+	}
+
+	/* then, try a wildcard match over final char. */
+	for (i = 0; i < 4; i++) {
+		recommend = ei->recommend[i];
+		for (j = 0; j < ei->recommendsize[i]; j++) {
+			if (cs->type != recommend[j].type)
+				continue;
+			if (cs->final && (cs->final != recommend[j].final))
+				continue;
+			if (cs->interm && (cs->interm != recommend[j].interm))
+				continue;
+
+			return i;
+		}
+	}
+
+	/* there's no recommendation. make a guess. */
+	if (ei->maxcharset == 0) {
+		return 0;
+	} else {
+		switch (cs->type) {
+		case CS94:
+		case CS94MULTI:
+			return 0;
+		case CS96:
+		case CS96MULTI:
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int
+_ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t wc,
+		   char * __restrict string, size_t n,
+		   char ** __restrict result,
+		   _ISO2022State * __restrict psenc,
+		   size_t * __restrict nresult)
+{
+	int i = 0;
+	size_t len;
+	_ISO2022Charset cs;
+	char *p;
+	char tmp[MB_LEN_MAX];
+	int target;
+	u_char mask;
+	int bit8;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(string != NULL);
+	/* result may be NULL */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (isc0(wc & 0xff)) {
+		/* go back to INIT0 or ASCII on control chars */
+		cs = ei->initg[0].final ? ei->initg[0] : ascii;
+	} else if (isc1(wc & 0xff)) {
+		/* go back to INIT1 or ISO-8859-1 on control chars */
+		cs = ei->initg[1].final ? ei->initg[1] : iso88591;
+	} else if (!(wc & ~0xff)) {
+		if (wc & 0x80) {
+			/* special treatment for ISO-8859-1 */
+			cs = iso88591;
+		} else {
+			/* special treatment for ASCII */
+			cs = ascii;
+		}
+	} else {
+		cs.final = (wc >> 24) & 0x7f;
+		if ((wc >> 16) & 0x80)
+			cs.interm = (wc >> 16) & 0x7f;
+		else
+			cs.interm = '\0';
+		if (wc & 0x80)
+			cs.type = (wc & 0x00007f00) ? CS96MULTI : CS96;
+		else
+			cs.type = (wc & 0x00007f00) ? CS94MULTI : CS94;
+	}
+	target = recommendation(ei, &cs);
+	p = tmp;
+	bit8 = ei->flags & F_8BIT;
+
+	/* designate the charset onto the target plane(G0/1/2/3). */
+	if (psenc->g[target].type == cs.type
+	 && psenc->g[target].final == cs.final
+	 && psenc->g[target].interm == cs.interm)
+		goto planeok;
+
+	*p++ = '\033';
+	if (cs.type == CS94MULTI || cs.type == CS96MULTI)
+		*p++ = '$';
+	if (target == 0 && cs.type == CS94MULTI && strchr("@AB", cs.final)
+	 && !cs.interm && !(ei->flags & F_NOOLD))
+		;
+	else if (cs.type == CS94 || cs.type == CS94MULTI)
+		*p++ = "()*+"[target];
+	else
+		*p++ = ",-./"[target];
+	if (cs.interm)
+		*p++ = cs.interm;
+	*p++ = cs.final;
+
+	psenc->g[target].type = cs.type;
+	psenc->g[target].final = cs.final;
+	psenc->g[target].interm = cs.interm;
+
+planeok:
+	/* invoke the plane onto GL or GR. */
+	if (psenc->gl == target)
+		goto sideok;
+	if (bit8 && psenc->gr == target)
+		goto sideok;
+
+	if (target == 0 && (ei->flags & F_LS0)) {
+		*p++ = '\017';
+		psenc->gl = 0;
+	} else if (target == 1 && (ei->flags & F_LS1)) {
+		*p++ = '\016';
+		psenc->gl = 1;
+	} else if (target == 2 && (ei->flags & F_LS2)) {
+		*p++ = '\033';
+		*p++ = 'n';
+		psenc->gl = 2;
+	} else if (target == 3 && (ei->flags & F_LS3)) {
+		*p++ = '\033';
+		*p++ = 'o';
+		psenc->gl = 3;
+	} else if (bit8 && target == 1 && (ei->flags & F_LS1R)) {
+		*p++ = '\033';
+		*p++ = '~';
+		psenc->gr = 1;
+	} else if (bit8 && target == 2 && (ei->flags & F_LS2R)) {
+		*p++ = '\033';
+		/*{*/
+		*p++ = '}';
+		psenc->gr = 2;
+	} else if (bit8 && target == 3 && (ei->flags & F_LS3R)) {
+		*p++ = '\033';
+		*p++ = '|';
+		psenc->gr = 3;
+	} else if (target == 2 && (ei->flags & F_SS2)) {
+		*p++ = '\033';
+		*p++ = 'N';
+		psenc->singlegl = 2;
+	} else if (target == 3 && (ei->flags & F_SS3)) {
+		*p++ = '\033';
+		*p++ = 'O';
+		psenc->singlegl = 3;
+	} else if (bit8 && target == 2 && (ei->flags & F_SS2R)) {
+		*p++ = '\216';
+		*p++ = 'N';
+		psenc->singlegl = psenc->singlegr = 2;
+	} else if (bit8 && target == 3 && (ei->flags & F_SS3R)) {
+		*p++ = '\217';
+		*p++ = 'O';
+		psenc->singlegl = psenc->singlegr = 3;
+	} else
+		goto ilseq;
+
+sideok:
+	if (psenc->singlegl == target)
+		mask = 0x00;
+	else if (psenc->singlegr == target)
+		mask = 0x80;
+	else if (psenc->gl == target)
+		mask = 0x00;
+	else if ((ei->flags & F_8BIT) && psenc->gr == target)
+		mask = 0x80;
+	else
+		goto ilseq;
+
+	switch (cs.type) {
+	case CS94:
+	case CS96:
+		i = 1;
+		break;
+	case CS94MULTI:
+	case CS96MULTI:
+		i = !iscntl(wc & 0xff) ?
+		    (isthree(cs.final) ? 3 : 2) : 1;
+		break;
+	}
+	while (i-- > 0)
+		*p++ = ((wc >> (i << 3)) & 0x7f) | mask;
+
+	/* reset single shift state */
+	psenc->singlegl = psenc->singlegr = -1;
+
+	len = (size_t)(p - tmp);
+	if (n < len) {
+		if (result)
+			*result = (char *)0;
+		*nresult = (size_t)-1;
+		return E2BIG;
+	}
+	if (result)
+		*result = string + len;
+	memcpy(string, tmp, len);
+	*nresult = len;
+
+	return 0;
+
+ilseq:
+	*nresult = (size_t)-1;
+	return EILSEQ;
+}
+
+static int
+_citrus_ISO2022_put_state_reset(_ISO2022EncodingInfo * __restrict ei,
+				char * __restrict s, size_t n,
+				_ISO2022State * __restrict psenc,
+				size_t * __restrict nresult)
+{
+	char buf[MB_LEN_MAX];
+	char *result;
+	int ret;
+	size_t len;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(s != NULL);
+
+	/* XXX state will be modified after this operation... */
+	ret = _ISO2022_sputwchar(ei, L'\0', buf, sizeof(buf), &result, psenc,
+	    &len);
+	if (ret) {
+		*nresult = len;
+		return ret;
+	}
+
+	if (sizeof(buf) < len || n < len-1) {
+		/* XXX should recover state? */
+		*nresult = (size_t)-1;
+		return E2BIG;
+	}
+
+	memcpy(s, buf, len-1);
+	*nresult = len-1;
+	return (0);
+}
+
+static int
+_citrus_ISO2022_wcrtomb_priv(_ISO2022EncodingInfo * __restrict ei,
+			     char * __restrict s, size_t n, wchar_t wc,
+			     _ISO2022State * __restrict psenc,
+			     size_t * __restrict nresult)
+{
+	char buf[MB_LEN_MAX];
+	char *result;
+	int ret;
+	size_t len;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != 0);
+
+	/* XXX state will be modified after this operation... */
+	ret = _ISO2022_sputwchar(ei, wc, buf, sizeof(buf), &result, psenc,
+	    &len);
+	if (ret) {
+		*nresult = len;
+		return ret;
+	}
+
+	if (sizeof(buf) < len || n < len) {
+		/* XXX should recover state? */
+		*nresult = (size_t)-1;
+		return E2BIG;
+	}
+
+	memcpy(s, buf, len);
+	*nresult = len;
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ISO2022_stdenc_wctocs(_ISO2022EncodingInfo * __restrict ei,
+			      _csid_t * __restrict csid,
+			      _index_t * __restrict idx, wchar_t wc)
+{
+	wchar_t m, nm;
+
+	_DIAGASSERT(csid != NULL && idx != NULL);
+
+	m = wc & 0x7FFF8080;
+	nm = wc & 0x007F7F7F;
+	if (m & 0x00800000) {
+		nm &= 0x00007F7F;
+	} else {
+		m &= 0x7F008080;
+	}
+	if (nm & 0x007F0000) {
+		/* ^3 mark */
+		m |= 0x007F0000;
+	} else if (nm & 0x00007F00) {
+		/* ^2 mark */
+		m |= 0x00007F00;
+	}
+	*csid = (_csid_t)m;
+	*idx  = (_index_t)nm;
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ISO2022_stdenc_cstowc(_ISO2022EncodingInfo * __restrict ei,
+			      wchar_t * __restrict wc,
+			      _csid_t csid, _index_t idx)
+{
+
+	_DIAGASSERT(ei != NULL && wc != NULL);
+
+	*wc = (wchar_t)(csid & 0x7F808080) | (wchar_t)idx;
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ISO2022_stdenc_get_state_desc_generic(_ISO2022EncodingInfo * __restrict ei,
+					      _ISO2022State * __restrict psenc,
+					      int * __restrict rstate)
+{
+
+	if (psenc->chlen == 0) {
+		/* XXX: it should distinguish initial and stable. */
+		*rstate = _STDENC_SDGEN_STABLE;
+	} else {
+		if (psenc->ch[0] == '\033')
+			*rstate = _STDENC_SDGEN_INCOMPLETE_SHIFT;
+		else
+			*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(ISO2022);
+_CITRUS_CTYPE_DEF_OPS(ISO2022);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(ISO2022);
+_CITRUS_STDENC_DEF_OPS(ISO2022);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(ISO2022_ctype);
+KICONV_GETOPS(ISO2022_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_ISO2022, "kiconv");
+
+static int
+kiconv_ISO2022_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_ISO2022_ctype_getops);
+		kiconv_attach_getops(&kiconv_ISO2022_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_ISO2022_stdenc_getops);
+		kiconv_detach_getops(&kiconv_ISO2022_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_iso2022.h src/sys/kiconv/modules/citrus_iso2022.h
--- src.orig/sys/kiconv/modules/citrus_iso2022.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_iso2022.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/*	$NetBSD: citrus_iso2022.h,v 1.2 2003/06/25 09:51:44 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ISO2022_H_
+#define _CITRUS_ISO2022_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(ISO2022);
+_CITRUS_STDENC_GETOPS_FUNC(ISO2022);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_johab.c src/sys/kiconv/modules/citrus_johab.c
--- src.orig/sys/kiconv/modules/citrus_johab.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_johab.c	2011-06-03 21:21:30.000000000 +0900
@@ -0,0 +1,436 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_johab.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+	int chlen;
+	char ch[2];
+} _JOHABState;
+
+typedef struct {
+	int dummy;
+} _JOHABEncodingInfo;
+
+typedef struct {
+	_JOHABEncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_JOHABState	s_mblen;
+		_JOHABState	s_mbrlen;
+		_JOHABState	s_mbrtowc;
+		_JOHABState	s_mbtowc;
+		_JOHABState	s_mbsrtowcs;
+		_JOHABState	s_wcrtomb;
+		_JOHABState	s_wcsrtombs;
+		_JOHABState	s_wctomb;
+	} states;
+} _JOHABCTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_JOHAB_##m
+#define _ENCODING_INFO			_JOHABEncodingInfo
+#define _CTYPE_INFO			_JOHABCTypeInfo
+#define _ENCODING_STATE			_JOHABState
+#define _ENCODING_MB_CUR_MAX(_ei_)		2
+#define _ENCODING_IS_STATE_DEPENDENT		0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+
+static __inline void
+/*ARGSUSED*/
+_citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei,
+	_JOHABState * __restrict psenc)
+{
+	/* ei may be null */
+	_DIAGASSERT(psenc != NULL);
+
+	psenc->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_JOHAB_pack_state(_JOHABEncodingInfo * __restrict ei,
+	void * __restrict pspriv,
+	const _JOHABState * __restrict psenc)
+{
+	/* ei may be null */
+	_DIAGASSERT(pspriv != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_JOHAB_unpack_state(_JOHABEncodingInfo * __restrict ei,
+	_JOHABState * __restrict psenc,
+	const void * __restrict pspriv)
+{
+	/* ei may be null */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(pspriv != NULL);
+
+	memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static void
+/*ARGSUSED*/
+_citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo *ei)
+{
+	/* ei may be null */
+}
+
+static int
+/*ARGSUSED*/
+_citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei,
+	const void * __restrict var, size_t lenvar)
+{
+	/* ei may be null */
+	return 0;
+}
+
+static __inline int
+ishangul(int l, int t)
+{
+
+	return (l >= 0x84 && l <= 0xD3) &&
+	      ((t >= 0x41 && t <= 0x7E) || (t >= 0x81 && t <= 0xFE));
+}
+
+static __inline int
+isuda(int l, int t)
+{
+	return (l == 0xD8) &&
+	       ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE));
+}
+
+static __inline int
+ishanja(int l, int t)
+{
+	return ((l >= 0xD9 && l <= 0xDE) || (l >= 0xE0 && l <= 0xF9)) &&
+	       ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,
+	wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
+	_JOHABState * __restrict psenc, size_t * __restrict nresult)
+{
+	const char *s0;
+	int l, t;
+
+	/* ei may be unused */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != 0);
+
+	if (*s == NULL) {
+		_citrus_JOHAB_init_state(ei, psenc);
+		*nresult = _ENCODING_IS_STATE_DEPENDENT;
+		return 0;
+	} 
+	s0 = *s;
+
+	switch (psenc->chlen) {
+	case 0:
+		if (n-- < 1)
+			goto restart;
+		l = *s0++ & 0xFF;
+		if (l <= 0x7F) {
+			if (pwc != NULL)
+				*pwc = (wchar_t)l;
+			*nresult = (l == 0) ? 0 : 1;
+			*s = s0;
+			return 0;
+		}
+		psenc->ch[psenc->chlen++] = l;
+		break;
+	case 1:
+		l = psenc->ch[0] & 0xFF;
+		break;
+	default:
+		return EINVAL;
+	}
+	if (n-- < 1) {
+restart:
+		*nresult = (size_t)-2;
+		*s = s0;
+		return 0;
+	}
+	t = *s0++ & 0xFF;
+	if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t)) {
+		*nresult = (size_t)-1;
+		return EILSEQ;
+	}
+	if (pwc != NULL)
+		*pwc = (wchar_t)(l << 8 | t);
+	*nresult = s0 - *s;
+	*s = s0;
+	psenc->chlen = 0;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, wchar_t wc,
+	_JOHABState * __restrict psenc, size_t * __restrict nresult)
+{
+	int l, t;
+
+	/* ei may be unused */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (psenc->chlen != 0)
+		return EINVAL;
+
+	/* XXX assume wchar_t as int */
+	if ((uint32_t)wc <= 0x7F) {
+		if (n < 1)
+			goto e2big;
+		*s = wc & 0xFF;
+		*nresult = 1;
+	} else if ((uint32_t)wc <= 0xFFFF) {
+		if (n < 2) {
+e2big:
+			*nresult = (size_t)-1;
+			return E2BIG;
+		}
+		l = (wc >> 8) & 0xFF;
+		t = wc & 0xFF;
+		if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t))
+			goto ilseq;
+		*s++ = l;
+		*s = t;
+		*nresult = 2;
+	} else {
+ilseq:
+		*nresult = (size_t)-1;
+		return EILSEQ;
+	}
+	return 0;
+
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei,
+	_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+	int m, l, t, linear;
+
+	/* ei may be unused */
+	_DIAGASSERT(csid != NULL);
+	_DIAGASSERT(idx != NULL);
+
+	/* XXX assume wchar_t as int */
+	if ((uint32_t)wc <= 0x7F) {
+		*idx = (_index_t)wc;
+		*csid = 0;
+	} else if ((uint32_t)wc <= 0xFFFF) {
+		l = (wc >> 8) & 0xFF;
+		t = wc & 0xFF;
+		if (ishangul(l, t) || isuda(l, t)) {
+			*idx = (_index_t)wc;
+			*csid = 1;
+		} else {
+			if (l >= 0xD9 && l <= 0xDE) {
+				linear = l - 0xD9;
+				m = 0x21;
+			} else if (l >= 0xE0 && l <= 0xF9) {
+				linear = l - 0xE0;
+				m = 0x4A;
+			} else {
+				return EILSEQ;
+			}
+			linear *= 188;
+			if (t >= 0x31 && t <= 0x7E) {
+				linear += t - 0x31;
+			} else if (t >= 0x91 && t <= 0xFE) {
+				linear += t - 0x43;
+			} else {
+				return EILSEQ;
+			}
+			l = (linear / 94) + m;
+			t = (linear % 94) + 0x21;
+			*idx = (_index_t)((l << 8) | t);
+			*csid = 2;
+		}
+	} else {
+		return EILSEQ;
+	}
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei,
+	wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+	int m, n, l, t, linear;
+
+	/* ei may be unused */
+	_DIAGASSERT(wc != NULL);
+
+	switch (csid) {
+	case 0:
+	case 1:
+		*wc = (wchar_t)idx;
+		break;
+	case 2:
+		if (idx >= 0x2121 && idx <= 0x2C71) {
+			m = 0xD9;
+			n = 0x21;
+		} else if (idx >= 0x4A21 && idx <= 0x7D7E) {
+			m = 0xE0;
+			n = 0x4A;
+		} else {
+			return EILSEQ;
+		}
+		l = ((idx >> 8) & 0xFF) - n;
+		t = (idx & 0xFF) - 0x21;
+		linear = (l * 94) + t;
+		l = (linear / 188) + m;
+		t = linear % 188;
+		t += (t <= 0x4D) ? 0x31 : 0x43;
+		break;
+	default:
+		return EILSEQ;
+	}
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei,
+	_JOHABState * __restrict psenc, int * __restrict rstate)
+{
+	/* ei may be unused */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(rstate != NULL);
+
+	*rstate = (psenc->chlen == 0)
+	    ? _STDENC_SDGEN_INITIAL
+	    : _STDENC_SDGEN_INCOMPLETE_CHAR;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(JOHAB);
+_CITRUS_CTYPE_DEF_OPS(JOHAB);
+
+#include "citrus_ctype_template.h"
+
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(JOHAB);
+_CITRUS_STDENC_DEF_OPS(JOHAB);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(JOHAB_ctype);
+KICONV_GETOPS(JOHAB_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_JOHAB, "kiconv");
+
+static int
+kiconv_JOHAB_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_JOHAB_ctype_getops);
+		kiconv_attach_getops(&kiconv_JOHAB_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_JOHAB_stdenc_getops);
+		kiconv_detach_getops(&kiconv_JOHAB_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_johab.h src/sys/kiconv/modules/citrus_johab.h
--- src.orig/sys/kiconv/modules/citrus_johab.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_johab.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/* $NetBSD: citrus_johab.h,v 1.1 2006/10/18 17:54:55 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_JOHAB_H_
+#define _CITRUS_JOHAB_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(JOHAB);
+_CITRUS_STDENC_GETOPS_FUNC(JOHAB);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_646.c src/sys/kiconv/modules/citrus_mapper_646.c
--- src.orig/sys/kiconv/modules/citrus_mapper_646.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_646.c	2011-06-03 21:21:33.000000000 +0900
@@ -0,0 +1,310 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_mapper_646.c,v 1.4 2003/07/14 11:37:49 tshiozak Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_mapper_646.c,v 1.4 2003/07/14 11:37:49 tshiozak Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/queue.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_mapper_646.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_646);
+_CITRUS_MAPPER_DEF_OPS(mapper_646);
+
+/* ---------------------------------------------------------------------- */
+
+#define ILSEQ	0xFFFFFFFE
+#define INVALID	0xFFFFFFFF
+#define SPECIALS(x)				\
+	x(0x23)					\
+	x(0x24)					\
+	x(0x40)					\
+	x(0x5B)					\
+	x(0x5C)					\
+	x(0x5D)					\
+	x(0x5E)					\
+	x(0x60)					\
+	x(0x7B)					\
+	x(0x7C)					\
+	x(0x7D)					\
+	x(0x7E)
+
+#define INDEX(x) INDEX_##x,
+
+enum {
+	SPECIALS(INDEX)
+	NUM_OF_SPECIALS
+};
+struct _citrus_mapper_646 {
+	int		m6_forward;
+	_index_t	m6_map[NUM_OF_SPECIALS];
+};
+
+int
+_citrus_mapper_646_mapper_getops(struct _citrus_mapper_ops *ops,
+				 size_t lenops, uint32_t expected_version)
+{
+	if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
+		return EINVAL;
+
+	memcpy(ops, &_citrus_mapper_646_mapper_ops,
+	       sizeof(_citrus_mapper_646_mapper_ops));
+
+	return 0;
+}
+
+#define T_COMM '#'
+static int
+parse_file(struct _citrus_mapper_646 *m6, const char *path)
+{
+	int ret, i;
+	struct _region r;
+	struct _memstream ms;
+	const char *p;
+	size_t len;
+	char *buf, *q;
+
+	ret = _map_file(&r, path);
+	if (ret)
+		return ret;
+	buf = PNBUF_GET();
+	KASSERT(buf != NULL);
+	_memstream_bind(&ms, &r);
+	for (i=0; i<NUM_OF_SPECIALS; i++) {
+retry:
+		p = _memstream_getln(&ms, &len);
+		if (p==NULL) {
+			ret = EINVAL;
+			break;
+		}
+		p = _bcs_skip_ws_len(p, &len);
+		if (*p == T_COMM || len==0)
+			goto retry;
+		if (!_bcs_isdigit(*p)) {
+			ret = EINVAL;
+			break;
+		}
+		snprintf(buf, PATH_MAX, "%.*s", (int)len, p);
+		q = __UNCONST(p);
+		m6->m6_map[i] = strtoul(buf, &q, 0);
+		p = _bcs_skip_ws(buf);
+		if (*p != T_COMM && !*p) {
+			ret = EINVAL;
+			break;
+		}
+	}
+	PNBUF_PUT(buf);
+	_unmap_file(&r);
+
+	return ret;
+};
+
+static int
+parse_var(struct _citrus_mapper_646 *m6, struct _memstream *ms,
+	  const char *dir)
+{
+	struct _region r = { .r_head = NULL, .r_size = 0 };
+	char *path;
+	int error;
+
+	path = PNBUF_GET();
+	KASSERT(path != NULL);
+
+	m6->m6_forward = 1;
+	_memstream_skip_ws(ms);
+	/* whether backward */
+	if (_memstream_peek(ms) == '!') {
+		_memstream_getc(ms);
+		m6->m6_forward = 0;
+	}
+	/* get description file path */
+	_memstream_getregion(ms, &r, _memstream_remainder(ms));
+	snprintf(path, PATH_MAX, "%s/%.*s",
+		 dir, (int)_region_size(&r), (char *)_region_head(&r));
+	/* remove trailing white spaces */
+	path[_bcs_skip_nonws(path)-path] = '\0';
+	error = parse_file(m6, path);
+	PNBUF_PUT(path);
+	return error;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_646_mapper_init(struct _citrus_mapper_area *__restrict ma,
+			       struct _citrus_mapper * __restrict cm,
+			       const char * __restrict dir,
+			       const void * __restrict var, size_t lenvar,
+			       struct _citrus_mapper_traits * __restrict mt,
+			       size_t lenmt)
+{
+	struct _citrus_mapper_646 *m6;
+	struct _memstream ms;
+	struct _region r;
+	int ret;
+
+	_DIAGASSERT(cm && dir && mt);
+
+	if (lenmt<sizeof(*mt))
+		return EINVAL;
+
+	m6 = malloc(sizeof(*m6), M_KICONV, M_WAITOK);
+
+	_region_init(&r, __UNCONST(var), lenvar);
+	_memstream_bind(&ms, &r);
+	ret = parse_var(m6, &ms, dir);
+	if (ret) {
+		free(m6, M_KICONV);
+		return ret;
+	}
+
+	cm->cm_closure = m6;
+	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
+	mt->mt_state_size = 0;			/* stateless */
+
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_646_mapper_uninit(struct _citrus_mapper *cm)
+{
+	if (cm && cm->cm_closure) {
+		free(cm->cm_closure, M_KICONV);
+	}
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_646_mapper_convert(struct _citrus_mapper * __restrict cm,
+				  _index_t * __restrict dst, _index_t src,
+				  void * __restrict ps)
+{
+	struct _citrus_mapper_646 *m6;
+
+	_DIAGASSERT(cm && cm->cm_closure);
+
+	m6 = cm->cm_closure;
+	if (m6->m6_forward) {
+		/* forward */
+		if (src>=0x80)
+			return _MAPPER_CONVERT_ILSEQ;
+#define FORWARD(x)					\
+if (src==(x)) {						\
+	if (m6->m6_map[INDEX_##x]==INVALID)		\
+		return _MAPPER_CONVERT_NONIDENTICAL;	\
+	*dst = m6->m6_map[INDEX_##x];			\
+	return 0;					\
+} else
+		SPECIALS(FORWARD) {/*Nothing to do*/}
+		*dst = src;
+	} else {
+		/* backward */
+#define BACKWARD(x)							\
+if (m6->m6_map[INDEX_##x]!=INVALID && src==m6->m6_map[INDEX_##x]) {	\
+	*dst = (x);							\
+	return 0;							\
+} else if (src==(x))							\
+	return _MAPPER_CONVERT_ILSEQ;					\
+else
+		SPECIALS(BACKWARD) {/*Nothing to do*/}
+		if (src>=0x80)
+			return _MAPPER_CONVERT_NONIDENTICAL;
+		*dst = src;
+	}
+
+	return _MAPPER_CONVERT_SUCCESS;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_646_mapper_init_state(struct _citrus_mapper * __restrict cm,
+				     void * __restrict ps)
+{
+}
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(mapper_646_mapper);
+
+MODULE(MODULE_CLASS_MISC, kiconv_mapper_646, "kiconv");
+
+static int
+kiconv_mapper_646_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_mapper_646_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_mapper_646_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_646.h src/sys/kiconv/modules/citrus_mapper_646.h
--- src.orig/sys/kiconv/modules/citrus_mapper_646.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_646.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/*	$NetBSD: citrus_mapper_646.h,v 1.1 2003/06/25 09:51:45 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_646_H_
+#define _CITRUS_MAPPER_646_H_
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_646);
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_646);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_none.c src/sys/kiconv/modules/citrus_mapper_none.c
--- src.orig/sys/kiconv/modules/citrus_mapper_none.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_none.c	2011-06-03 21:21:35.000000000 +0900
@@ -0,0 +1,152 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_mapper_none.c,v 1.2 2003/06/27 17:53:31 tshiozak Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_mapper_none.c,v 1.2 2003/06/27 17:53:31 tshiozak Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/queue.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_mapper_none.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_none);
+_CITRUS_MAPPER_DEF_OPS(mapper_none);
+
+
+/* ---------------------------------------------------------------------- */
+
+int
+_citrus_mapper_none_mapper_getops(struct _citrus_mapper_ops *ops,
+				  size_t lenops, uint32_t expected_version)
+{
+	if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
+		return (EINVAL);
+
+	memcpy(ops, &_citrus_mapper_none_mapper_ops,
+	       sizeof(_citrus_mapper_none_mapper_ops));
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_none_mapper_init(struct _citrus_mapper_area *__restrict ma,
+				struct _citrus_mapper * __restrict cm,
+				const char * __restrict dir,
+				const void * __restrict var, size_t lenvar,
+				struct _citrus_mapper_traits * __restrict mt,
+				size_t lenmt)
+{
+
+	_DIAGASSERT(cm && dir && mt);
+
+	if (lenmt<sizeof(*mt))
+		return (EINVAL);
+
+	cm->cm_closure = NULL;
+	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
+	mt->mt_state_size = 0;			/* stateless */
+
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_none_mapper_uninit(struct _citrus_mapper *cm)
+{
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_none_mapper_convert(struct _citrus_mapper * __restrict cm,
+				   _citrus_index_t * __restrict dst,
+				   _citrus_index_t src, void * __restrict ps)
+{
+	*dst = src;
+	return _CITRUS_MAPPER_CONVERT_SUCCESS;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_none_mapper_init_state(struct _citrus_mapper * __restrict cm,
+				      void * __restrict ps)
+{
+}
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(mapper_none_mapper);
+
+MODULE(MODULE_CLASS_MISC, kiconv_mapper_none, "kiconv");
+
+static int
+kiconv_mapper_none_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_mapper_none_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_mapper_none_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_none.h src/sys/kiconv/modules/citrus_mapper_none.h
--- src.orig/sys/kiconv/modules/citrus_mapper_none.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_none.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,36 @@
+/*	$NetBSD: citrus_mapper_none.h,v 1.1 2003/06/25 09:51:45 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_NONE_H_
+#define _CITRUS_MAPPER_NONE_H_
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_none);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_serial.c src/sys/kiconv/modules/citrus_mapper_serial.c
--- src.orig/sys/kiconv/modules/citrus_mapper_serial.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_serial.c	2011-06-03 21:21:40.000000000 +0900
@@ -0,0 +1,338 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 tshiozak Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 tshiozak Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/namei.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/queue.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_mapper_serial.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_serial);
+_CITRUS_MAPPER_DEF_OPS(mapper_serial);
+
+#define _citrus_mapper_parallel_mapper_init		\
+	_citrus_mapper_serial_mapper_init
+#define _citrus_mapper_parallel_mapper_uninit		\
+	_citrus_mapper_serial_mapper_uninit
+#define _citrus_mapper_parallel_mapper_init_state	\
+	_citrus_mapper_serial_mapper_init_state
+static int	_citrus_mapper_parallel_mapper_convert(
+	struct _citrus_mapper * __restrict, _index_t * __restrict, _index_t,
+	void * __restrict);
+_CITRUS_MAPPER_DEF_OPS(mapper_parallel);
+#undef _citrus_mapper_parallel_mapper_init
+#undef _citrus_mapper_parallel_mapper_uninit
+#undef _citrus_mapper_parallel_mapper_init_state
+
+
+/* ---------------------------------------------------------------------- */
+
+struct maplink {
+	SIMPLEQ_ENTRY(maplink)	ml_entry;
+	struct _mapper		*ml_mapper;
+};
+SIMPLEQ_HEAD(maplist, maplink);
+
+struct _citrus_mapper_serial {
+	struct maplist	sr_mappers;
+};
+
+int
+_citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops,
+				    size_t lenops, uint32_t expected_version)
+{
+	if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
+		return EINVAL;
+
+	memcpy(ops, &_citrus_mapper_serial_mapper_ops,
+	       sizeof(_citrus_mapper_serial_mapper_ops));
+
+	return 0;
+}
+
+int
+_citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops,
+				      size_t lenops, uint32_t expected_version)
+{
+	if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
+		return EINVAL;
+
+	memcpy(ops, &_citrus_mapper_parallel_mapper_ops,
+	       sizeof(_citrus_mapper_parallel_mapper_ops));
+
+	return 0;
+}
+
+static void
+uninit(struct _citrus_mapper_serial *sr)
+{
+	struct maplink *ml;
+
+	while ((ml = SIMPLEQ_FIRST(&sr->sr_mappers)) != NULL) {
+		SIMPLEQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry);
+		_mapper_close(ml->ml_mapper);
+		free(ml, M_KICONV);
+	}
+}
+
+static int
+parse_var(struct _citrus_mapper_area *__restrict ma,
+	  struct _citrus_mapper_serial *sr, struct _memstream *ms)
+{
+	int ret;
+	struct _region r;
+	char *mapname;
+	struct maplink *ml;
+
+	mapname = PNBUF_GET();
+	KASSERT(mapname = NULL);
+
+	SIMPLEQ_INIT(&sr->sr_mappers);
+	while (1) {
+		/* remove beginning white spaces */
+		_memstream_skip_ws(ms);
+		if (_memstream_iseof(ms))
+			break;
+		/* cut down a mapper name */
+		_memstream_chr(ms, &r, ',');
+		snprintf(mapname, PATH_MAX, "%.*s",
+			 (int)_region_size(&r), (char *)_region_head(&r));
+		/* remove trailing white spaces */
+		mapname[_bcs_skip_nonws(mapname)-mapname] = '\0';
+		/* create a new mapper record */
+		ml = malloc(sizeof(*ml), M_KICONV, M_WAITOK);
+		ret = _mapper_open(ma, &ml->ml_mapper, mapname);
+		if (ret) {
+			free(ml, M_KICONV);
+			PNBUF_PUT(mapname);
+			return ret;
+		}
+		/* support only 1:1 and stateless converter */
+		if (_mapper_get_src_max(ml->ml_mapper) != 1 ||
+		    _mapper_get_dst_max(ml->ml_mapper) != 1 ||
+		    _mapper_get_state_size(ml->ml_mapper) != 0) {
+			free(ml, M_KICONV);
+			PNBUF_PUT(mapname);
+			return EINVAL;
+		}
+		SIMPLEQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry);
+	}
+	PNBUF_PUT(mapname);
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_serial_mapper_init(struct _citrus_mapper_area *__restrict ma,
+				  struct _citrus_mapper * __restrict cm,
+				  const char * __restrict dir,
+				  const void * __restrict var, size_t lenvar,
+				  struct _citrus_mapper_traits * __restrict mt,
+				  size_t lenmt)
+{
+	struct _citrus_mapper_serial *sr;
+	struct _memstream ms;
+	struct _region r;
+
+	_DIAGASSERT(cm && dir && mt);
+
+	if (lenmt<sizeof(*mt))
+		return EINVAL;
+
+	sr = malloc(sizeof(*sr), M_KICONV, M_WAITOK);
+
+	_region_init(&r, __UNCONST(var), lenvar);
+	_memstream_bind(&ms, &r);
+	if (parse_var(ma, sr, &ms)) {
+		uninit(sr);
+		free(sr, M_KICONV);
+		return EINVAL;
+	}
+	cm->cm_closure = sr;
+	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
+	mt->mt_state_size = 0;			/* stateless */
+
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm)
+{
+	if (cm && cm->cm_closure) {
+		uninit(cm->cm_closure);
+		free(cm->cm_closure, M_KICONV);
+	}
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm,
+				     _index_t * __restrict dst, _index_t src,
+				     void * __restrict ps)
+{
+	int ret;
+	struct _citrus_mapper_serial *sr;
+	struct maplink *ml;
+
+	_DIAGASSERT(cm && cm->cm_closure);
+
+	sr = cm->cm_closure;
+	SIMPLEQ_FOREACH(ml, &sr->sr_mappers, ml_entry) {
+		ret = _mapper_convert(ml->ml_mapper, &src, src, NULL);
+		if (ret != _MAPPER_CONVERT_SUCCESS)
+			return ret;
+	}
+	*dst = src;
+	return _MAPPER_CONVERT_SUCCESS;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm,
+				       _index_t * __restrict dst, _index_t src,
+				       void * __restrict ps)
+{
+	int ret;
+	struct _citrus_mapper_serial *sr;
+	struct maplink *ml;
+	_index_t tmp;
+
+	_DIAGASSERT(cm && cm->cm_closure);
+
+	sr = cm->cm_closure;
+	SIMPLEQ_FOREACH(ml, &sr->sr_mappers, ml_entry) {
+		ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL);
+		if (ret == _MAPPER_CONVERT_SUCCESS) {
+			*dst = tmp;
+			return _MAPPER_CONVERT_SUCCESS;
+		} else if (ret == _MAPPER_CONVERT_ILSEQ)
+			return _MAPPER_CONVERT_ILSEQ;
+	}
+	return _MAPPER_CONVERT_NONIDENTICAL;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_serial_mapper_init_state(struct _citrus_mapper * __restrict cm,
+					void * __restrict ps)
+{
+}
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+#if !defined(KICONV_MAPPER_ONLY_PARALLEL)
+KICONV_GETOPS(mapper_serial_mapper);
+
+MODULE(MODULE_CLASS_MISC, kiconv_mapper_serial, "kiconv");
+
+static int
+kiconv_mapper_serial_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_mapper_serial_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_mapper_serial_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif
+
+#if !defined(KICONV_MAPPER_ONLY_SERIAL)
+KICONV_GETOPS(mapper_parallel_mapper);
+
+MODULE(MODULE_CLASS_MISC, kiconv_mapper_parallel, "kiconv");
+
+static int
+kiconv_mapper_parallel_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_mapper_parallel_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_mapper_parallel_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_serial.h src/sys/kiconv/modules/citrus_mapper_serial.h
--- src.orig/sys/kiconv/modules/citrus_mapper_serial.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_serial.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/*	$NetBSD: citrus_mapper_serial.h,v 1.1 2003/06/25 09:51:46 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_SERIAL_H_
+#define _CITRUS_MAPPER_SERIAL_H_
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_serial);
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_parallel);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_std.c src/sys/kiconv/modules/citrus_mapper_std.c
--- src.orig/sys/kiconv/modules/citrus_mapper_std.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_std.c	2011-06-03 21:21:43.000000000 +0900
@@ -0,0 +1,498 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_mapper_std.c,v 1.8 2006/09/11 13:06:33 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)2003, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_mapper_std.c,v 1.8 2006/09/11 13:06:33 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/namei.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <machine/endian.h>
+#include <sys/queue.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_mmap.h"
+#include "citrus_module.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_db.h"
+#include "citrus_db_hash.h"
+
+#include "citrus_mapper_std.h"
+#include "citrus_mapper_std_file.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_std);
+_CITRUS_MAPPER_DEF_OPS(mapper_std);
+
+
+/* ---------------------------------------------------------------------- */
+
+int
+_citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops *ops, size_t lenops,
+				 u_int32_t expected_version)
+{
+	if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
+		return (EINVAL);
+
+	memcpy(ops, &_citrus_mapper_std_mapper_ops,
+	       sizeof(_citrus_mapper_std_mapper_ops));
+
+	return (0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int
+/*ARGSUSED*/
+rowcol_convert(struct _citrus_mapper_std * __restrict ms,
+	       _index_t * __restrict dst, _index_t src,
+	       void * __restrict ps)
+{
+	struct _citrus_mapper_std_rowcol *rc;
+	size_t i;
+	struct _citrus_mapper_std_linear_zone *lz;
+	_index_t n, idx = 0;
+	u_int32_t conv;
+
+	_DIAGASSERT(ms != NULL);
+	_DIAGASSERT(dst != NULL);
+	/* ps may be unused */
+	rc = &ms->ms_rowcol;
+
+	for (i = rc->rc_src_rowcol_len * rc->rc_src_rowcol_bits,
+	     lz = &rc->rc_src_rowcol[0]; i > 0; ++lz) {
+		i -= rc->rc_src_rowcol_bits;
+		n = (src >> i) & rc->rc_src_rowcol_mask;
+		if (n < lz->begin || n > lz->end) {
+			switch (rc->rc_oob_mode) {
+			case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL:
+				*dst = rc->rc_dst_invalid;
+				return _MAPPER_CONVERT_NONIDENTICAL;
+			case _CITRUS_MAPPER_STD_OOB_ILSEQ:
+				return _MAPPER_CONVERT_ILSEQ;
+			default:
+				return _MAPPER_CONVERT_FATAL;
+			}
+		}
+		idx = idx * lz->width + n - lz->begin;
+	}
+	switch (rc->rc_dst_unit_bits) {
+	case 8:
+		conv = _region_peek8(&rc->rc_table, idx);
+		break;
+	case 16:
+		conv = be16toh(_region_peek16(&rc->rc_table, idx*2));
+		break;
+	case 32:
+		conv = be32toh(_region_peek32(&rc->rc_table, idx*4));
+		break;
+	default:
+		return _MAPPER_CONVERT_FATAL;
+	}
+
+	if (conv == rc->rc_dst_invalid) {
+		*dst = rc->rc_dst_invalid;
+		return _MAPPER_CONVERT_NONIDENTICAL;
+	}
+	if (conv == rc->rc_dst_ilseq)
+		return _MAPPER_CONVERT_ILSEQ;
+
+	*dst = conv;
+
+	return _MAPPER_CONVERT_SUCCESS;
+}
+
+static __inline int
+set_linear_zone(struct _citrus_mapper_std_linear_zone *lz,
+	u_int32_t begin, u_int32_t end)
+{
+	_DIAGASSERT(lz != NULL);
+
+	if (begin > end)
+		return EFTYPE;
+
+	lz->begin = begin;
+	lz->end = end;
+	lz->width= end - begin + 1;
+
+	return 0;
+}
+
+static __inline int
+rowcol_parse_variable_compat(struct _citrus_mapper_std_rowcol *rc,
+	struct _region *r)
+{
+	const struct _citrus_mapper_std_rowcol_info_compat_x *rcx;
+	struct _citrus_mapper_std_linear_zone *lz;
+	u_int32_t m, n;
+	int ret;
+
+	_DIAGASSERT(rc != NULL);
+	_DIAGASSERT(r != NULL && _region_size(r) == sizeof(*rcx));
+	rcx = _region_head(r);
+
+	rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid);
+	rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits);
+	m = be32toh(rcx->rcx_src_col_bits);
+	n = 1 << (m - 1);
+	n |= n - 1;
+	rc->rc_src_rowcol_bits = m;
+	rc->rc_src_rowcol_mask = n;
+
+	rc->rc_src_rowcol = malloc(2 *
+	    sizeof(*rc->rc_src_rowcol), M_KICONV, M_WAITOK);
+	lz = rc->rc_src_rowcol;
+	rc->rc_src_rowcol_len = 1;
+	m = be32toh(rcx->rcx_src_row_begin);
+	n = be32toh(rcx->rcx_src_row_end);
+	if (m + n > 0) {
+		ret = set_linear_zone(lz, m, n);
+		if (ret != 0)
+			return ret;
+		++rc->rc_src_rowcol_len, ++lz;
+	}
+	m = be32toh(rcx->rcx_src_col_begin);
+	n = be32toh(rcx->rcx_src_col_end);
+
+	return set_linear_zone(lz, m, n);
+}
+
+static __inline int
+rowcol_parse_variable(struct _citrus_mapper_std_rowcol *rc,
+	struct _region *r)
+{
+	const struct _citrus_mapper_std_rowcol_info_x *rcx;
+	struct _citrus_mapper_std_linear_zone *lz;
+	u_int32_t m, n;
+	size_t i;
+	int ret;
+
+	_DIAGASSERT(rc != NULL);
+	_DIAGASSERT(r != NULL && _region_size(r) == sizeof(*rcx));
+	rcx = _region_head(r);
+
+	rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid);
+	rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits);
+
+	m = be32toh(rcx->rcx_src_rowcol_bits);
+	n = 1 << (m - 1);
+	n |= n - 1;
+	rc->rc_src_rowcol_bits = m;
+	rc->rc_src_rowcol_mask = n;
+
+	rc->rc_src_rowcol_len = be32toh(rcx->rcx_src_rowcol_len);
+	if (rc->rc_src_rowcol_len > _CITRUS_MAPPER_STD_ROWCOL_MAX)
+		return EFTYPE;
+	rc->rc_src_rowcol = malloc(rc->rc_src_rowcol_len *
+	    sizeof(*rc->rc_src_rowcol), M_KICONV, M_WAITOK);
+	for (i = 0, lz = rc->rc_src_rowcol;
+	     i < rc->rc_src_rowcol_len; ++i, ++lz) {
+		m = be32toh(rcx->rcx_src_rowcol[i].begin),
+		n = be32toh(rcx->rcx_src_rowcol[i].end);
+		ret = set_linear_zone(lz, m, n);
+		if (ret != 0) {
+			free(rc->rc_src_rowcol, M_KICONV);
+			rc->rc_src_rowcol = NULL;
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static void
+rowcol_uninit(struct _citrus_mapper_std *ms)
+{
+	struct _citrus_mapper_std_rowcol *rc;
+	_DIAGASSERT(ms != NULL);
+
+	rc = &ms->ms_rowcol;
+	free(rc->rc_src_rowcol, M_KICONV);
+}
+
+static int
+rowcol_init(struct _citrus_mapper_std *ms)
+{
+	int ret;
+	struct _citrus_mapper_std_rowcol *rc;
+	const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x *eix;
+	struct _region r;
+	u_int64_t table_size;
+	size_t i;
+	struct _citrus_mapper_std_linear_zone *lz;
+
+	_DIAGASSERT(ms != NULL);
+	ms->ms_convert = &rowcol_convert;
+	ms->ms_uninit = &rowcol_uninit;
+	rc = &ms->ms_rowcol;
+
+	/* get table region */
+	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TABLE,
+			      &rc->rc_table, NULL);
+	if (ret) {
+		if (ret==ENOENT)
+			ret = EFTYPE;
+		return ret;
+	}
+
+	/* get table information */
+	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_INFO, &r, NULL);
+	if (ret) {
+		if (ret==ENOENT)
+			ret = EFTYPE;
+		return ret;
+	}
+	switch (_region_size(&r)) {
+	case _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE:
+		ret = rowcol_parse_variable_compat(rc, &r);
+		break;
+	case _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE:
+		ret = rowcol_parse_variable(rc, &r);
+		break;
+	default:
+		return EFTYPE;
+	}
+	if (ret != 0)
+		return ret;
+	/* sanity check */
+	switch (rc->rc_src_rowcol_bits) {
+	case 8: case 16: case 32:
+		if (rc->rc_src_rowcol_len <= 32 / rc->rc_src_rowcol_bits)
+			break;
+	/*FALLTHROUGH*/
+	default:
+		return EFTYPE;
+	}
+
+	/* ilseq extension */
+	rc->rc_oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL;
+	rc->rc_dst_ilseq = rc->rc_dst_invalid;
+	ret = _db_lookup_by_s(ms->ms_db,
+			      _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ,
+			      &r, NULL);
+	if (ret && ret != ENOENT)
+		return ret;
+	if (_region_size(&r) < sizeof(*eix))
+		return EFTYPE;
+	if (ret == 0) {
+		eix = _region_head(&r);
+		rc->rc_oob_mode = be32toh(eix->eix_oob_mode);
+		rc->rc_dst_ilseq = be32toh(eix->eix_dst_ilseq);
+	}
+
+	/* calcurate expected table size */
+	i = rc->rc_src_rowcol_len;
+	lz = &rc->rc_src_rowcol[--i];
+	table_size = lz->width;
+	while (i > 0) {
+		lz = &rc->rc_src_rowcol[--i];
+		table_size *= lz->width;
+	}
+	table_size *= rc->rc_dst_unit_bits/8;
+
+	if (table_size > UINT32_MAX ||
+	    _region_size(&rc->rc_table) < table_size)
+		return EFTYPE;
+
+	return 0;
+}
+
+typedef int (*initfunc_t)(struct _citrus_mapper_std *);
+static const struct {
+	const char			*t_name;
+	initfunc_t			t_init;
+} types[] = {
+	{ _CITRUS_MAPPER_STD_TYPE_ROWCOL, &rowcol_init },
+};
+#define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_std_mapper_init(struct _citrus_mapper_area *__restrict ma,
+			       struct _citrus_mapper * __restrict cm,
+			       const char * __restrict curdir,
+			       const void * __restrict var, size_t lenvar,
+			       struct _citrus_mapper_traits * __restrict mt,
+			       size_t lenmt)
+{
+	char *path;
+	const char *type;
+	int ret, id;
+	struct _citrus_mapper_std *ms;
+
+	/* set traits */
+	if (lenmt<sizeof(*mt)) {
+		ret = EINVAL;
+		goto err0;
+	}
+	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
+	mt->mt_state_size = 0;			/* stateless */
+
+	/* alloc mapper std structure */
+	ms = malloc(sizeof(*ms), M_KICONV, M_WAITOK);
+
+	/* open mapper file */
+	path = PNBUF_GET();
+	KASSERT(path != NULL);
+	snprintf(path, PATH_MAX,
+		 "%s/%.*s", curdir, (int)lenvar, (const char *)var);
+	ret = _map_file(&ms->ms_file, path);
+	PNBUF_PUT(path);
+	if (ret)
+		goto err1;
+
+	ret = _db_open(&ms->ms_db, &ms->ms_file, _CITRUS_MAPPER_STD_MAGIC,
+		       &_db_hash_std, NULL);
+	if (ret)
+		goto err2;
+
+	/* get mapper type */
+	ret = _db_lookupstr_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TYPE,
+				 &type, NULL);
+	if (ret) {
+		if (ret==ENOENT)
+			ret = EFTYPE;
+		goto err3;
+	}
+	for (id=0; id<NUM_OF_TYPES; id++)
+		if (_bcs_strcasecmp(type, types[id].t_name) == 0)
+			break;
+
+	if (id == NUM_OF_TYPES)
+		goto err3;
+
+	/* init the per-type structure */
+	ret = (*types[id].t_init)(ms);
+	if (ret)
+		goto err3;
+
+	cm->cm_closure = ms;
+
+	return 0;
+
+err3:
+	_db_close(ms->ms_db);
+err2:
+	_unmap_file(&ms->ms_file);
+err1:
+	free(ms, M_KICONV);
+err0:
+	return ret;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_std_mapper_uninit(struct _citrus_mapper *cm)
+{
+	struct _citrus_mapper_std *ms;
+
+	_DIAGASSERT(cm!=NULL & cm->cm_closure!=NULL);
+
+	ms = cm->cm_closure;
+	if (ms->ms_uninit)
+		(*ms->ms_uninit)(ms);
+	_db_close(ms->ms_db);
+	_unmap_file(&ms->ms_file);
+	free(ms, M_KICONV);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_std_mapper_init_state(struct _citrus_mapper * __restrict cm,
+				     void * __restrict ps)
+{
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm,
+				  _index_t * __restrict dst, _index_t src,
+				  void * __restrict ps)
+{
+	struct _citrus_mapper_std *ms;
+
+	_DIAGASSERT(cm!=NULL && cm->cm_closure!=NULL);
+
+	ms = cm->cm_closure;
+
+	_DIAGASSERT(ms->ms_convert != NULL);
+
+	return (*ms->ms_convert)(ms, dst, src, ps);
+}
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(mapper_std_mapper);
+
+MODULE(MODULE_CLASS_MISC, kiconv_mapper_std, "kiconv");
+
+static int
+kiconv_mapper_std_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_mapper_std_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_mapper_std_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_std.h src/sys/kiconv/modules/citrus_mapper_std.h
--- src.orig/sys/kiconv/modules/citrus_mapper_std.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_std.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,38 @@
+/*	$NetBSD: citrus_mapper_std.h,v 1.1 2003/06/25 09:51:47 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_STD_H_
+#define _CITRUS_MAPPER_STD_H_
+
+#include "citrus_mapper_std_local.h"
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_std);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_std_file.h src/sys/kiconv/modules/citrus_mapper_std_file.h
--- src.orig/sys/kiconv/modules/citrus_mapper_std_file.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_std_file.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,75 @@
+/*	$NetBSD: citrus_mapper_std_file.h,v 1.3 2006/09/09 14:35:17 tnozaki Exp $	*/
+
+/*-
+ * Copyright (c)2003, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_STD_FILE_H_
+#define _CITRUS_MAPPER_STD_FILE_H_
+
+#define _CITRUS_MAPPER_STD_MAGIC		"MAPPER\0\0"
+
+#define _CITRUS_MAPPER_STD_SYM_TYPE		"type"
+#define _CITRUS_MAPPER_STD_SYM_INFO		"info"
+#define _CITRUS_MAPPER_STD_SYM_TABLE		"table"
+
+#define _CITRUS_MAPPER_STD_TYPE_ROWCOL		"rowcol"
+struct _citrus_mapper_std_rowcol_info_x {
+	u_int32_t		rcx_src_rowcol_bits;
+	u_int32_t		rcx_dst_invalid;
+#define _CITRUS_MAPPER_STD_ROWCOL_MAX			4
+	struct {
+		u_int32_t		begin;
+		u_int32_t		end;
+	} __packed		rcx_src_rowcol[_CITRUS_MAPPER_STD_ROWCOL_MAX];
+	u_int32_t		rcx_dst_unit_bits;
+	u_int32_t		rcx_src_rowcol_len;
+} __packed;
+#define _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE		48
+
+/* old file layout */
+struct _citrus_mapper_std_rowcol_info_compat_x {
+	u_int32_t		rcx_src_col_bits;
+	u_int32_t		rcx_dst_invalid;
+	u_int32_t		rcx_src_row_begin;
+	u_int32_t		rcx_src_row_end;
+	u_int32_t		rcx_src_col_begin;
+	u_int32_t		rcx_src_col_end;
+	u_int32_t		rcx_dst_unit_bits;
+	u_int32_t		rcx_pad;
+} __packed;
+#define _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE	32
+
+/* rowcol oob extension info */
+#define _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ		"rowcol_ext_ilseq"
+struct _citrus_mapper_std_rowcol_ext_ilseq_info_x {
+#define _CITRUS_MAPPER_STD_OOB_NONIDENTICAL	0
+#define _CITRUS_MAPPER_STD_OOB_ILSEQ		1
+	u_int32_t		eix_oob_mode;
+	u_int32_t		eix_dst_ilseq;
+} __packed;
+#define _CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE	8
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_std_local.h src/sys/kiconv/modules/citrus_mapper_std_local.h
--- src.orig/sys/kiconv/modules/citrus_mapper_std_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_std_local.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,70 @@
+/*	$NetBSD: citrus_mapper_std_local.h,v 1.3 2006/09/09 14:35:17 tnozaki Exp $	*/
+
+/*-
+ * Copyright (c)2003, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_STD_LOCAL_H_
+#define _CITRUS_MAPPER_STD_LOCAL_H_
+
+typedef u_int32_t (*_citrus_mapper_std_getvalfunc_t)(const void *, u_int32_t);
+
+struct _citrus_mapper_std_linear_zone {
+	_citrus_index_t		begin;
+	_citrus_index_t		end;
+	_citrus_index_t		width;
+};
+struct _citrus_mapper_std_rowcol {
+	struct _citrus_region	rc_table;
+	size_t			rc_src_rowcol_len;
+	struct _citrus_mapper_std_linear_zone
+				*rc_src_rowcol;
+	_citrus_index_t		rc_src_rowcol_bits;
+	_citrus_index_t		rc_src_rowcol_mask;
+	_citrus_index_t		rc_dst_invalid;
+	_citrus_index_t		rc_dst_unit_bits;
+	int			rc_oob_mode;
+	_citrus_index_t		rc_dst_ilseq;
+};
+
+struct _citrus_mapper_std;
+
+typedef int (*_citrus_mapper_std_convert_t)(
+	struct _citrus_mapper_std *__restrict,
+	_index_t *__restrict, _index_t, void *__restrict);
+typedef void (*_citrus_mapper_std_uninit_t)(struct _citrus_mapper_std *);
+
+struct _citrus_mapper_std {
+	struct _citrus_region		ms_file;
+	struct _citrus_db		*ms_db;
+	_citrus_mapper_std_convert_t	ms_convert;
+	_citrus_mapper_std_uninit_t	ms_uninit;
+	union {
+		struct _citrus_mapper_std_rowcol	rowcol;
+	} u;
+#define ms_rowcol	u.rowcol
+};
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_zone.c src/sys/kiconv/modules/citrus_mapper_zone.c
--- src.orig/sys/kiconv/modules/citrus_mapper_zone.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_zone.c	2011-06-03 21:21:46.000000000 +0900
@@ -0,0 +1,440 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_mapper_zone.c,v 1.4 2003/07/12 15:39:21 tshiozak Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_mapper_zone.c,v 1.4 2003/07/12 15:39:21 tshiozak Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+#include <sys/fcntl.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/queue.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_mapper_zone.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_zone);
+_CITRUS_MAPPER_DEF_OPS(mapper_zone);
+
+
+/* ---------------------------------------------------------------------- */
+
+struct _zone {
+	u_int32_t z_begin;
+	u_int32_t z_end;
+};
+
+struct _citrus_mapper_zone {
+	struct _zone	mz_row;
+	struct _zone	mz_col;
+	int		mz_col_bits;
+	int32_t		mz_row_offset;
+	int32_t		mz_col_offset;
+};
+
+struct _parse_state {
+	enum { S_BEGIN, S_OFFSET }	ps_state;
+	union {
+		u_int32_t	u_imm;
+		int32_t		s_imm;
+		struct _zone	zone;
+	} u;
+#define ps_u_imm	u.u_imm
+#define ps_s_imm	u.s_imm
+#define ps_zone		u.zone
+	int ps_top;
+};
+
+int
+_citrus_mapper_zone_mapper_getops(struct _citrus_mapper_ops *ops,
+				  size_t lenops, uint32_t expected_version)
+{
+	if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
+		return EINVAL;
+
+	memcpy(ops, &_citrus_mapper_zone_mapper_ops,
+	       sizeof(_citrus_mapper_zone_mapper_ops));
+
+	return 0;
+}
+
+#define BUFSIZE 20
+#define T_ERR	0x100
+#define T_IMM	0x101
+
+static int
+get_imm(struct _memstream *ms, struct _parse_state *ps)
+{
+	int sign = 0;
+	int c, i;
+	char buf[BUFSIZE+1], *p;
+
+	for (i=0; i<BUFSIZE; i++) {
+retry:
+		c = _memstream_peek(ms);
+		if (i==0) {
+			if (sign == 0 && (c == '+' || c == '-')) {
+				sign = c;
+				_memstream_getc(ms);
+				goto retry;
+			} else if (!_bcs_isdigit(c))
+				break;
+		} else if (!_bcs_isxdigit(c))
+			if (!(i==1 && c == 'x'))
+				break;
+		buf[i] = _memstream_getc(ms);
+	}
+	buf[i] = '\0';
+	ps->ps_u_imm = strtoul(buf, &p, 0);
+	if ((p-buf) != i)
+		return T_ERR;
+	if (sign == '-')
+		ps->ps_u_imm = (unsigned long)-(long)ps->ps_u_imm;
+	return T_IMM;
+}
+
+static int
+get_tok(struct _memstream *ms, struct _parse_state *ps)
+{
+	int c;
+
+loop:
+	c = _memstream_peek(ms);
+	if (c==0x00)
+		return EOF;
+	if (_bcs_isspace(c)) {
+		_memstream_getc(ms);
+		goto loop;
+	}
+
+	switch (ps->ps_state) {
+	case S_BEGIN:
+		switch (c) {
+		case ':':
+		case '-':
+		case '/':
+			_memstream_getc(ms);
+			return c;
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			return get_imm(ms, ps);
+		}
+		break;
+	case S_OFFSET:
+		switch (c) {
+		case '/':
+			_memstream_getc(ms);
+			return c;
+		case '+': 
+		case '-': 
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			return get_imm(ms, ps);
+		}
+		break;
+	}
+	return T_ERR;
+}
+
+static int
+parse_zone(struct _memstream *ms, struct _parse_state *ps, struct _zone *z)
+{
+	if (get_tok(ms, ps) != T_IMM)
+		return -1;
+	z->z_begin = ps->ps_u_imm;
+	if (get_tok(ms, ps) != '-')
+		return -1;
+	if (get_tok(ms, ps) != T_IMM)
+		return -1;
+	z->z_end = ps->ps_u_imm;
+
+	if (z->z_begin > z->z_end)
+		return -1;
+
+	return 0;
+}
+
+static int
+check_rowcol(struct _zone *z, int32_t ofs, uint32_t maxval)
+{
+	u_int32_t remain;
+
+	if (maxval != 0 && z->z_end >= maxval)
+		return -1;
+
+	if (ofs > 0) {
+		if (maxval == 0) {
+			/* this should 0x100000000 - z->z_end */
+			if (z->z_end == 0) {
+				remain = 0xFFFFFFFF;
+			} else {
+				remain = 0xFFFFFFFF - z->z_end + 1;
+			}
+		} else
+			remain = maxval - z->z_end;
+		if ((u_int32_t)ofs > remain)
+			return -1;
+	} else if (ofs < 0) {
+		if (z->z_begin < (u_int32_t)-ofs)
+			return -1;
+	}
+
+	return 0;
+}
+
+static int
+parse_var(struct _citrus_mapper_zone *mz, struct _memstream *ms)
+{
+	struct _parse_state ps;
+	int ret, isrc;
+	uint32_t rowmax, colmax;
+
+	ps.ps_state = S_BEGIN;
+
+	if (parse_zone(ms, &ps, &mz->mz_col))
+		return -1;
+
+	ret = get_tok(ms, &ps);
+	if (ret == '/') {
+		/* rowzone / colzone / bits */
+		isrc = 1;
+		mz->mz_row = mz->mz_col;
+
+		if (parse_zone(ms, &ps, &mz->mz_col))
+			return -1;
+		if (get_tok(ms, &ps) != '/')
+			return -1;
+		if (get_tok(ms, &ps) != T_IMM)
+			return -1;
+		mz->mz_col_bits = ps.ps_u_imm;
+		if (mz->mz_col_bits<0 || mz->mz_col_bits>32)
+			return -1;
+		ret = get_tok(ms, &ps);
+	} else {
+		/* colzone */
+		isrc = 0;
+		mz->mz_col_bits = 32;
+		mz->mz_row.z_begin = mz->mz_row.z_end = 0;
+	}
+	if (ret == ':') {
+		/* offset */
+		ps.ps_state = S_OFFSET;
+		if (get_tok(ms, &ps) != T_IMM)
+			return -1;
+		mz->mz_col_offset = ps.ps_s_imm;
+		if (isrc) {
+			/* row/col */
+			mz->mz_row_offset = mz->mz_col_offset;
+			if (get_tok(ms, &ps) != '/')
+				return -1;
+			if (get_tok(ms, &ps) != T_IMM)
+				return -1;
+			mz->mz_col_offset = ps.ps_s_imm;
+		} else
+			mz->mz_row_offset = 0;
+		ret = get_tok(ms, &ps);
+	}
+	if (ret != EOF)
+		return -1;
+
+	/* sanity check */
+	if (mz->mz_col_bits==32)
+		colmax = 0;
+	else
+		colmax = 1 << mz->mz_col_bits;
+	if (mz->mz_col_bits==0)
+		rowmax = 0;
+	else
+		rowmax = 1 << (32-mz->mz_col_bits);
+	if (check_rowcol(&mz->mz_col, mz->mz_col_offset, colmax))
+		return -1;
+	if (check_rowcol(&mz->mz_row, mz->mz_row_offset, rowmax))
+		return -1;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_zone_mapper_init(struct _citrus_mapper_area *__restrict ma,
+				struct _citrus_mapper * __restrict cm,
+				const char * __restrict dir,
+				const void * __restrict var, size_t lenvar,
+				struct _citrus_mapper_traits * __restrict mt,
+				size_t lenmt)
+{
+	struct _citrus_mapper_zone *mz;
+	struct _memstream ms;
+	struct _region r;
+
+	_DIAGASSERT(cm && dir && mt);
+
+	if (lenmt<sizeof(*mt))
+		return EINVAL;
+
+	mz = malloc(sizeof(*mz), M_KICONV, M_WAITOK);
+	mz->mz_col.z_begin = mz->mz_col.z_end = 0;
+	mz->mz_row.z_begin = mz->mz_row.z_end = 0;
+	mz->mz_col_bits = 0;
+	mz->mz_row_offset = 0;
+	mz->mz_col_offset = 0;
+
+	_region_init(&r, __UNCONST(var), lenvar);
+	_memstream_bind(&ms, &r);
+	if (parse_var(mz, &ms)) {
+		free(mz, M_KICONV);
+		return EINVAL;
+	}
+	cm->cm_closure = mz;
+	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
+	mt->mt_state_size = 0;			/* stateless */
+
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_zone_mapper_uninit(struct _citrus_mapper *cm)
+{
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_zone_mapper_convert(struct _citrus_mapper * __restrict cm,
+				   _citrus_index_t * __restrict dst,
+				   _citrus_index_t src, void * __restrict ps)
+{
+	u_int32_t row, col;
+	struct _citrus_mapper_zone *mz = cm->cm_closure;
+
+	if (mz->mz_col_bits == 32) {
+		col = src;
+		row = 0;
+		if (col < mz->mz_col.z_begin || col > mz->mz_col.z_end)
+			return _CITRUS_MAPPER_CONVERT_NONIDENTICAL;
+		if (mz->mz_col_offset>0)
+			col += (u_int32_t)mz->mz_col_offset;
+		else
+			col -= (u_int32_t)-mz->mz_col_offset;
+		*dst = col;
+	} else {
+		col = src & (((u_int32_t)1<<mz->mz_col_bits)-1);
+		row = src >> mz->mz_col_bits;
+		if (row < mz->mz_row.z_begin || row > mz->mz_row.z_end ||
+		    col < mz->mz_col.z_begin || col > mz->mz_col.z_end)
+			return _CITRUS_MAPPER_CONVERT_NONIDENTICAL;
+		if (mz->mz_col_offset>0)
+			col += (u_int32_t)mz->mz_col_offset;
+		else
+			col -= (u_int32_t)-mz->mz_col_offset;
+		if (mz->mz_row_offset>0)
+			row += (u_int32_t)mz->mz_row_offset;
+		else
+			row -= (u_int32_t)-mz->mz_row_offset;
+		*dst = col | (row << mz->mz_col_bits);
+	}
+	return _CITRUS_MAPPER_CONVERT_SUCCESS;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_zone_mapper_init_state(struct _citrus_mapper * __restrict cm,
+				      void * __restrict ps)
+{
+}
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(mapper_zone_mapper);
+
+MODULE(MODULE_CLASS_MISC, kiconv_mapper_zone, "kiconv");
+
+static int
+kiconv_mapper_zone_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_mapper_zone_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_mapper_zone_mapper_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mapper_zone.h src/sys/kiconv/modules/citrus_mapper_zone.h
--- src.orig/sys/kiconv/modules/citrus_mapper_zone.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mapper_zone.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,36 @@
+/*	$NetBSD: citrus_mapper_zone.h,v 1.1 2003/06/25 09:51:48 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_ZONE_H_
+#define _CITRUS_MAPPER_ZONE_H_
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_zone);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mskanji.c src/sys/kiconv/modules/citrus_mskanji.c
--- src.orig/sys/kiconv/modules/citrus_mskanji.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mskanji.c	2011-06-03 21:21:49.000000000 +0900
@@ -0,0 +1,588 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_mskanji.c,v 1.13 2008/06/14 16:01:08 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ *    ja_JP.SJIS locale table for BSD4.4/rune
+ *    version 1.0
+ *    (C) Sin'ichiro MIYATANI / Phase One, Inc
+ *    May 12, 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Phase One, Inc.
+ * 4. The name of Phase One, Inc. may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE  
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  
+ * SUCH DAMAGE.  
+ */  
+
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_mskanji.c,v 1.13 2008/06/14 16:01:08 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <sys/types.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_mskanji.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct _MSKanjiState {
+	char ch[2];
+	int chlen;
+} _MSKanjiState;
+
+typedef struct {
+	int mode;
+#define MODE_JIS2004	1
+} _MSKanjiEncodingInfo;
+
+typedef struct {
+	_MSKanjiEncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_MSKanjiState	s_mblen;
+		_MSKanjiState	s_mbrlen;
+		_MSKanjiState	s_mbrtowc;
+		_MSKanjiState	s_mbtowc;
+		_MSKanjiState	s_mbsrtowcs;
+		_MSKanjiState	s_wcrtomb;
+		_MSKanjiState	s_wcsrtombs;
+		_MSKanjiState	s_wctomb;
+	} states;
+} _MSKanjiCTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_MSKanji_##m
+#define _ENCODING_INFO			_MSKanjiEncodingInfo
+#define _CTYPE_INFO			_MSKanjiCTypeInfo
+#define _ENCODING_STATE			_MSKanjiState
+#define _ENCODING_MB_CUR_MAX(_ei_)	2
+#define _ENCODING_IS_STATE_DEPENDENT	0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+
+static int
+_mskanji1(int c)
+{
+
+	if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xfc))
+		return 1;
+	else
+		return 0;
+}
+
+static int
+_mskanji2(int c)
+{
+
+	if ((c >= 0x40 && c <= 0x7e) || (c >= 0x80 && c <= 0xfc))
+		return 1;
+	else
+		return 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_MSKanji_init_state(_MSKanjiEncodingInfo * __restrict ei,
+			   _MSKanjiState * __restrict s)
+{
+	s->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_MSKanji_pack_state(_MSKanjiEncodingInfo * __restrict ei,
+			   void * __restrict pspriv,
+			   const _MSKanjiState * __restrict s)
+{
+	memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_MSKanji_unpack_state(_MSKanjiEncodingInfo * __restrict ei,
+			     _MSKanjiState * __restrict s,
+			     const void * __restrict pspriv)
+{
+	memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_MSKanji_mbrtowc_priv(_MSKanjiEncodingInfo * __restrict ei,
+			     wchar_t * __restrict pwc,
+			     const char ** __restrict s, size_t n,
+			     _MSKanjiState * __restrict psenc,
+			     size_t * __restrict nresult)
+{
+	wchar_t wchar;
+	int len;
+	int chlenbak;
+	const char *s0;
+
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	s0 = *s;
+
+	if (s0 == NULL) {
+		_citrus_MSKanji_init_state(ei, psenc);
+		*nresult = 0; /* state independent */
+		return (0);
+	}
+
+	chlenbak = psenc->chlen;
+
+	/* make sure we have the first byte in the buffer */
+	switch (psenc->chlen) {
+	case 0:
+		if (n < 1)
+			goto restart;
+		psenc->ch[0] = *s0++;
+		psenc->chlen = 1;
+		n--;
+		break;
+	case 1:
+		break;
+	default:
+		/* illegal state */
+		goto encoding_error;
+	}
+
+	len = _mskanji1(psenc->ch[0] & 0xff) ? 2 : 1;
+	while (psenc->chlen < len) {
+		if (n < 1)
+			goto restart;
+		psenc->ch[psenc->chlen] = *s0++;
+		psenc->chlen++;
+		n--;
+	}
+
+	*s = s0;
+
+	switch (len) {
+	case 1:
+		wchar = psenc->ch[0] & 0xff;
+		break;
+	case 2:
+		if (!_mskanji2(psenc->ch[1] & 0xff))
+			goto encoding_error;
+		wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
+		break;
+	default:
+		/* illegal state */
+		goto encoding_error;
+	}
+
+	psenc->chlen = 0;
+
+	if (pwc)
+		*pwc = wchar;
+
+	if (!wchar)
+		*nresult = 0;
+	else
+		*nresult = len - chlenbak;
+
+	return (0);
+
+encoding_error:
+	psenc->chlen = 0;
+	*nresult = (size_t)-1;
+	return (EILSEQ);
+
+restart:
+	*nresult = (size_t)-2;
+	*s = s0;
+	return (0);
+}
+
+
+static int
+_citrus_MSKanji_wcrtomb_priv(_MSKanjiEncodingInfo * __restrict ei,
+			     char * __restrict s, size_t n, wchar_t wc,
+			     _MSKanjiState * __restrict psenc,
+			     size_t * __restrict nresult)
+{
+	int ret;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(s != NULL);
+
+	/* check invalid sequence */
+	if (wc & ~0xffff) {
+		ret = EILSEQ;
+		goto err;
+	}
+
+	if (wc & 0xff00) {
+		if (n < 2) {
+			ret = E2BIG;
+			goto err;
+		}
+
+		s[0] = (wc >> 8) & 0xff;
+		s[1] = wc & 0xff;
+		if (!_mskanji1(s[0] & 0xff) || !_mskanji2(s[1] & 0xff)) {
+			ret = EILSEQ;
+			goto err;
+		}
+
+		*nresult = 2;
+		return 0;
+	} else {
+		if (n < 1) {
+			ret = E2BIG;
+			goto err;
+		}
+
+		s[0] = wc & 0xff;
+		if (_mskanji1(s[0] & 0xff)) {
+			ret = EILSEQ;
+			goto err;
+		}
+
+		*nresult = 1;
+		return 0;
+	}
+
+err:
+	*nresult = (size_t)-1;
+	return ret;
+}
+
+
+static __inline int
+/*ARGSUSED*/
+_citrus_MSKanji_stdenc_wctocs(_MSKanjiEncodingInfo * __restrict ei,
+			      _csid_t * __restrict csid,
+			      _index_t * __restrict idx, wchar_t wc)
+{
+	_index_t row, col;
+	int offset;
+
+	_DIAGASSERT(csid != NULL && idx != NULL);
+
+	if ((_wc_t)wc < 0x80) {
+		/* ISO-646 */
+		*csid = 0;
+		*idx = (_index_t)wc;
+	} else if ((_wc_t)wc < 0x100) {
+		/* KANA */
+		*csid = 1;
+		*idx = (_index_t)wc & 0x7F;
+	} else {
+		/* Kanji (containing Gaiji zone) */
+		/*
+		 * 94^2 zone (contains a part of Gaiji (0xED40 - 0xEEFC)):
+		 * 0x8140 - 0x817E -> 0x2121 - 0x215F
+		 * 0x8180 - 0x819E -> 0x2160 - 0x217E
+		 * 0x819F - 0x81FC -> 0x2221 - 0x227E
+		 *
+		 * 0x8240 - 0x827E -> 0x2321 - 0x235F
+		 *  ...
+		 * 0x9F9F - 0x9FFc -> 0x5E21 - 0x5E7E
+		 *
+		 * 0xE040 - 0xE07E -> 0x5F21 - 0x5F5F
+		 *  ...
+		 * 0xEF9F - 0xEFFC -> 0x7E21 - 0x7E7E
+		 *
+		 * extended Gaiji zone:
+		 * 0xF040 - 0xFCFC
+		 *
+		 * JIS X0213-plane2:
+		 * 0xF040 - 0xF09E -> 0x2121 - 0x217E
+		 * 0xF140 - 0xF19E -> 0x2321 - 0x237E
+		 * ...
+		 * 0xF240 - 0xF29E -> 0x2521 - 0x257E
+		 *
+		 * 0xF09F - 0xF0FC -> 0x2821 - 0x287E
+		 * 0xF29F - 0xF2FC -> 0x2C21 - 0x2C7E
+		 * ...
+		 * 0xF44F - 0xF49E -> 0x2F21 - 0x2F7E
+		 *
+		 * 0xF49F - 0xF4FC -> 0x6E21 - 0x6E7E
+		 * ...
+		 * 0xFC9F - 0xFCFC -> 0x7E21 - 0x7E7E
+		 */
+		row = ((_wc_t)wc >> 8) & 0xFF;
+		col = (_wc_t)wc & 0xFF;
+		if (!_mskanji1(row) || !_mskanji2(col))
+			return EILSEQ;
+		if ((ei->mode & MODE_JIS2004) == 0 || row < 0xF0) {
+			*csid = 2;
+			offset = 0x81;
+		} else {
+			*csid = 3;
+			if ((_wc_t)wc <= 0xF49E) {
+				offset = (_wc_t)wc >= 0xF29F ||
+				  ((_wc_t)wc >= 0xF09F && (_wc_t)wc <= 0xF0FC)
+				    ? 0xED : 0xF0;
+			} else
+				offset = 0xCE;
+		}
+		row -= offset;
+		if (row >= 0x5F)
+			row -= 0x40;
+		row = row * 2 + 0x21;
+		col -= 0x1F;
+		if (col >= 0x61)
+			col -= 1;
+		if (col > 0x7E) {
+			row += 1;
+			col -= 0x5E;
+		}
+		*idx = ((_index_t)row << 8) | col;
+	}
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_MSKanji_stdenc_cstowc(_MSKanjiEncodingInfo * __restrict ei,
+			      wchar_t * __restrict wc,
+			      _csid_t csid, _index_t idx)
+{
+	u_int32_t row, col;
+	int offset;
+
+	_DIAGASSERT(wc != NULL);
+
+	switch (csid) {
+	case 0:
+		/* ISO-646 */
+		if (idx >= 0x80)
+			return EILSEQ;
+		*wc = (wchar_t)idx;
+		break;
+	case 1:
+		/* kana */
+		if (idx >= 0x80)
+			return EILSEQ;
+		*wc = (wchar_t)idx + 0x80;
+		break;
+	case 3:
+		if ((ei->mode & MODE_JIS2004) == 0)
+			return EILSEQ;
+	/*FALLTHROUGH*/
+	case 2:
+		/* kanji */
+		row = (idx >> 8);
+		if (row < 0x21)
+			return EILSEQ;
+		if (csid == 3) {
+			if (row <= 0x2F)
+				offset = (row == 0x22 || row >= 0x26)
+				    ? 0xED : 0xF0;
+			else if (row >= 0x4D && row <= 0x7E)
+				offset = 0xCE;
+			else
+				return EILSEQ;
+		} else {
+			if (row > 0x97)
+				return EILSEQ;
+			offset = (row < 0x5F) ? 0x81 : 0xC1;
+		}
+		col = idx & 0xFF;
+		if (col < 0x21 || col > 0x7E)
+			return EILSEQ;
+		row -= 0x21; col -= 0x21;
+		if ((row & 1) == 0) {
+			col += 0x40;
+			if (col >= 0x7F)
+				col += 1;
+		} else
+			col += 0x9F;
+		row = row / 2 + offset;
+		*wc = ((wchar_t)row << 8) | col;
+		break;
+	default:
+		return EILSEQ;
+	}
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_MSKanji_stdenc_get_state_desc_generic(_MSKanjiEncodingInfo * __restrict ei,
+					      _MSKanjiState * __restrict psenc,
+					      int * __restrict rstate)
+{
+
+	if (psenc->chlen == 0)
+		*rstate = _STDENC_SDGEN_INITIAL;
+	else
+		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_MSKanji_encoding_module_init(_MSKanjiEncodingInfo *  __restrict ei,
+				     const void * __restrict var,
+				     size_t lenvar)
+{
+	const char *p;
+
+	_DIAGASSERT(ei != NULL);
+
+	p = var;
+#define MATCH(x, act)						\
+do {								\
+	if (lenvar >= (sizeof(#x)-1) &&				\
+	    _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) {	\
+		act;						\
+		lenvar -= sizeof(#x)-1;				\
+		p += sizeof(#x)-1;				\
+	}							\
+} while (/*CONSTCOND*/0)
+	memset((void *)ei, 0, sizeof(*ei));
+	while (lenvar > 0) {
+		switch (_bcs_toupper(*p)) {
+		case 'J':
+			MATCH(JIS2004, ei->mode |= MODE_JIS2004);
+			break;
+		}
+		++p;
+		--lenvar;
+	}
+
+	return 0;
+}
+
+static void
+_citrus_MSKanji_encoding_module_uninit(_MSKanjiEncodingInfo *ei)
+{
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(MSKanji);
+_CITRUS_CTYPE_DEF_OPS(MSKanji);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(MSKanji);
+_CITRUS_STDENC_DEF_OPS(MSKanji);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(MSKanji_ctype);
+KICONV_GETOPS(MSKanji_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_MSKanji, "kiconv");
+
+static int
+kiconv_MSKanji_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_MSKanji_ctype_getops);
+		kiconv_attach_getops(&kiconv_MSKanji_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_MSKanji_stdenc_getops);
+		kiconv_detach_getops(&kiconv_MSKanji_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_mskanji.h src/sys/kiconv/modules/citrus_mskanji.h
--- src.orig/sys/kiconv/modules/citrus_mskanji.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_mskanji.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/*	$NetBSD: citrus_mskanji.h,v 1.2 2003/06/25 09:51:48 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MSKANJI_H_
+#define _CITRUS_MSKANJI_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(MSKanji);
+_CITRUS_STDENC_GETOPS_FUNC(MSKanji);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_ues.c src/sys/kiconv/modules/citrus_ues.c
--- src.orig/sys/kiconv/modules/citrus_ues.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_ues.c	2011-06-03 21:21:51.000000000 +0900
@@ -0,0 +1,516 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_ues.c,v 1.2 2010/12/07 22:01:22 joerg Exp */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_ues.c,v 1.2 2010/12/07 22:01:22 joerg Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <wchar.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_ues.h"
+
+typedef struct {
+	int mode;
+#define MODE_C99	1
+	size_t mb_cur_max;
+} _UESEncodingInfo;
+
+typedef struct {
+	int chlen;
+	char ch[12];
+} _UESState;
+
+typedef struct {
+	_UESEncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_UESState	s_mblen;
+		_UESState	s_mbrlen;
+		_UESState	s_mbrtowc;
+		_UESState	s_mbtowc;
+		_UESState	s_mbsrtowcs;
+		_UESState	s_wcrtomb;
+		_UESState	s_wcsrtombs;
+		_UESState	s_wctomb;
+	} states;
+} _UESCTypeInfo;
+
+#define _CEI_TO_EI(_cei_)               (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)    (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_UES_##m
+#define _ENCODING_INFO			_UESEncodingInfo
+#define _CTYPE_INFO			_UESCTypeInfo
+#define _ENCODING_STATE			_UESState
+#define _ENCODING_MB_CUR_MAX(_ei_)	(_ei_)->mb_cur_max
+#define _ENCODING_IS_STATE_DEPENDENT		0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UES_init_state(_UESEncodingInfo * __restrict ei,
+	_UESState * __restrict psenc)
+{
+	psenc->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UES_pack_state(_UESEncodingInfo * __restrict ei,
+	void *__restrict pspriv, const _UESState * __restrict psenc)
+{
+	/* ei seem to be unused */
+	_DIAGASSERT(pspriv != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UES_unpack_state(_UESEncodingInfo * __restrict ei,
+	_UESState * __restrict psenc, const void * __restrict pspriv)
+{
+	/* ei seem to be unused */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(pspriv != NULL);
+
+	memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static __inline int
+to_int(int ch)
+{
+	if (ch >= '0' && ch <= '9')
+		return ch - '0';
+	else if (ch >= 'A' && ch <= 'F')
+		return (ch - 'A') + 10;
+	else if (ch >= 'a' && ch <= 'f')
+		return (ch - 'a') + 10;
+	return -1;
+}
+
+#define ESCAPE		'\\'
+#define UCS2_ESC	'u'
+#define UCS4_ESC	'U'
+
+#define UCS2_BIT	16
+#define UCS4_BIT	32
+#define BMP_MAX		UINT32_C(0xFFFF)
+#define UCS2_MAX	UINT32_C(0x10FFFF)
+#define UCS4_MAX	UINT32_C(0x7FFFFFFF)
+
+static const char *xdig = "0123456789abcdef";
+
+static __inline int
+to_str(char *s, wchar_t wc, int bit)
+{
+	char *p;
+
+	p = s;
+	*p++ = ESCAPE;
+	switch (bit) {
+	case UCS2_BIT:
+		*p++ = UCS2_ESC;
+		break;
+	case UCS4_BIT:
+		*p++ = UCS4_ESC;
+		break;
+	default:
+		panic("kiconv_UES: unknown bit (%d)", bit);
+	}
+	do {
+		*p++ = xdig[(wc >> (bit -= 4)) & 0xF];
+	} while (bit > 0);
+	return p - s;
+}
+
+static __inline int
+is_hi_surrogate(wchar_t wc)
+{
+	return wc >= 0xD800 && wc <= 0xDBFF;
+}
+
+static __inline int
+is_lo_surrogate(wchar_t wc)
+{
+	return wc >= 0xDC00 && wc <= 0xDFFF;
+}
+
+static __inline wchar_t
+surrogate_to_ucs(wchar_t hi, wchar_t lo)
+{
+	_DIAGASSERT(is_hi_surrogate(hi));
+	_DIAGASSERT(is_lo_surrogate(lo));
+
+	hi -= 0xD800;
+	lo -= 0xDC00;
+	return (hi << 10 | lo) + 0x10000;
+}
+
+static __inline void
+ucs_to_surrogate(wchar_t wc, wchar_t * __restrict hi, wchar_t * __restrict lo)
+{
+	_DIAGASSERT(hi != NULL);
+	_DIAGASSERT(lo != NULL);
+	_DIAGASSERT(wc >= 0x10000);
+
+	wc -= 0x10000;
+	*hi = (wc >> 10) + 0xD800;
+	*lo = (wc & 0x3FF) + 0xDC00;
+}
+
+static __inline int
+is_basic(wchar_t wc)
+{
+	return (uint32_t)wc <= 0x9F &&
+	    wc != 0x24 && wc != 0x40 && wc != 0x60;
+}
+
+static int
+_citrus_UES_mbrtowc_priv(_UESEncodingInfo * __restrict ei,
+	wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
+	_UESState * __restrict psenc, size_t * __restrict nresult)
+{
+	const char *s0;
+	int ch, head, tail, num;
+	wchar_t hi, wc;
+
+	_DIAGASSERT(ei != NULL);
+	/* pwc may be null */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (*s == NULL) {
+		_citrus_UES_init_state(ei, psenc);
+		*nresult = 0;
+		return 0;
+	}
+	s0 = *s;
+
+	hi = (wchar_t)0;
+	tail = 0;
+
+surrogate:
+	wc = (wchar_t)0;
+	head = tail;
+	if (psenc->chlen == head) {
+		if (n-- < 1)
+			goto restart;
+		psenc->ch[psenc->chlen++] = *s0++;
+	}
+	ch = (unsigned char)psenc->ch[head++];
+	if (ch == ESCAPE) {
+		if (psenc->chlen == head) {
+			if (n-- < 1)
+				goto restart;
+			psenc->ch[psenc->chlen++] = *s0++;
+		}
+		switch (psenc->ch[head]) {
+		case UCS2_ESC:
+			tail += 6;
+			break;
+		case UCS4_ESC:
+			if (ei->mode & MODE_C99) {
+				tail = 10;
+				break;
+			}
+		/*FALLTHROUGH*/
+		default:
+			tail = 0;
+		}
+		++head;
+	}
+	for (; head < tail; ++head) {
+		if (psenc->chlen == head) {
+			if (n-- < 1) {
+restart:
+				*s = s0;
+				*nresult = (size_t)-2;
+				return 0;
+			}
+			psenc->ch[psenc->chlen++] = *s0++;
+		}
+		num = to_int((int)(unsigned char)psenc->ch[head]);
+		if (num < 0) {
+			tail = 0;
+			break;
+		}
+		wc = (wc << 4) | num;
+	}
+	head = 0;
+	switch (tail) {
+	case 0:
+		break;
+	case 6:
+		if (hi != (wchar_t)0)
+			break;
+		if ((ei->mode & MODE_C99) == 0) {
+			if (is_hi_surrogate(wc) != 0) {
+				hi = wc;
+				goto surrogate;
+			}
+			if ((uint32_t)wc <= 0x7F /* XXX */ ||
+			    is_lo_surrogate(wc) != 0)
+				break;
+			goto done;
+		}
+	/*FALLTHROUGH*/
+	case 10:
+		if (is_basic(wc) == 0 && (uint32_t)wc <= UCS4_MAX &&
+		    is_hi_surrogate(wc) == 0 && is_lo_surrogate(wc) == 0)
+			goto done;
+		*nresult = (size_t)-1;
+		return EILSEQ;
+	case 12:
+		if (is_lo_surrogate(wc) == 0)
+			break;
+		wc = surrogate_to_ucs(hi, wc);
+		goto done;
+	}
+	ch = (unsigned char)psenc->ch[0];
+	head = psenc->chlen;
+	if (--head > 0)
+		memmove(&psenc->ch[0], &psenc->ch[1], head);
+	wc = (wchar_t)ch;
+done:
+	psenc->chlen = head;
+	if (pwc != NULL)
+		*pwc = wc;
+	*nresult = (size_t)((wc == 0) ? 0 : (s0 - *s));
+	*s = s0;
+
+	return 0;
+}
+
+static int
+_citrus_UES_wcrtomb_priv(_UESEncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, wchar_t wc,
+	_UESState * __restrict psenc, size_t * __restrict nresult)
+{
+	wchar_t hi, lo;
+
+	if (psenc->chlen != 0)
+		return EINVAL;
+
+	if ((ei->mode & MODE_C99) ? is_basic(wc) : (uint32_t)wc <= 0x7F) {
+		if (n-- < 1)
+			goto e2big;
+		psenc->ch[psenc->chlen++] = (char)wc;
+	} else if ((uint32_t)wc <= BMP_MAX) {
+		if (n < 6)
+			goto e2big;
+		psenc->chlen = to_str(&psenc->ch[0], wc, UCS2_BIT);
+	} else if ((ei->mode & MODE_C99) == 0 && (uint32_t)wc <= UCS2_MAX) {
+		if (n < 12)
+			goto e2big;
+		ucs_to_surrogate(wc, &hi, &lo);
+		psenc->chlen += to_str(&psenc->ch[0], hi, UCS2_BIT);
+		psenc->chlen += to_str(&psenc->ch[6], lo, UCS2_BIT);
+	} else if ((ei->mode & MODE_C99) && (uint32_t)wc <= UCS4_MAX) {
+		if (n < 10)
+			goto e2big;
+		psenc->chlen = to_str(&psenc->ch[0], wc, UCS4_BIT);
+	} else {
+		*nresult = (size_t)-1;
+		return EILSEQ;
+	}
+	memcpy(s, psenc->ch, psenc->chlen);
+	*nresult = psenc->chlen;
+	psenc->chlen = 0;
+
+	return 0;
+
+e2big:
+	*nresult = (size_t)-1;
+	return E2BIG;
+}
+
+/*ARGSUSED*/
+static int
+_citrus_UES_stdenc_wctocs(_UESEncodingInfo * __restrict ei,
+	_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+	/* ei seem to be unused */
+	_DIAGASSERT(csid != NULL);
+	_DIAGASSERT(idx != NULL);
+
+	*csid = 0;
+	*idx = (_index_t)wc;
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UES_stdenc_cstowc(_UESEncodingInfo * __restrict ei,
+	wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+	/* ei seem to be unused */
+	_DIAGASSERT(wc != NULL);
+
+	if (csid != 0)
+		return EILSEQ;
+	*wc = (wchar_t)idx;
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UES_stdenc_get_state_desc_generic(_UESEncodingInfo * __restrict ei,
+	_UESState * __restrict psenc, int * __restrict rstate)
+{
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(rstate != NULL);
+
+	if (psenc->chlen == 0)
+		*rstate = _STDENC_SDGEN_INITIAL;
+	else
+		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR; /* XXX */
+ 
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_UES_encoding_module_uninit(_UESEncodingInfo *ei)
+{
+	/* ei seems to be unused */
+}
+
+static int
+/*ARGSUSED*/
+_citrus_UES_encoding_module_init(_UESEncodingInfo * __restrict ei,
+	const void * __restrict var, size_t lenvar)
+{
+	const char *p;
+
+	_DIAGASSERT(ei != NULL);
+
+	p = var;
+#define MATCH(x, act)						\
+do {								\
+        if (lenvar >= (sizeof(#x)-1) &&				\
+            _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) {	\
+                act;						\
+                lenvar -= sizeof(#x)-1;				\
+                p += sizeof(#x)-1;				\
+        }							\
+} while (/*CONSTCOND*/0)
+	memset((void *)ei, 0, sizeof(*ei));
+	while (lenvar > 0) {
+		switch (_bcs_toupper(*p)) {
+		case 'C':
+			MATCH(C99, ei->mode |= MODE_C99);
+			break;
+		}
+		++p;
+		--lenvar;
+	}
+	ei->mb_cur_max = (ei->mode & MODE_C99) ? 10 : 12;
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(UES);
+_CITRUS_CTYPE_DEF_OPS(UES);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(UES);
+_CITRUS_STDENC_DEF_OPS(UES);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(UES_ctype);
+KICONV_GETOPS(UES_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_UES, "kiconv");
+
+static int
+kiconv_UES_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_UES_ctype_getops);
+		kiconv_attach_getops(&kiconv_UES_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_UES_stdenc_getops);
+		kiconv_detach_getops(&kiconv_UES_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_ues.h src/sys/kiconv/modules/citrus_ues.h
--- src.orig/sys/kiconv/modules/citrus_ues.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_ues.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/* $NetBSD: citrus_ues.h,v 1.1 2006/11/13 15:16:31 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_UES_H_
+#define _CITRUS_UES_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(UES);
+_CITRUS_STDENC_GETOPS_FUNC(UES);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_utf1632.c src/sys/kiconv/modules/citrus_utf1632.c
--- src.orig/sys/kiconv/modules/citrus_utf1632.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_utf1632.c	2011-06-03 21:21:53.000000000 +0900
@@ -0,0 +1,526 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_utf1632.c,v 1.11 2010/03/20 18:15:32 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_utf1632.c,v 1.11 2010/03/20 18:15:32 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <limits.h>
+#include <wchar.h>
+#include <sys/types.h>
+#include <machine/endian.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_bcs.h"
+
+#include "citrus_utf1632.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+	u_int8_t		ch[4];
+	int			chlen;
+	int			current_endian;
+} _UTF1632State;
+
+typedef struct {
+	int		preffered_endian;
+	unsigned int	cur_max;
+#define _ENDIAN_UNKNOWN	0
+#define _ENDIAN_BIG	1
+#define _ENDIAN_LITTLE	2
+	u_int32_t	mode;
+#define _MODE_UTF32		0x00000001U
+#define _MODE_FORCE_ENDIAN	0x00000002U
+} _UTF1632EncodingInfo;
+
+#define _FUNCNAME(m)			_citrus_UTF1632_##m
+#define _ENCODING_INFO			_UTF1632EncodingInfo
+#define _ENCODING_STATE			_UTF1632State
+#define _ENCODING_MB_CUR_MAX(_ei_)	((_ei_)->cur_max)
+#define _ENCODING_IS_STATE_DEPENDENT	0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF1632_init_state(_UTF1632EncodingInfo *ei, _UTF1632State *s)
+{
+	memset(s, 0, sizeof(*s));
+}
+
+static int
+_citrus_UTF1632_mbrtowc_priv(_UTF1632EncodingInfo *ei, wchar_t *pwc,
+			     const char **s, size_t n, _UTF1632State *psenc,
+			     size_t *nresult)
+{
+	int chlenbak, endian, needlen;
+	wchar_t wc = L'\0';
+	size_t result;
+	const char *s0;
+
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	s0 = *s;
+
+	if (s0 == NULL) {
+		_citrus_UTF1632_init_state(ei, psenc);
+		*nresult = 0; /* state independent */
+		return (0);
+	}
+
+	result = 0;
+	chlenbak = psenc->chlen;
+
+refetch:
+	if ((ei->mode & _MODE_UTF32) != 0 || chlenbak>=2)
+		needlen = 4;
+	else
+		needlen = 2;
+
+	while (chlenbak < needlen) {
+		if (n==0)
+			goto restart;
+		psenc->ch[chlenbak++] = *s0++;
+		n--;
+		result++;
+	}
+
+	if (psenc->current_endian == _ENDIAN_UNKNOWN) {
+		if ((ei->mode & _MODE_FORCE_ENDIAN) == 0) {
+			/* judge endian marker */
+			if ((ei->mode & _MODE_UTF32) == 0) {
+				/* UTF16 */
+				if (psenc->ch[0]==0xFE && psenc->ch[1]==0xFF) {
+					psenc->current_endian = _ENDIAN_BIG;
+					chlenbak = 0;
+					goto refetch;
+				} else if (psenc->ch[0]==0xFF && psenc->ch[1]==0xFE) {
+					psenc->current_endian = _ENDIAN_LITTLE;
+					chlenbak = 0;
+					goto refetch;
+				}
+			} else {
+				/* UTF32 */
+				if (psenc->ch[0]==0x00 && psenc->ch[1]==0x00 &&
+				    psenc->ch[2]==0xFE && psenc->ch[3]==0xFF) {
+					psenc->current_endian = _ENDIAN_BIG;
+					chlenbak = 0;
+					goto refetch;
+				} else if (psenc->ch[0]==0xFF && psenc->ch[1]==0xFE &&
+					   psenc->ch[2]==0x00 && psenc->ch[3]==0x00) {
+					psenc->current_endian = _ENDIAN_LITTLE;
+					chlenbak = 0;
+					goto refetch;
+				}
+			}
+		}
+		psenc->current_endian = ei->preffered_endian;
+	}
+	endian = psenc->current_endian;
+
+	/* get wc */
+	if ((ei->mode & _MODE_UTF32) == 0) {
+		/* UTF16 */
+		if (needlen==2) {
+			switch (endian) {
+			case _ENDIAN_LITTLE:
+				wc = (psenc->ch[0] |
+				      ((wchar_t)psenc->ch[1] << 8));
+				break;
+			case _ENDIAN_BIG:
+				wc = (psenc->ch[1] |
+				      ((wchar_t)psenc->ch[0] << 8));
+				break;
+			default:
+				goto ilseq;
+			}
+			if (wc >= 0xD800 && wc <= 0xDBFF) {
+				/* surrogate high */
+				needlen=4;
+				goto refetch;
+			}
+		} else {
+			/* surrogate low */
+			wc -= 0xD800; /* wc : surrogate high (see above) */
+			wc <<= 10;
+			switch (endian) {
+			case _ENDIAN_LITTLE:
+				if (psenc->ch[3]<0xDC || psenc->ch[3]>0xDF)
+					goto ilseq;
+				wc |= psenc->ch[2];
+				wc |= (wchar_t)(psenc->ch[3] & 3) << 8;
+				break;
+			case _ENDIAN_BIG:
+				if (psenc->ch[2]<0xDC || psenc->ch[2]>0xDF)
+					goto ilseq;
+				wc |= psenc->ch[3];
+				wc |= (wchar_t)(psenc->ch[2] & 3) << 8;
+				break;
+			default:
+				goto ilseq;
+			}
+			wc += 0x10000;
+		}
+	} else {
+		/* UTF32 */
+		switch (endian) {
+		case _ENDIAN_LITTLE:
+			wc = (psenc->ch[0] |
+			      ((wchar_t)psenc->ch[1] << 8) |
+			      ((wchar_t)psenc->ch[2] << 16) |
+			      ((wchar_t)psenc->ch[3] << 24));
+			break;
+		case _ENDIAN_BIG:
+			wc = (psenc->ch[3] |
+			      ((wchar_t)psenc->ch[2] << 8) |
+			      ((wchar_t)psenc->ch[1] << 16) |
+			      ((wchar_t)psenc->ch[0] << 24));
+			break;
+		default:
+			goto ilseq;
+		}
+		if (wc >= 0xD800 && wc <= 0xDFFF)
+			goto ilseq;
+	}
+
+
+	*pwc = wc;
+	psenc->chlen = 0;
+	*nresult = result;
+	*s = s0;
+
+	return (0);
+
+ilseq:
+	*nresult = (size_t)-1;
+	psenc->chlen = 0;
+	return (EILSEQ);
+
+restart:
+	*nresult = (size_t)-2;
+	psenc->chlen = chlenbak;
+	*s = s0;
+	return (0);
+}
+
+static int
+_citrus_UTF1632_wcrtomb_priv(_UTF1632EncodingInfo *ei, char *s, size_t n,
+			     wchar_t wc, _UTF1632State *psenc,
+			     size_t *nresult)
+{
+	wchar_t wc2;
+	static const char _bom[4] = {
+#if BYTE_ORDER == BIG_ENDIAN
+	    0x00, 0x00, 0xFE, 0xFF,
+#else
+	    0xFF, 0xFE, 0x00, 0x00,
+#endif
+	};
+	const char *bom = &_bom[0];
+	size_t cnt;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(s != NULL);
+
+	cnt = (size_t)0;
+	if (psenc->current_endian == _ENDIAN_UNKNOWN) {
+		if ((ei->mode & _MODE_FORCE_ENDIAN) == 0) {
+			if (ei->mode & _MODE_UTF32) {
+				cnt = 4;
+			} else {
+				cnt = 2;
+#if BYTE_ORDER == BIG_ENDIAN
+				bom += 2;
+#endif
+			}
+			if (n < cnt)
+				goto e2big;
+			memcpy(s, bom, cnt);
+			s += cnt, n -= cnt;
+		}
+		psenc->current_endian = ei->preffered_endian;
+	}
+
+	wc2 = 0;
+	if ((ei->mode & _MODE_UTF32)==0) {
+		/* UTF16 */
+		if (wc>0xFFFF) {
+			/* surrogate */
+			if (wc>0x10FFFF)
+				goto ilseq;
+			if (n < 4)
+				goto e2big;
+			cnt += 4;
+			wc -= 0x10000;
+			wc2 = (wc & 0x3FF) | 0xDC00;
+			wc = (wc>>10) | 0xD800;
+		} else {
+			if (n < 2)
+				goto e2big;
+			cnt += 2;
+		}
+
+surrogate:
+		switch (psenc->current_endian) {
+		case _ENDIAN_BIG:
+			s[1] = wc;
+			s[0] = (wc >>= 8);
+			break;
+		case _ENDIAN_LITTLE:
+			s[0] = wc;
+			s[1] = (wc >>= 8);
+			break;
+		}
+		if (wc2!=0) {
+			wc = wc2;
+			wc2 = 0;
+			s += 2;
+			goto surrogate;
+		}
+	} else {
+		/* UTF32 */
+		if (wc >= 0xD800 && wc <= 0xDFFF)
+			goto ilseq;
+		if (n < 4)
+			goto e2big;
+		cnt += 4;
+		switch (psenc->current_endian) {
+		case _ENDIAN_BIG:
+			s[3] = wc;
+			s[2] = (wc >>= 8);
+			s[1] = (wc >>= 8);
+			s[0] = (wc >>= 8);
+			break;
+		case _ENDIAN_LITTLE:
+			s[0] = wc;
+			s[1] = (wc >>= 8);
+			s[2] = (wc >>= 8);
+			s[3] = (wc >>= 8);
+			break;
+		}
+	}
+	*nresult = cnt;
+
+	return 0;
+
+ilseq:
+	*nresult = (size_t)-1;
+	return EILSEQ;
+e2big:
+	*nresult = (size_t)-1;
+	return E2BIG;
+}
+
+static void
+parse_variable(_UTF1632EncodingInfo * __restrict ei,
+	       const void * __restrict var, size_t lenvar)
+{
+#define MATCH(x, act)						\
+do {								\
+	if (lenvar >= (sizeof(#x)-1) &&				\
+	    _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) {	\
+		act;						\
+		lenvar -= sizeof(#x)-1;				\
+		p += sizeof(#x)-1;				\
+	}							\
+} while (/*CONSTCOND*/0)
+	const char *p;
+	p = var;
+	while (lenvar>0) {
+		switch (*p) {
+		case 'B':
+		case 'b':
+			MATCH(big, ei->preffered_endian = _ENDIAN_BIG);
+			break;
+		case 'L':
+		case 'l':
+			MATCH(little, ei->preffered_endian = _ENDIAN_LITTLE);
+			break;
+		case 'F':
+		case 'f':
+			MATCH(force, ei->mode |= _MODE_FORCE_ENDIAN);
+			break;
+		case 'U':
+		case 'u':
+			MATCH(utf32, ei->mode |= _MODE_UTF32);
+			break;
+		}
+		p++;
+		lenvar--;
+	}
+}
+
+static int
+/*ARGSUSED*/
+_citrus_UTF1632_encoding_module_init(_UTF1632EncodingInfo * __restrict ei,
+				     const void * __restrict var,
+				     size_t lenvar)
+{
+	_DIAGASSERT(ei != NULL);
+
+	memset((void *)ei, 0, sizeof(*ei));
+
+	parse_variable(ei, var, lenvar);
+
+	if ((ei->mode&_MODE_UTF32)==0)
+		ei->cur_max = 6; /* endian + surrogate */
+	else
+		ei->cur_max = 8; /* endian + normal */
+
+	if (ei->preffered_endian == _ENDIAN_UNKNOWN) {
+#if BYTE_ORDER == BIG_ENDIAN
+		ei->preffered_endian = _ENDIAN_BIG;
+#else
+		ei->preffered_endian = _ENDIAN_LITTLE;
+#endif
+	}
+
+	return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_UTF1632_encoding_module_uninit(_UTF1632EncodingInfo *ei)
+{
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF1632_stdenc_wctocs(_UTF1632EncodingInfo * __restrict ei,
+			      _csid_t * __restrict csid,
+			      _index_t * __restrict idx,
+			      _wc_t wc)
+{
+
+	_DIAGASSERT(csid != NULL && idx != NULL);
+
+	*csid = 0;
+	*idx = (_index_t)wc;
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF1632_stdenc_cstowc(_UTF1632EncodingInfo * __restrict ei,
+			      _wc_t * __restrict wc,
+			      _csid_t csid, _index_t idx)
+{
+
+	_DIAGASSERT(wc != NULL);
+
+	if (csid != 0)
+		return (EILSEQ);
+
+	*wc = (_wc_t)idx;
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF1632_stdenc_get_state_desc_generic(_UTF1632EncodingInfo * __restrict ei,
+					      _UTF1632State * __restrict psenc,
+					      int * __restrict rstate)
+{
+
+	if (psenc->chlen == 0)
+		*rstate = _STDENC_SDGEN_INITIAL;
+	else
+		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(UTF1632);
+_CITRUS_STDENC_DEF_OPS(UTF1632);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(UTF1632_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_UTF1632, "kiconv");
+
+static int
+kiconv_UTF1632_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_UTF1632_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_UTF1632_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_utf1632.h src/sys/kiconv/modules/citrus_utf1632.h
--- src.orig/sys/kiconv/modules/citrus_utf1632.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_utf1632.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,36 @@
+/*	$NetBSD: citrus_utf1632.h,v 1.1 2003/06/25 09:51:49 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_UTF1632_H_
+#define _CITRUS_UTF1632_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(UTF1632);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_utf7.c src/sys/kiconv/modules/citrus_utf7.c
--- src.orig/sys/kiconv/modules/citrus_utf7.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_utf7.c	2011-06-03 21:21:55.000000000 +0900
@@ -0,0 +1,615 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_utf7.c,v 1.5 2006/08/23 12:57:24 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)2004, 2005 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+ 
+#include <sys/cdefs.h>
+#if defined(LIB_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_utf7.c,v 1.5 2006/08/23 12:57:24 tnozaki Exp");
+#endif /* LIB_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <wchar.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_utf7.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+	uint16_t	cell[0x80];
+#define	EI_MASK		UINT16_C(0xff)
+#define EI_DIRECT	UINT16_C(0x100)
+#define EI_OPTION	UINT16_C(0x200)
+#define EI_SPACE	UINT16_C(0x400)
+} _UTF7EncodingInfo;
+
+typedef struct {
+	unsigned int
+		mode: 1,	/* whether base64 mode */
+		bits: 4,	/* need to hold 0 - 15 */
+		cache: 22,	/* 22 = BASE64_BIT + UTF16_BIT */
+		surrogate: 1;	/* whether surrogate pair or not */
+	int chlen;
+	char ch[4]; /* BASE64_IN, 3 * 6 = 18, most closed to UTF16_BIT */
+} _UTF7State;
+
+typedef struct {
+	_UTF7EncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_UTF7State	s_mblen;
+		_UTF7State	s_mbrlen;
+		_UTF7State	s_mbrtowc;
+		_UTF7State	s_mbtowc;
+		_UTF7State	s_mbsrtowcs;
+		_UTF7State	s_wcrtomb;
+		_UTF7State	s_wcsrtombs;
+		_UTF7State	s_wctomb;
+	} states;
+} _UTF7CTypeInfo;
+
+#define	_CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define	_CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define	_FUNCNAME(m)			_citrus_UTF7_##m
+#define	_ENCODING_INFO			_UTF7EncodingInfo
+#define	_CTYPE_INFO			_UTF7CTypeInfo
+#define	_ENCODING_STATE			_UTF7State
+#define	_ENCODING_MB_CUR_MAX(_ei_)		4
+#define	_ENCODING_IS_STATE_DEPENDENT		1
+#define	_STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF7_init_state(_UTF7EncodingInfo * __restrict ei,
+	_UTF7State * __restrict s)
+{
+	/* ei appears to be unused */
+	_DIAGASSERT(s != NULL);
+
+	memset((void *)s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF7_pack_state(_UTF7EncodingInfo * __restrict ei,
+	void *__restrict pspriv, const _UTF7State * __restrict s)
+{
+	/* ei seem to be unused */
+	_DIAGASSERT(pspriv != NULL);
+	_DIAGASSERT(s != NULL);
+
+	memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF7_unpack_state(_UTF7EncodingInfo * __restrict ei,
+	_UTF7State * __restrict s, const void * __restrict pspriv)
+{
+	/* ei seem to be unused */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(pspriv != NULL);
+
+	memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static const char base64[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	"abcdefghijklmnopqrstuvwxyz"
+	"0123456789+/";
+
+static const char direct[] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	"abcdefghijklmnopqrstuvwxyz"
+	"0123456789(),-./:?";
+
+static const char option[] = "!\"#$%&';<=>@[]^_`{|}";
+static const char spaces[] = " \t\r\n";
+
+#define	BASE64_BIT	6
+#define	UTF16_BIT	16
+
+#define	BASE64_MAX	0x3f
+#define	UTF16_MAX	UINT16_C(0xffff)
+#define	UTF32_MAX	UINT32_C(0x10ffff)
+
+#define	BASE64_IN	'+'
+#define	BASE64_OUT	'-'
+
+#define	SHIFT7BIT(c)	((c) >> 7)
+#define	ISSPECIAL(c)	((c) == '\0' || (c) == BASE64_IN)
+
+#define	FINDLEN(ei, c) \
+	(SHIFT7BIT((c)) ? -1 : (((ei)->cell[(c)] & EI_MASK) - 1))
+
+#define	ISDIRECT(ei, c)	(!SHIFT7BIT((c)) && (ISSPECIAL((c)) || \
+	ei->cell[(c)] & (EI_DIRECT | EI_OPTION | EI_SPACE)))
+
+#define	ISSAFE(ei, c)	(!SHIFT7BIT((c)) && (ISSPECIAL((c)) || \
+	(c < 0x80 && ei->cell[(c)] & (EI_DIRECT | EI_SPACE))))
+
+/* surrogate pair */
+#define	SRG_BASE	UINT32_C(0x10000)
+#define	HISRG_MIN	UINT16_C(0xd800)
+#define	HISRG_MAX	UINT16_C(0xdbff)
+#define	LOSRG_MIN	UINT16_C(0xdc00)
+#define	LOSRG_MAX	UINT16_C(0xdfff)
+
+static int
+_citrus_UTF7_mbtoutf16(_UTF7EncodingInfo * __restrict ei,
+	uint16_t * __restrict u16, const char ** __restrict s, size_t n,
+	_UTF7State * __restrict psenc, size_t * __restrict nresult)
+{
+	_UTF7State sv;
+	const char *s0;
+	int i, done, len;
+ 
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL && *s != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	s0 = *s;
+	sv = *psenc;
+
+	for (i = 0, done = 0; done == 0; i++) {
+		_DIAGASSERT(i <= psenc->chlen);
+		if (i == psenc->chlen) {
+			if (n-- < 1) {
+				*nresult = (size_t)-2;
+				*s = s0;
+				sv.chlen = psenc->chlen;
+				*psenc = sv;
+				return 0;
+			}
+			psenc->ch[psenc->chlen++] = *s0++;
+		}
+		if (SHIFT7BIT((int)psenc->ch[i]))
+			goto ilseq;
+		if (!psenc->mode) {
+			if (psenc->bits > 0 || psenc->cache > 0)
+				return EINVAL;
+			if (psenc->ch[i] == BASE64_IN) {
+				psenc->mode = 1;
+			} else {
+				if (!ISDIRECT(ei, (int)psenc->ch[i]))
+					goto ilseq;
+				*u16 = (uint16_t)psenc->ch[i];
+				done = 1;
+				continue;
+			}
+		} else {
+			if (psenc->ch[i] == BASE64_OUT && psenc->cache == 0) {
+				psenc->mode = 0;
+				*u16 = (uint16_t)BASE64_IN;
+				done = 1;
+				continue;
+			}
+			len = FINDLEN(ei, (int)psenc->ch[i]);
+			if (len < 0) {
+				if (psenc->bits >= BASE64_BIT)
+					return EINVAL;
+				psenc->mode = 0;
+				psenc->bits = psenc->cache = 0;
+				if (psenc->ch[i] != BASE64_OUT) {
+					if (!ISDIRECT(ei, (int)psenc->ch[i]))
+						goto ilseq;
+					*u16 = (uint16_t)psenc->ch[i];
+					done = 1;
+				}
+			} else {
+				psenc->cache =
+				    (psenc->cache << BASE64_BIT) | len;
+				switch (psenc->bits) {
+				case 0: case 2: case 4: case 6: case 8:
+					psenc->bits += BASE64_BIT;
+					break;
+				case 10: case 12: case 14:
+					psenc->bits -= (UTF16_BIT - BASE64_BIT);
+					*u16 = (psenc->cache >> psenc->bits)
+					    & UTF16_MAX;
+					done = 1;
+					break;
+				default:
+					return EINVAL;
+				}
+			}
+		}
+	}
+
+	if (psenc->chlen > i)
+		return EINVAL;
+	psenc->chlen = 0;
+	*nresult = (size_t)((*u16 == 0) ? 0 : s0 - *s);
+	*s = s0;
+
+	return 0;
+
+ilseq:
+	*nresult = (size_t)-1;
+	return EILSEQ;
+}
+
+static int
+_citrus_UTF7_mbrtowc_priv(_UTF7EncodingInfo * __restrict ei,
+	wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
+	_UTF7State * __restrict psenc, size_t * __restrict nresult)
+{
+	const char *s0;
+	uint32_t u32;
+	uint16_t hi, lo;
+	size_t siz, nr;
+	int err;
+
+	_DIAGASSERT(ei != NULL);
+	/* pwc may be null */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	if (*s == NULL) {
+		_citrus_UTF7_init_state(ei, psenc);
+		*nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
+		return 0;
+	}
+	s0 = *s;
+	if (psenc->surrogate) {
+		hi = (psenc->cache >> 2) & UTF16_MAX;
+		if (hi < HISRG_MIN || hi > HISRG_MAX)
+			return EINVAL;
+		siz = 0;
+	} else {
+		err = _citrus_UTF7_mbtoutf16(ei, &hi, &s0, n, psenc, &nr);
+		if (nr == (size_t)-1 || nr == (size_t)-2) {
+			*nresult = nr;
+			return err;
+		}
+		if (err != 0)
+			return err;
+		n -= nr;
+		siz = nr;
+		if (hi < HISRG_MIN || hi > HISRG_MAX) {
+			u32 = (uint32_t)hi;
+			goto done;
+		}
+		psenc->surrogate = 1;
+	}
+	err = _citrus_UTF7_mbtoutf16(ei, &lo, &s0, n, psenc, &nr);
+	if (nr == (size_t)-1 || nr == (size_t)-2) {
+		*nresult = nr;
+		return err;
+	}
+	if (err != 0)
+		return err;
+	hi -= HISRG_MIN;
+	lo -= LOSRG_MIN;
+	u32 = (hi << 10 | lo) + SRG_BASE;
+	siz += nr;
+done:
+	*s = s0;
+	if (pwc != NULL)
+		*pwc = (wchar_t)u32;
+	if (u32 == (uint32_t)0) {
+		*nresult = (size_t)0;
+		_citrus_UTF7_init_state(ei, psenc);
+	} else {
+		*nresult = siz;
+		psenc->surrogate = 0;
+	}
+	return err;
+}
+
+static int
+_citrus_UTF7_utf16tomb(_UTF7EncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, uint16_t u16,
+	_UTF7State * __restrict psenc, size_t * __restrict nresult)
+{
+	int bits, i;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	if (psenc->chlen != 0 || psenc->bits > BASE64_BIT)
+		return EINVAL;
+
+	if (ISSAFE(ei, u16)) {
+		if (psenc->mode) {
+			if (psenc->bits > 0) {
+				bits = BASE64_BIT - psenc->bits;
+				i = (psenc->cache << bits) & BASE64_MAX;
+				psenc->ch[psenc->chlen++] = base64[i];
+				psenc->bits = psenc->cache = 0;
+			}
+			if (u16 == BASE64_OUT || FINDLEN(ei, u16) >= 0)
+				psenc->ch[psenc->chlen++] = BASE64_OUT;
+			psenc->mode = 0;
+		}
+		if (psenc->bits != 0)
+			return EINVAL;
+		psenc->ch[psenc->chlen++] = (char)u16;
+		if (u16 == BASE64_IN)
+			psenc->ch[psenc->chlen++] = BASE64_OUT;
+	} else {
+		if (!psenc->mode) {
+			if (psenc->bits > 0)
+				return EINVAL;
+			psenc->ch[psenc->chlen++] = BASE64_IN;
+			psenc->mode = 1;
+		}
+		psenc->cache = (psenc->cache << UTF16_BIT) | u16;
+		bits = UTF16_BIT + psenc->bits;
+		psenc->bits = bits % BASE64_BIT;
+		while ((bits -= BASE64_BIT) >= 0) {
+			i = (psenc->cache >> bits) & BASE64_MAX;
+			psenc->ch[psenc->chlen++] = base64[i];
+		}
+	}
+	memcpy(s, psenc->ch, psenc->chlen);
+	*nresult = psenc->chlen;
+	psenc->chlen = 0;
+
+	return 0;
+}
+
+static int
+_citrus_UTF7_wcrtomb_priv(_UTF7EncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, wchar_t wchar,
+	_UTF7State * __restrict psenc, size_t * __restrict nresult)
+{
+	uint32_t u32;
+	uint16_t u16[2];
+	int err, len, i;
+	size_t siz, nr;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	u32 = (uint32_t)wchar;
+	if (u32 <= UTF16_MAX) {
+		u16[0] = (uint16_t)u32;
+		len = 1;
+	} else if (u32 <= UTF32_MAX) {
+		u32 -= SRG_BASE;
+		u16[0] = (u32 >> 10) + HISRG_MIN;
+		u16[1] = ((uint16_t)(u32 & UINT32_C(0x3ff))) + LOSRG_MIN;
+		len = 2;
+	} else {
+		*nresult = (size_t)-1;
+		return EILSEQ;
+	}
+	siz = 0;
+	for (i = 0; i < len; ++i) {
+		err = _citrus_UTF7_utf16tomb(ei, s, n, u16[i], psenc, &nr);
+		if (err != 0)
+			return err; /* XXX: state has been modified */
+		s += nr;
+		n -= nr;
+		siz += nr;
+	}
+	*nresult = siz;
+
+	return 0;
+}
+
+static int
+/* ARGSUSED */
+_citrus_UTF7_put_state_reset(_UTF7EncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, _UTF7State * __restrict psenc,
+	size_t * __restrict nresult)
+{
+	int bits, pos;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (psenc->chlen != 0 || psenc->bits > BASE64_BIT || psenc->surrogate)
+		return EINVAL;
+
+	if (psenc->mode) {
+		if (psenc->bits > 0) {
+			if (n-- < 1)
+				return E2BIG;
+			bits = BASE64_BIT - psenc->bits;
+			pos = (psenc->cache << bits) & BASE64_MAX;
+			psenc->ch[psenc->chlen++] = base64[pos];
+			psenc->ch[psenc->chlen++] = BASE64_OUT;
+			psenc->bits = psenc->cache = 0;
+		}
+		psenc->mode = 0;
+	}
+	if (psenc->bits != 0)
+		return EINVAL;
+	if (n-- < 1)
+		return E2BIG;
+
+	_DIAGASSERT(n >= psenc->chlen);
+	*nresult = (size_t)psenc->chlen;
+	if (psenc->chlen > 0) {
+		memcpy(s, psenc->ch, psenc->chlen);
+		psenc->chlen = 0;
+	}
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF7_stdenc_wctocs(_UTF7EncodingInfo * __restrict ei,
+			   _csid_t * __restrict csid,
+			   _index_t * __restrict idx, wchar_t wc)
+{
+	/* ei seem to be unused */
+	_DIAGASSERT(csid != NULL);
+	_DIAGASSERT(idx != NULL);
+
+	*csid = 0;
+	*idx = (_index_t)wc;
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF7_stdenc_cstowc(_UTF7EncodingInfo * __restrict ei,
+			   wchar_t * __restrict wc,
+			   _csid_t csid, _index_t idx)
+{
+	/* ei seem to be unused */
+	_DIAGASSERT(wc != NULL);
+
+	if (csid != 0)
+		return EILSEQ;
+	*wc = (wchar_t)idx;
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF7_stdenc_get_state_desc_generic(_UTF7EncodingInfo * __restrict ei,
+					   _UTF7State * __restrict psenc,
+					   int * __restrict rstate)
+{
+
+	if (psenc->chlen == 0)
+		*rstate = _STDENC_SDGEN_INITIAL;
+	else
+		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_UTF7_encoding_module_uninit(_UTF7EncodingInfo *ei)
+{
+	/* ei seems to be unused */
+}
+
+static int
+/*ARGSUSED*/
+_citrus_UTF7_encoding_module_init(_UTF7EncodingInfo * __restrict ei,
+				  const void * __restrict var, size_t lenvar)
+{
+	const char *s;
+
+	_DIAGASSERT(ei != NULL);
+	/* var may be null */
+
+	memset(ei, 0, sizeof(*ei));
+
+#define FILL(str, flag)				\
+do {						\
+	for (s = str; *s != '\0'; s++)		\
+		ei->cell[*s & 0x7f] |= flag;	\
+} while (/*CONSTCOND*/0)
+
+	FILL(base64, (s - base64) + 1);
+	FILL(direct, EI_DIRECT);
+	FILL(option, EI_OPTION);
+	FILL(spaces, EI_SPACE);
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(UTF7);
+_CITRUS_CTYPE_DEF_OPS(UTF7);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(UTF7);
+_CITRUS_STDENC_DEF_OPS(UTF7);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(UTF7_ctype);
+KICONV_GETOPS(UTF7_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_UTF7, "kiconv");
+
+static int
+kiconv_UTF7_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_UTF7_ctype_getops);
+		kiconv_attach_getops(&kiconv_UTF7_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_UTF7_stdenc_getops);
+		kiconv_detach_getops(&kiconv_UTF7_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_utf7.h src/sys/kiconv/modules/citrus_utf7.h
--- src.orig/sys/kiconv/modules/citrus_utf7.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_utf7.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/*	$NetBSD: citrus_utf7.h,v 1.1 2005/03/05 18:05:15 tnozaki Exp $	*/
+
+/*-
+ * Copyright (c)2004,2005 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_UTF7_H_
+#define _CITRUS_UTF7_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(UTF7);
+_CITRUS_STDENC_GETOPS_FUNC(UTF7);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_utf8.c src/sys/kiconv/modules/citrus_utf8.c
--- src.orig/sys/kiconv/modules/citrus_utf8.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_utf8.c	2011-06-04 16:56:40.000000000 +0900
@@ -0,0 +1,439 @@
+/*	$NetBSD$	*/
+/*	NetBSD: citrus_utf8.c,v 1.17 2008/06/14 16:01:08 tnozaki Exp	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_utf8.c,v 1.17 2008/06/14 16:01:08 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <sys/types.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_utf8.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+static int _UTF8_count_array[256];
+static int const *_UTF8_count = NULL;
+
+static const u_int32_t _UTF8_range[] = {
+	0,	/*dummy*/
+	0x00000000, 0x00000080, 0x00000800, 0x00010000, 
+	0x00200000, 0x04000000, 0x80000000,
+};
+
+typedef struct {
+	char ch[6];
+	int chlen;
+} _UTF8State;
+
+typedef struct {
+} _UTF8EncodingInfo;
+
+typedef struct {
+	_UTF8EncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_UTF8State	s_mblen;
+		_UTF8State	s_mbrlen;
+		_UTF8State	s_mbrtowc;
+		_UTF8State	s_mbtowc;
+		_UTF8State	s_mbsrtowcs;
+		_UTF8State	s_wcrtomb;
+		_UTF8State	s_wcsrtombs;
+		_UTF8State	s_wctomb;
+	} states;
+} _UTF8CTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_ei_, _func_)	(_ei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_UTF8_##m
+#define _ENCODING_INFO			_UTF8EncodingInfo
+#define _CTYPE_INFO			_UTF8CTypeInfo
+#define _ENCODING_STATE			_UTF8State
+#define _ENCODING_MB_CUR_MAX(_ei_)	6
+#define _ENCODING_IS_STATE_DEPENDENT	0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+
+static __inline void
+_UTF8_init_count(void)
+{
+	int i;
+	if (!_UTF8_count) {
+		memset(_UTF8_count_array, 0, sizeof(_UTF8_count_array));
+		for (i = 0; i <= 0x7f; i++)
+			_UTF8_count_array[i] = 1;
+		for (i = 0xc0; i <= 0xdf; i++)
+			_UTF8_count_array[i] = 2;
+		for (i = 0xe0; i <= 0xef; i++)
+			_UTF8_count_array[i] = 3;
+		for (i = 0xf0; i <= 0xf7; i++)
+			_UTF8_count_array[i] = 4;
+		for (i = 0xf8; i <= 0xfb; i++)
+			_UTF8_count_array[i] = 5;
+		for (i = 0xfc; i <= 0xfd; i++)
+			_UTF8_count_array[i] = 6;
+		_UTF8_count = _UTF8_count_array;
+	}
+}
+
+static int
+_UTF8_findlen(wchar_t v)
+{
+	int i;
+	u_int32_t c;
+
+	c = (u_int32_t)v;	/*XXX*/
+	for (i = 1; i < sizeof(_UTF8_range) / sizeof(_UTF8_range[0]) - 1; i++)
+		if (c >= _UTF8_range[i] && c < _UTF8_range[i + 1])
+			return i;
+
+	return -1;	/*out of range*/
+}
+
+static __inline int
+_UTF8_surrogate(wchar_t wc)
+{
+	return wc >= 0xd800 && wc <= 0xdfff;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF8_init_state(_UTF8EncodingInfo *ei, _UTF8State *s)
+{
+	s->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF8_pack_state(_UTF8EncodingInfo *ei, void *pspriv,
+			const _UTF8State *s)
+{
+	memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF8_unpack_state(_UTF8EncodingInfo *ei, _UTF8State *s,
+			  const void *pspriv)
+{
+	memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+_citrus_UTF8_mbrtowc_priv(_UTF8EncodingInfo *ei, wchar_t *pwc, const char **s,
+			  size_t n, _UTF8State *psenc, size_t *nresult)
+{
+	wchar_t wchar;
+	const char *s0;
+	int c;
+	int i;
+
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	s0 = *s;
+
+	if (s0 == NULL) {
+		_citrus_UTF8_init_state(ei, psenc);
+		*nresult = 0; /* state independent */
+		return 0;
+	}
+
+	/* make sure we have the first byte in the buffer */
+	if (psenc->chlen == 0) {
+		if (n-- < 1)
+			goto restart;
+		psenc->ch[psenc->chlen++] = *s0++;
+	}
+
+	c = _UTF8_count[psenc->ch[0] & 0xff];
+	if (c < 1 || c < psenc->chlen)
+		goto ilseq;
+
+	if (c == 1)
+		wchar = psenc->ch[0] & 0xff;
+	else {
+		while (psenc->chlen < c) {
+			if (n-- < 1)
+				goto restart;
+			psenc->ch[psenc->chlen++] = *s0++;
+		}
+		wchar = psenc->ch[0] & (0x7f >> c);
+		for (i = 1; i < c; i++) {
+			if ((psenc->ch[i] & 0xc0) != 0x80)
+				goto ilseq;
+			wchar <<= 6;
+			wchar |= (psenc->ch[i] & 0x3f);
+		}
+		if (_UTF8_surrogate(wchar) || _UTF8_findlen(wchar) != c)
+			goto ilseq;
+	}
+	if (pwc != NULL)
+		*pwc = wchar;
+	*nresult = (wchar == 0) ? 0 : s0 - *s;
+	*s = s0;
+	psenc->chlen = 0;
+
+	return 0;
+
+ilseq:
+	*nresult = (size_t)-1;
+	return EILSEQ;
+
+restart:
+	*s = s0;
+	*nresult = (size_t)-2;
+	return 0;
+}
+
+static int
+_citrus_UTF8_wcrtomb_priv(_UTF8EncodingInfo *ei, char *s, size_t n, wchar_t wc,
+			  _UTF8State *psenc, size_t *nresult)
+{
+	int cnt, i, ret;
+	wchar_t c;
+
+	_DIAGASSERT(nresult != 0);
+	_DIAGASSERT(s != NULL);
+
+	if (_UTF8_surrogate(wc)) {
+		ret = EILSEQ;
+		goto err;
+	}
+	cnt = _UTF8_findlen(wc);
+	if (cnt <= 0 || cnt > 6) {
+		/* invalid UCS4 value */
+		ret = EILSEQ;
+		goto err;
+	}
+	if (n < cnt) {
+		/* bound check failure */
+		ret = E2BIG;
+		goto err;
+	}
+
+	c = wc;
+	if (s) {
+		for (i = cnt - 1; i > 0; i--) {
+			s[i] = 0x80 | (c & 0x3f);
+			c >>= 6;
+		}
+		s[0] = c;
+		if (cnt == 1)
+			s[0] &= 0x7f;
+		else {
+			s[0] &= (0x7f >> cnt);
+			s[0] |= ((0xff00 >> cnt) & 0xff);
+		}
+	}
+
+	*nresult = (size_t)cnt;
+	return 0;
+
+err:
+	*nresult = (size_t)-1;
+	return ret;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF8_stdenc_wctocs(_UTF8EncodingInfo * __restrict ei,
+			   _csid_t * __restrict csid,
+			   _index_t * __restrict idx,
+			   wchar_t wc)
+{
+
+	_DIAGASSERT(csid != NULL && idx != NULL);
+
+	*csid = 0;
+	*idx = (_citrus_index_t)wc;
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF8_stdenc_cstowc(_UTF8EncodingInfo * __restrict ei,
+			   wchar_t * __restrict wc,
+			   _csid_t csid, _index_t idx)
+{
+
+	_DIAGASSERT(wc != NULL);
+
+	if (csid != 0)
+		return (EILSEQ);
+
+	*wc = (wchar_t)idx;
+
+	return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF8_stdenc_get_state_desc_generic(_UTF8EncodingInfo * __restrict ei,
+					   _UTF8State * __restrict psenc,
+					   int * __restrict rstate)
+{
+
+	if (psenc->chlen == 0)
+		*rstate = _STDENC_SDGEN_INITIAL;
+	else
+		*rstate = _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_UTF8_encoding_module_init(_UTF8EncodingInfo * __restrict ei,
+				  const void * __restrict var, size_t lenvar)
+{
+	_UTF8_init_count();
+
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_UTF8_encoding_module_uninit(_UTF8EncodingInfo *ei)
+{
+}
+
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(UTF8);
+_CITRUS_CTYPE_DEF_OPS(UTF8);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(UTF8);
+_CITRUS_STDENC_DEF_OPS(UTF8);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(UTF8_ctype);
+KICONV_GETOPS(UTF8_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_UTF8, "kiconv");
+
+static int
+kiconv_UTF8_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_UTF8_ctype_getops);
+		kiconv_attach_getops(&kiconv_UTF8_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_UTF8_stdenc_getops);
+		kiconv_detach_getops(&kiconv_UTF8_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_utf8.h src/sys/kiconv/modules/citrus_utf8.h
--- src.orig/sys/kiconv/modules/citrus_utf8.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_utf8.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/*	$NetBSD: citrus_utf8.h,v 1.2 2003/06/25 09:51:49 tshiozak Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_UTF8_H_
+#define _CITRUS_UTF8_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(UTF8);
+_CITRUS_STDENC_GETOPS_FUNC(UTF8);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_viqr.c src/sys/kiconv/modules/citrus_viqr.c
--- src.orig/sys/kiconv/modules/citrus_viqr.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_viqr.c	2011-06-03 21:22:00.000000000 +0900
@@ -0,0 +1,620 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_viqr.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_viqr.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp");
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_viqr.h"
+
+#define ESCAPE	'\\'
+
+/*
+ * this table generated from RFC 1456.
+ */
+static const char *mnemonic_rfc1456[0x100] = {
+  NULL , NULL , "A(?", NULL , NULL , "A(~", "A^~", NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , "Y?" , NULL , NULL , NULL ,
+  NULL , "Y~" , NULL , NULL , NULL , NULL , "Y." , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+  "A." , "A('", "A(`", "A(.", "A^'", "A^`", "A^?", "A^.",
+  "E~" , "E." , "E^'", "E^`", "E^?", "E^~", "E^.", "O^'",
+  "O^`", "O^?", "O^~", "O^.", "O+.", "O+'", "O+`", "O+?",
+  "I." , "O?" , "O." , "I?" , "U?" , "U~" , "U." , "Y`" ,
+  "O~" , "a('", "a(`", "a(.", "a^'", "a^`", "a^?", "a^.",
+  "e~" , "e." , "e^'", "e^`", "e^?", "e^~", "e^.", "o^'",
+  "o^`", "o^?", "o^~", "O+~", "O+" , "o^.", "o+`", "o+?",
+  "i." , "U+.", "U+'", "U+`", "U+?", "o+" , "o+'", "U+" ,
+  "A`" , "A'" , "A^" , "A~" , "A?" , "A(" , "a(?", "a(~",
+  "E`" , "E'" , "E^" , "E?" , "I`" , "I'" , "I~" , "y`" ,
+  "DD" , "u+'", "O`" , "O'" , "O^" , "a." , "y?" , "u+`",
+  "u+?", "U`" , "U'" , "y~" , "y." , "Y'" , "o+~", "u+" ,
+  "a`" , "a'" , "a^" , "a~" , "a?" , "a(" , "u+~", "a^~",
+  "e`" , "e'" , "e^" , "e?" , "i`" , "i'" , "i~" , "i?" ,
+  "dd" , "u+.", "o`" , "o'" , "o^" , "o~" , "o?" , "o." ,
+  "u." , "u`" , "u'" , "u~" , "u?" , "y'" , "o+.", "U+~",
+};
+
+typedef struct {
+	const char *name;
+	wchar_t value;
+} mnemonic_def_t;
+
+#if _KERNEL
+#define	EMPTY_MNEMONIC_EXT	/* XXX: gcc */
+#endif
+static const mnemonic_def_t mnemonic_ext[] = {
+/* add extra mnemonic here (should be sorted by wchar_t order). */
+};
+static const size_t mnemonic_ext_size =
+	sizeof(mnemonic_ext) / sizeof(mnemonic_def_t);
+
+static const char *
+mnemonic_ext_find(wchar_t wc, const mnemonic_def_t *head, size_t n)
+{
+	const mnemonic_def_t *mid;
+
+	_DIAGASSERT(head != NULL);
+
+	for (; n > 0; n >>= 1) {
+		mid = head + (n >> 1);
+		if (mid->value == wc) {
+			return mid->name;
+		} else if (mid->value < wc) {
+			head = mid + 1;
+			--n;
+		}
+	}
+	return NULL;
+}
+
+struct mnemonic_t;
+typedef TAILQ_HEAD(mnemonic_list_t, mnemonic_t) mnemonic_list_t;
+typedef struct mnemonic_t {
+	TAILQ_ENTRY(mnemonic_t) entry;
+	int ascii;
+	struct mnemonic_t *parent;
+	mnemonic_list_t child;
+	wchar_t value;
+} mnemonic_t;
+
+static mnemonic_t *
+mnemonic_list_find(mnemonic_list_t *ml, int ch)
+{
+	mnemonic_t *m;
+
+	_DIAGASSERT(ml != NULL);
+
+	TAILQ_FOREACH(m, ml, entry) {
+		if (m->ascii == ch)
+			return m;
+	}
+
+	return NULL;
+}
+
+static mnemonic_t *
+mnemonic_create(mnemonic_t *parent, int ascii, wchar_t value)
+{
+	mnemonic_t *m;
+
+	_DIAGASSERT(parent != NULL);
+
+	m = malloc(sizeof(*m), M_KICONV, M_WAITOK);
+	m->parent = parent;
+	m->ascii = ascii;
+	m->value = value;
+	TAILQ_INIT(&m->child);
+
+	return m;
+}
+
+static int
+mnemonic_append_child(mnemonic_t *m, const char *s,
+	wchar_t value, wchar_t invalid)
+{
+	int ch;
+	mnemonic_t *m0;
+
+	_DIAGASSERT(m != NULL);
+	_DIAGASSERT(s != NULL);
+
+	ch = (unsigned char)*s++;
+	if (ch == '\0')
+		return EINVAL;
+	m0 = mnemonic_list_find(&m->child, ch);
+	if (m0 == NULL) {
+		m0 = mnemonic_create(m, ch, (wchar_t)ch);
+		if (m0 == NULL)
+			return ENOMEM;
+		TAILQ_INSERT_TAIL(&m->child, m0, entry);
+	}
+	m = m0;
+	for (m0 = NULL; (ch = (unsigned char)*s) != '\0'; ++s) {
+		m0 = mnemonic_list_find(&m->child, ch);
+		if (m0 == NULL) {
+			m0 = mnemonic_create(m, ch, invalid);
+			if (m0 == NULL)
+				return ENOMEM;
+			TAILQ_INSERT_TAIL(&m->child, m0, entry);
+		}
+		m = m0;
+	}
+	if (m0 == NULL)
+		return EINVAL;
+	m0->value = value;
+
+	return 0;
+}
+
+static void
+mnemonic_destroy(mnemonic_t *m)
+{
+	mnemonic_t *m0;
+
+	_DIAGASSERT(m != NULL);
+
+	TAILQ_FOREACH(m0, &m->child, entry)
+		mnemonic_destroy(m0);
+	free(m, M_KICONV);
+}
+
+typedef struct {
+	size_t mb_cur_max;
+	wchar_t invalid;
+	mnemonic_t *mroot;
+} _VIQREncodingInfo;
+
+typedef struct {
+	int chlen;
+	char ch[MB_LEN_MAX];
+} _VIQRState;
+
+typedef struct {
+	_VIQREncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_VIQRState	s_mblen;
+		_VIQRState	s_mbrlen;
+		_VIQRState	s_mbrtowc;
+		_VIQRState	s_mbtowc;
+		_VIQRState	s_mbsrtowcs;
+		_VIQRState	s_wcrtomb;
+		_VIQRState	s_wcsrtombs;
+		_VIQRState	s_wctomb;
+	} states;
+} _VIQRCTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_VIQR_##m
+#define _ENCODING_INFO			_VIQREncodingInfo
+#define _CTYPE_INFO			_VIQRCTypeInfo
+#define _ENCODING_STATE			_VIQRState
+#define _ENCODING_MB_CUR_MAX(_ei_)	(_ei_)->mb_cur_max
+#define _ENCODING_IS_STATE_DEPENDENT		1
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_VIQR_init_state(_VIQREncodingInfo * __restrict ei,
+	_VIQRState * __restrict psenc)
+{
+	/* ei may be unused */
+	_DIAGASSERT(psenc != NULL);
+
+	psenc->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_VIQR_pack_state(_VIQREncodingInfo * __restrict ei,
+	void *__restrict pspriv, const _VIQRState * __restrict psenc)
+{
+	/* ei may be unused */
+	_DIAGASSERT(pspriv != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_VIQR_unpack_state(_VIQREncodingInfo * __restrict ei,
+	_VIQRState * __restrict psenc, const void * __restrict pspriv)
+{
+	/* ei may be unused */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(pspriv != NULL);
+
+	memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static int
+_citrus_VIQR_mbrtowc_priv(_VIQREncodingInfo * __restrict ei,
+	wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
+	_VIQRState * __restrict psenc, size_t * __restrict nresult)
+{
+	const char *s0;
+	wchar_t wc;
+	mnemonic_t *m, *m0;
+	size_t i;
+	int ch, escape;
+
+	_DIAGASSERT(ei != NULL);
+	/* pwc may be null */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (*s == NULL) {
+		_citrus_VIQR_init_state(ei, psenc);
+		*nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
+		return 0;
+	}
+	s0 = *s;
+
+	i = 0;
+	m = ei->mroot;
+	for (escape = 0;;) {
+		if (psenc->chlen == i) {
+			if (n-- < 1) {
+				*s = s0;
+				*nresult = (size_t)-2;
+				return 0;
+			}
+			psenc->ch[psenc->chlen++] = *s0++;
+		}
+		ch = (unsigned char)psenc->ch[i++];
+		if (ch == ESCAPE) {
+			if (m != ei->mroot)
+				break;
+			escape = 1;
+			continue;
+		}
+		if (escape != 0)
+			break;
+		m0 = mnemonic_list_find(&m->child, ch);
+		if (m0 == NULL)
+			break;
+		m = m0;
+	}
+	while (m != ei->mroot) {
+		--i;
+		if (m->value != ei->invalid)
+			break;
+		m = m->parent;
+	}
+	if (ch == ESCAPE && m != ei->mroot)
+		++i;
+	psenc->chlen -= i;
+	memmove(&psenc->ch[0], &psenc->ch[i], psenc->chlen);
+	wc = (m == ei->mroot) ? (wchar_t)ch : m->value;
+	if (pwc != NULL)
+		*pwc = wc;
+	*nresult = (size_t)(wc == 0 ? 0 : s0 - *s);
+	*s = s0;
+
+	return 0;
+}
+
+static int
+_citrus_VIQR_wcrtomb_priv(_VIQREncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, wchar_t wc,
+	_VIQRState * __restrict psenc, size_t * __restrict nresult)
+{
+	mnemonic_t *m;
+	int ch;
+	const char *p;
+
+	_DIAGASSERT(ei != NULL);
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	ch = 0; /* XXX: gcc */
+
+	switch (psenc->chlen) {
+	case 0: case 1:
+		break;
+	default:
+		return EINVAL;
+	}
+	m = NULL;
+	if ((uint32_t)wc <= 0xFF) {
+		p = mnemonic_rfc1456[wc & 0xFF];
+		if (p != NULL)
+			goto mnemonic_found;
+		if (n-- < 1)
+			goto e2big;
+		ch = (unsigned int)wc;
+		m = ei->mroot;
+		if (psenc->chlen > 0) {
+			m = mnemonic_list_find(&m->child, psenc->ch[0]);
+			if (m == NULL)
+				return EINVAL;
+			psenc->ch[0] = ESCAPE;
+		}
+		if (mnemonic_list_find(&m->child, ch) == NULL) {
+			psenc->chlen = 0;
+			m = NULL;
+		}
+		psenc->ch[psenc->chlen++] = ch;
+	} else {
+		p = mnemonic_ext_find(wc, &mnemonic_ext[0], mnemonic_ext_size);
+		if (p == NULL) {
+			*nresult = (size_t)-1;
+			return EILSEQ;
+		} else {
+mnemonic_found:
+			psenc->chlen = 0;
+			while (*p != '\0') {
+				if (n-- < 1)
+					goto e2big;
+				psenc->ch[psenc->chlen++] = *p++;
+			}
+		}
+	}
+	memcpy(s, psenc->ch, psenc->chlen);
+	*nresult = psenc->chlen;
+	if (m == ei->mroot) {
+		psenc->ch[0] = ch;
+		psenc->chlen = 1;
+	} else {
+		psenc->chlen = 0;
+	}
+
+	return 0;
+
+e2big:
+	*nresult = (size_t)-1;
+	return E2BIG;
+}
+
+static int
+/* ARGSUSED */
+_citrus_VIQR_put_state_reset(_VIQREncodingInfo * __restrict ei,
+	char * __restrict s, size_t n, _VIQRState * __restrict psenc,
+	size_t * __restrict nresult)
+{
+	/* ei may be unused */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	switch (psenc->chlen) {
+	case 0: case 1:
+		break;
+	default:
+		return EINVAL;
+	}
+	*nresult = 0;
+	psenc->chlen = 0;
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_VIQR_stdenc_wctocs(_VIQREncodingInfo * __restrict ei,
+	_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+	/* ei may be unused */
+	_DIAGASSERT(csid != NULL);
+	_DIAGASSERT(idx != NULL);
+
+	*csid = 0;
+	*idx = (_index_t)wc;
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_VIQR_stdenc_cstowc(_VIQREncodingInfo * __restrict ei,
+	wchar_t * __restrict pwc, _csid_t csid, _index_t idx)
+{
+	/* ei may be unused */
+	_DIAGASSERT(pwc != NULL);
+
+	if (csid != 0)
+		return EILSEQ;
+	*pwc = (wchar_t)idx;
+
+	return 0;
+}
+
+static void
+_citrus_VIQR_encoding_module_uninit(_VIQREncodingInfo *ei)
+{
+	_DIAGASSERT(ei != NULL);
+
+	mnemonic_destroy(ei->mroot);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_VIQR_encoding_module_init(_VIQREncodingInfo * __restrict ei,
+	const void * __restrict var, size_t lenvar)
+{
+	int errnum;
+	const char *s;
+	size_t i, n;
+
+	_DIAGASSERT(ei != NULL);
+	/* var may be unused */
+
+	ei->mb_cur_max = 1;
+	ei->invalid = (wchar_t)-1;
+	ei->mroot = mnemonic_create(NULL, '\0', ei->invalid);
+	if (ei->mroot == NULL)
+		return ENOMEM;
+	for (i = 0; i < sizeof(mnemonic_rfc1456) / sizeof(const char *); ++i) {
+		s = mnemonic_rfc1456[i];
+		if (s == NULL)
+			continue;
+		n = strlen(s);
+		_DIAGASSERT(n <= MB_LEN_MAX);
+		if (ei->mb_cur_max < n)
+			ei->mb_cur_max = n;
+		errnum = mnemonic_append_child(ei->mroot,
+		    s, (wchar_t)i, ei->invalid);
+		if (errnum != 0) {
+			_citrus_VIQR_encoding_module_uninit(ei);
+			return errnum;
+		}
+	}
+#ifndef	EMPTY_MNEMONIC_EXT	/* XXX:gcc */
+	for (i = 0; i < mnemonic_ext_size; ++i) {
+		const mnemonic_def_t *p = &mnemonic_ext[i];
+		_DIAGASSERT(p != NULL && p->name != NULL);
+		n = strlen(p->name);
+		_DIAGASSERT(n <= MB_LEN_MAX);
+		if (ei->mb_cur_max < n)
+			ei->mb_cur_max = n;
+		errnum = mnemonic_append_child(ei->mroot,
+		    p->name, p->value, ei->invalid);
+		if (errnum != 0) {
+			_citrus_VIQR_encoding_module_uninit(ei);
+			return errnum;
+		}
+	}
+#endif
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_VIQR_stdenc_get_state_desc_generic(_VIQREncodingInfo * __restrict ei,
+	_VIQRState * __restrict psenc, int * __restrict rstate)
+{
+	/* ei may be unused */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(rstate != NULL);
+
+	*rstate = (psenc->chlen == 0)
+	    ? _STDENC_SDGEN_INITIAL
+	    : _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(VIQR);
+_CITRUS_CTYPE_DEF_OPS(VIQR);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(VIQR);
+_CITRUS_STDENC_DEF_OPS(VIQR);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(VIQR_ctype);
+KICONV_GETOPS(VIQR_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_VIQR, "kiconv");
+
+static int
+kiconv_VIQR_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_VIQR_ctype_getops);
+		kiconv_attach_getops(&kiconv_VIQR_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_VIQR_stdenc_getops);
+		kiconv_detach_getops(&kiconv_VIQR_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_viqr.h src/sys/kiconv/modules/citrus_viqr.h
--- src.orig/sys/kiconv/modules/citrus_viqr.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_viqr.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/* $NetBSD: citrus_viqr.h,v 1.1 2006/11/13 15:16:31 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_VIQR_H_
+#define _CITRUS_VIQR_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(VIQR);
+_CITRUS_STDENC_GETOPS_FUNC(VIQR);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_zw.c src/sys/kiconv/modules/citrus_zw.c
--- src.orig/sys/kiconv/modules/citrus_zw.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_zw.c	2011-06-03 21:22:03.000000000 +0900
@@ -0,0 +1,556 @@
+/* $NetBSD$ */
+/* NetBSD: citrus_zw.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp */
+
+/*-
+ * Copyright (c)2004, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+ 
+#include <sys/cdefs.h>
+#if defined(LIB_SCCS) && !defined(lint)
+__RCSID("NetBSD: citrus_zw.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp");
+#endif /* LIB_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/module.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <limits.h>
+#endif
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_zw.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+	int dummy;
+} _ZWEncodingInfo;
+
+typedef enum {
+	NONE, AMBIGIOUS, ASCII, GB2312
+} _ZWCharset;
+
+typedef struct {
+	int		chlen;
+	char		ch[4];
+	_ZWCharset	charset;
+} _ZWState;
+
+typedef struct {
+	_ZWEncodingInfo	ei;
+	struct {
+		/* for future multi-locale facility */
+		_ZWState	s_mblen;
+		_ZWState	s_mbrlen;
+		_ZWState	s_mbrtowc;
+		_ZWState	s_mbtowc;
+		_ZWState	s_mbsrtowcs;
+		_ZWState	s_wcrtomb;
+		_ZWState	s_wcsrtombs;
+		_ZWState	s_wctomb;
+	} states;
+} _ZWCTypeInfo;
+
+#define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m)			_citrus_ZW_##m
+#define _ENCODING_INFO			_ZWEncodingInfo
+#define _CTYPE_INFO			_ZWCTypeInfo
+#define _ENCODING_STATE			_ZWState
+#define _ENCODING_MB_CUR_MAX(_ei_)	MB_LEN_MAX
+#define _ENCODING_IS_STATE_DEPENDENT		1
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	((_ps_)->charset != NONE)
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ZW_init_state(_ZWEncodingInfo * __restrict ei,
+	_ZWState * __restrict psenc)
+{
+	/* ei my be unused */
+	_DIAGASSERT(psenc != NULL);
+
+	psenc->chlen = 0;
+	psenc->charset = NONE;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ZW_pack_state(_ZWEncodingInfo * __restrict ei,
+	void *__restrict pspriv, const _ZWState * __restrict psenc)
+{
+	/* ei may be unused */
+	_DIAGASSERT(pspriv != NULL);
+	_DIAGASSERT(psenc != NULL);
+
+	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ZW_unpack_state(_ZWEncodingInfo * __restrict ei,
+	_ZWState * __restrict psenc, const void * __restrict pspriv)
+{
+	/* ei may be unused */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(pspriv != NULL);
+
+	memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static int
+_citrus_ZW_mbrtowc_priv(_ZWEncodingInfo * __restrict ei,
+	wchar_t * __restrict pwc, const char **__restrict s, size_t n,
+	_ZWState * __restrict psenc, size_t * __restrict nresult)
+{
+	const char *s0;
+	int ch, len;
+	wchar_t	 wc;
+
+	/* ei may be unused */
+	/* pwc may be null */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (*s == NULL) {
+		_citrus_ZW_init_state(ei, psenc);
+		*nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
+		return 0;
+	}
+	s0 = *s;
+	len = 0;
+
+#define	STORE				\
+do {					\
+	if (n-- < 1) {			\
+		*nresult = (size_t)-2;	\
+		*s = s0;		\
+		return 0;		\
+	}				\
+	ch = (unsigned char)*s0++;	\
+	if (len++ > MB_LEN_MAX || ch > 0x7F)\
+		goto ilseq;		\
+	psenc->ch[psenc->chlen++] = ch;	\
+} while (/*CONSTCOND*/0)
+
+loop:
+	switch (psenc->charset) {
+	case ASCII:
+		switch (psenc->chlen) {
+		case 0:
+			STORE;
+			switch (psenc->ch[0]) {
+			case '\0': case '\n':
+				psenc->charset = NONE;
+			}
+		/*FALLTHROUGH*/
+		case 1:
+			break;
+		default:
+			return EINVAL;
+		}
+		ch = (unsigned char)psenc->ch[0];
+		if (ch > 0x7F)
+			goto ilseq;
+		wc = (wchar_t)ch;
+		psenc->chlen = 0;
+		break;
+	case NONE:
+		if (psenc->chlen != 0)
+			return EINVAL;
+		STORE;
+		ch = (unsigned char)psenc->ch[0];
+		if (ch != 'z') {
+			if (ch != '\n' && ch != '\0')
+				psenc->charset = ASCII;
+			wc = (wchar_t)ch;
+			psenc->chlen = 0;
+			break;
+		}
+		psenc->charset = AMBIGIOUS;
+		psenc->chlen = 0;
+	/* FALLTHROUGH */
+	case AMBIGIOUS:
+		if (psenc->chlen != 0)
+			return EINVAL;
+		STORE;
+		if (psenc->ch[0] != 'W') {
+			psenc->charset = ASCII;
+			wc = L'z';
+			break;
+		}
+		psenc->charset = GB2312;
+		psenc->chlen = 0;
+	/* FALLTHROUGH */
+	case GB2312:
+		switch (psenc->chlen) {
+		case 0:
+			STORE;
+			ch = (unsigned char)psenc->ch[0];
+			if (ch == '\0') {
+				psenc->charset = NONE;
+				wc = (wchar_t)ch;
+				psenc->chlen = 0;
+				break;
+			} else if (ch == '\n') {
+				psenc->charset = NONE;
+				psenc->chlen = 0;
+				goto loop;
+			}
+		/*FALLTHROUGH*/
+		case 1:
+			STORE;
+			if (psenc->ch[0] == ' ') {
+				ch = (unsigned char)psenc->ch[1];
+				wc = (wchar_t)ch;
+				psenc->chlen = 0;
+				break;
+			} else if (psenc->ch[0] == '#') {
+				ch = (unsigned char)psenc->ch[1];
+				if (ch == '\n') {
+					psenc->charset = NONE;
+					wc = (wchar_t)ch;
+					psenc->chlen = 0;
+					break;
+				} else if (ch == ' ') {
+					wc = (wchar_t)ch;
+					psenc->chlen = 0;
+					break;
+				}
+			}
+			ch = (unsigned char)psenc->ch[0];
+			if (ch < 0x21 || ch > 0x7E)
+				goto ilseq;
+			wc = (wchar_t)(ch << 8);
+			ch = (unsigned char)psenc->ch[1];
+			if (ch < 0x21 || ch > 0x7E) {
+ilseq:
+				*nresult = (size_t)-1;
+				return EILSEQ;
+			}
+			wc |= (wchar_t)ch;
+			psenc->chlen = 0;
+			break;
+		default:
+			return EINVAL;
+		}
+		break;
+	default:
+		return EINVAL;
+	}
+	if (pwc != NULL)
+		*pwc = wc;
+
+	*nresult = (size_t)(wc == 0 ? 0 : len);
+	*s = s0;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_ZW_wcrtomb_priv(_ZWEncodingInfo * __restrict ei,
+	char *__restrict s, size_t n, wchar_t wc,
+	_ZWState * __restrict psenc, size_t * __restrict nresult)
+{
+	int ch;
+
+	/* ei may be null */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (psenc->chlen != 0)
+		return EINVAL;
+	if ((uint32_t)wc <= 0x7F) {
+		ch = (unsigned char)wc;
+		switch (psenc->charset) {
+		case NONE:
+			if (ch == '\0' || ch == '\n') {
+				psenc->ch[psenc->chlen++] = ch;
+			} else {
+				if (n < 4)
+					return E2BIG;
+				n -= 4;
+				psenc->ch[psenc->chlen++] = 'z';
+				psenc->ch[psenc->chlen++] = 'W';
+				psenc->ch[psenc->chlen++] = ' ';
+				psenc->ch[psenc->chlen++] = ch;
+				psenc->charset = GB2312;
+			}
+			break;
+		case GB2312:
+			if (n < 2)
+				return E2BIG;
+			n -= 2;
+			if (ch == '\0') {
+				psenc->ch[psenc->chlen++] = '\n';
+				psenc->ch[psenc->chlen++] = '\0';
+				psenc->charset = NONE;
+			} else if (ch == '\n') {
+				psenc->ch[psenc->chlen++] = '#';
+				psenc->ch[psenc->chlen++] = '\n';
+				psenc->charset = NONE;
+			} else {
+				psenc->ch[psenc->chlen++] = ' ';
+				psenc->ch[psenc->chlen++] = ch;
+			}
+			break;
+		default:
+			return EINVAL;
+		}
+	} else if ((uint32_t)wc <= 0x7E7E) {
+		switch (psenc->charset) {
+		case NONE:
+			if (n < 2)
+				return E2BIG;
+			n -= 2;
+			psenc->ch[psenc->chlen++] = 'z';
+			psenc->ch[psenc->chlen++] = 'W';
+			psenc->charset = GB2312;
+		/* FALLTHROUGH*/
+		case GB2312:
+			if (n < 2)
+				return E2BIG;
+			n -= 2;
+			ch = (wc >> 8) & 0xFF;
+			if (ch < 0x21 || ch > 0x7E)
+				goto ilseq;
+			psenc->ch[psenc->chlen++] = ch;
+			ch = wc & 0xFF;
+			if (ch < 0x21 || ch > 0x7E)
+				goto ilseq;
+			psenc->ch[psenc->chlen++] = ch;
+			break;
+		default:
+			return EINVAL;
+		}
+	} else {
+ilseq:
+		*nresult = (size_t)-1;
+		return EILSEQ;
+	}
+	memcpy(s, psenc->ch, psenc->chlen);
+	*nresult = psenc->chlen;
+	psenc->chlen = 0;
+
+	return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_ZW_put_state_reset(_ZWEncodingInfo * __restrict ei,
+	char * __restrict s, size_t n,
+	_ZWState * __restrict psenc, size_t * __restrict nresult)
+{
+	/* ei may be unused */
+	_DIAGASSERT(s != NULL);
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(nresult != NULL);
+
+	if (psenc->chlen != 0)
+		return EINVAL;
+	switch (psenc->charset) {
+	case GB2312:
+		if (n-- < 1)
+			return E2BIG;
+		psenc->ch[psenc->chlen++] = '\n';
+		psenc->charset = NONE;
+	/*FALLTHROUGH*/
+	case NONE:
+		*nresult = psenc->chlen;
+		if (psenc->chlen > 0) {
+			memcpy(s, psenc->ch, psenc->chlen);
+			psenc->chlen = 0;
+		}
+		break;
+	default:
+		return EINVAL;
+	}
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ZW_stdenc_get_state_desc_generic(_ZWEncodingInfo * __restrict ei,
+	_ZWState * __restrict psenc, int * __restrict rstate)
+{
+	/* ei may be unused */
+	_DIAGASSERT(psenc != NULL);
+	_DIAGASSERT(rstate != NULL);
+
+	switch (psenc->charset) {
+	case NONE:
+		if (psenc->chlen != 0)
+			return EINVAL;
+		*rstate = _STDENC_SDGEN_INITIAL;
+		break;
+	case AMBIGIOUS:
+		if (psenc->chlen != 0)
+			return EINVAL;
+		*rstate = _STDENC_SDGEN_INCOMPLETE_SHIFT;
+		break;
+	case ASCII:
+	case GB2312:
+		switch (psenc->chlen) {
+		case 0:
+			*rstate = _STDENC_SDGEN_STABLE;
+			break;
+		case 1:
+			*rstate = (psenc->ch[0] == '#')
+			    ? _STDENC_SDGEN_INCOMPLETE_SHIFT
+			    : _STDENC_SDGEN_INCOMPLETE_CHAR;
+			break;
+		default:
+			return EINVAL;
+		}
+		break;
+	default:
+		return EINVAL;
+	}
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ZW_stdenc_wctocs(_ZWEncodingInfo * __restrict ei,
+	_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+	/* ei seems to be unused */
+	_DIAGASSERT(csid != NULL);
+	_DIAGASSERT(idx != NULL);
+
+	*csid = (_csid_t)(wc <= 0x7FU) ? 0 : 1;
+	*idx = (_index_t)wc;
+
+	return 0;
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ZW_stdenc_cstowc(_ZWEncodingInfo * __restrict ei,
+	 wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+	/* ei seems to be unused */
+	_DIAGASSERT(wc != NULL);
+
+	switch (csid) {
+	case 0: case 1:
+		break;
+	default:
+		return EINVAL;
+	}
+	*wc = (wchar_t)idx;
+
+	return 0;
+}
+
+static void
+/*ARGSUSED*/
+_citrus_ZW_encoding_module_uninit(_ZWEncodingInfo *ei)
+{
+}
+
+static int
+/*ARGSUSED*/
+_citrus_ZW_encoding_module_init(_ZWEncodingInfo * __restrict ei,
+	const void *__restrict var, size_t lenvar)
+{
+	return 0;
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for ctype
+ */
+
+_CITRUS_CTYPE_DECLS(ZW);
+_CITRUS_CTYPE_DEF_OPS(ZW);
+
+#include "citrus_ctype_template.h"
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(ZW);
+_CITRUS_STDENC_DEF_OPS(ZW);
+
+#include "citrus_stdenc_template.h"
+
+/*----------------------------------------------------------------------------
+ * kernel/module interface
+ */
+#if defined(_KERNEL)
+KICONV_GETOPS(ZW_ctype);
+KICONV_GETOPS(ZW_stdenc);
+
+MODULE(MODULE_CLASS_MISC, kiconv_ZW, "kiconv");
+
+static int
+kiconv_ZW_modcmd(modcmd_t cmd, void *arg)
+{
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+		kiconv_attach_getops(&kiconv_ZW_ctype_getops);
+		kiconv_attach_getops(&kiconv_ZW_stdenc_getops);
+		return 0;
+
+	case MODULE_CMD_FINI:
+		kiconv_detach_getops(&kiconv_ZW_stdenc_getops);
+		kiconv_detach_getops(&kiconv_ZW_ctype_getops);
+		return 0;
+
+	case MODULE_CMD_AUTOUNLOAD:
+		/* Couldn't unload automatically */
+		return EBUSY;
+
+	default:
+		return ENOTTY;
+	}
+}
+#endif	/* _KERNEL */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/modules/citrus_zw.h src/sys/kiconv/modules/citrus_zw.h
--- src.orig/sys/kiconv/modules/citrus_zw.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/modules/citrus_zw.h	2011-06-03 14:40:19.000000000 +0900
@@ -0,0 +1,37 @@
+/* $NetBSD: citrus_zw.h,v 1.1 2006/11/22 23:38:27 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004,2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ZW_H_
+#define _CITRUS_ZW_H_
+
+__BEGIN_DECLS
+_CITRUS_CTYPE_GETOPS_FUNC(ZW);
+_CITRUS_STDENC_GETOPS_FUNC(ZW);
+__END_DECLS
+
+#endif
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/multibyte.h src/sys/kiconv/multibyte.h
--- src.orig/sys/kiconv/multibyte.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/multibyte.h	2011-06-03 14:25:05.000000000 +0900
@@ -0,0 +1,126 @@
+/*	$NetBSD: multibyte.h,v 1.5 2009/01/11 02:46:28 christos Exp $	*/
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MULTIBYTE_H_
+#define _MULTIBYTE_H_
+
+/* mbstate_t private */
+
+#ifdef _BSD_MBSTATE_T_
+typedef	_BSD_MBSTATE_T_	mbstate_t;
+#undef _BSD_MBSTATE_T_
+#endif
+
+typedef struct _RuneStatePriv {
+	_RuneLocale	*__runelocale;
+	char		__private __attribute__((__aligned__));
+} _RuneStatePriv;
+
+typedef union _RuneState {
+	mbstate_t		__pad;
+	struct _RuneStatePriv	__priv;
+#define rs_runelocale		__priv.__runelocale
+#define rs_private		__priv.__private
+} _RuneState;
+#define _PRIVSIZE	(sizeof(mbstate_t)-offsetof(_RuneStatePriv, __private))
+
+
+/* */
+
+static __inline _citrus_ctype_t
+_to_cur_ctype(void)
+{
+	return (_CurrentRuneLocale->rl_citrus_ctype);
+}
+
+static __inline _RuneState *
+_ps_to_runestate(mbstate_t *ps)
+{
+	return (_RuneState *)(void *)ps;
+}
+
+static __inline _RuneState const *
+_ps_to_runestate_const(mbstate_t const *ps)
+{
+	return (_RuneState const *)(void const *)ps;
+}
+
+static __inline _RuneLocale *
+_ps_to_runelocale(mbstate_t const *ps)
+{
+	return _ps_to_runestate_const(ps)->rs_runelocale;
+}
+
+static __inline _citrus_ctype_t
+_ps_to_ctype(mbstate_t const *ps)
+{
+	if (!ps)
+		return _to_cur_ctype();
+
+	_DIAGASSERT(_ps_to_runelocale(ps) != NULL);
+
+	return _ps_to_runelocale(ps)->rl_citrus_ctype;
+}
+
+static __inline void *
+_ps_to_private(mbstate_t *ps)
+{
+	if (ps == NULL)
+		return NULL;
+	return (void *)&_ps_to_runestate(ps)->rs_private;
+}
+
+static __inline void const *
+_ps_to_private_const(mbstate_t const *ps)
+{
+	if (ps == NULL)
+		return NULL;
+	return (void const *)&_ps_to_runestate_const(ps)->rs_private;
+}
+
+static __inline void
+_init_ps(_RuneLocale *rl, mbstate_t *ps)
+{
+	size_t dum;
+	_ps_to_runestate(ps)->rs_runelocale = rl;
+	_citrus_ctype_mbrtowc(rl->rl_citrus_ctype, NULL, NULL, 0,
+			      _ps_to_private(ps), &dum);
+}
+
+static __inline void
+_fixup_ps(_RuneLocale *rl, mbstate_t *ps, int forceinit)
+{
+	/* for future multi-locale facility */
+	_DIAGASSERT(rl != NULL);
+
+	if (ps != NULL && (_ps_to_runelocale(ps) == NULL || forceinit)) {
+		_init_ps(rl, ps);
+	}
+}
+
+#endif /*_MULTIBYTE_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/nb_lc_template.h src/sys/kiconv/nb_lc_template.h
--- src.orig/sys/kiconv/nb_lc_template.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/nb_lc_template.h	2011-06-04 09:16:06.000000000 +0900
@@ -0,0 +1,257 @@
+/* $NetBSD: nb_lc_template.h,v 1.3 2010/05/22 13:15:59 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)1999, 2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NB_LC_TEMPLATE_H_
+#define _NB_LC_TEMPLATE_H_
+
+#include <sys/namei.h>
+
+#define _nb_part_t		_PREFIX(part_t)
+#define _nb_part_cache		_PREFIX(part_cache)
+#define _nb_default_c		_PREFIX(default_c)
+#define _nb_default_posix	_PREFIX(default_posix)
+#define _nb_mutex		_PREFIX(mutex)
+
+typedef struct _nb_part_t {
+	char name[_LOCALENAME_LEN_MAX];
+	_CATEGORY_TYPE *impl;
+	SIMPLEQ_ENTRY(_nb_part_t) entry;
+} _nb_part_t;
+
+static SIMPLEQ_HEAD(, _nb_part_t) _nb_part_cache =
+    SIMPLEQ_HEAD_INITIALIZER(_nb_part_cache);
+
+static const _nb_part_t _nb_default_c = {
+    _C_LOCALE,
+    __UNCONST(&_CATEGORY_DEFAULT),
+    { NULL },
+};
+
+static const _nb_part_t _nb_default_posix = {
+    _POSIX_LOCALE,
+    __UNCONST(&_CATEGORY_DEFAULT),
+    { NULL },
+};
+
+#include <sys/mutex.h>
+kmutex_t _PREFIX(mutex);
+
+static int
+_PREFIX(load_sub)(const char * __restrict name, const char * __restrict real,
+    _nb_part_t ** __restrict part, int force)
+{
+	_nb_part_t *p, *q;
+	int ret;
+
+	_DIAGASSERT(name != NULL);
+	_DIAGASSERT(part != NULL);
+
+	if (!strcmp(_C_LOCALE, name)) {
+		p = __UNCONST(&_nb_default_c);
+	} else if (!strcmp(_POSIX_LOCALE, name)) {
+		p = __UNCONST(&_nb_default_posix);
+	} else {
+		SIMPLEQ_FOREACH(p, &_nb_part_cache, entry) {
+			if (!strcmp((const char *)&p->name[0], name))
+				goto found;
+		}
+		p = malloc(sizeof(*p), M_KICONV, M_WAITOK);
+		if (force) {
+			p->impl = __UNCONST(&_CATEGORY_DEFAULT);
+		} else {
+			_DIAGASSERT(_PathLocale != NULL);
+			ret = _PREFIX(create_impl)((const char *)_PathLocale,
+			    name, &p->impl);
+			if (ret) {
+				free(p, M_KICONV);
+				return ret;
+			}
+		}
+		strlcpy(&p->name[0], name, sizeof(p->name));
+		SIMPLEQ_INSERT_TAIL(&_nb_part_cache, p, entry);
+	}
+found:
+	if (real != NULL) {
+		q = malloc(sizeof(*q), M_KICONV, M_WAITOK);
+		strlcpy(&q->name[0], real, sizeof(p->name));
+		q->impl = p->impl;
+		SIMPLEQ_INSERT_TAIL(&_nb_part_cache, q, entry);
+		p = q;
+	}
+	*part = p;
+	return 0;
+}
+
+static __inline int
+_PREFIX(load)(const char * __restrict name,
+    _nb_part_t ** __restrict part)
+{
+	int ret, force;
+	char *path, *loccat, *buf;
+	const char *aliaspath, *alias;
+
+#define _LOAD_SUB_ALIAS(key)						\
+do {									\
+	alias = __unaliasname(aliaspath, key, &buf[0], PATH_MAX);	\
+	if (alias != NULL) {						\
+		ret = (force = !__isforcemapping(alias))		\
+		    ? _PREFIX(load_sub)(name, NULL, part, force)	\
+		    : _PREFIX(load_sub)(alias, name, part, force);	\
+		_DIAGASSERT(!ret || !force);				\
+		goto done;						\
+	}								\
+} while (/*CONSTCOND*/0)
+
+	/* (1) non-aliased file */
+	mutex_enter(&_PREFIX(mutex));
+	ret = _PREFIX(load_sub)(name, NULL, part, 0);
+	if (ret != ENOENT)
+		goto out;
+
+	path = PNBUF_GET();
+	loccat = PNBUF_GET();
+	buf = PNBUF_GET();
+	KASSERT(path != NULL);
+	KASSERT(loccat != NULL);
+	KASSERT(buf != NULL);
+
+	/* (2) lookup locname/catname type alias */
+	_DIAGASSERT(_PathLocale != NULL);
+	snprintf(&path[0], PATH_MAX, "%s/" _LOCALE_ALIAS_NAME, _PathLocale);
+	aliaspath = (const char *)&path[0];
+	snprintf(&loccat[0], PATH_MAX, "%s/" _CATEGORY_NAME, name);
+	_LOAD_SUB_ALIAS((const char *)&loccat[0]);
+
+	/* (3) lookup locname type alias */
+	_LOAD_SUB_ALIAS(name);
+
+done:
+	if (path)
+		PNBUF_PUT(path);
+	if (loccat)
+		PNBUF_PUT(loccat);
+	if (buf)
+		PNBUF_PUT(buf);
+out:
+	mutex_exit(&_PREFIX(mutex));
+	return ret;
+}
+
+static const char *
+_PREFIX(setlocale)(const char * __restrict name,
+    struct _klocale_impl_t * __restrict locale)
+{
+	_nb_part_t *part;
+
+	/* name may be NULL */
+	_DIAGASSERT(locale != NULL);
+
+	if (name != NULL) {
+		if (*name == '\0')
+			name = _C_LOCALE;
+		_DIAGASSERT(name != NULL);
+		_DIAGASSERT(locale->part_name[(size_t)_CATEGORY_ID] != NULL);
+		if (strcmp(name, locale->part_name[(size_t)_CATEGORY_ID])) {
+			if (_PREFIX(load)(name, &part))
+				return NULL;
+			locale->part_name[(size_t)_CATEGORY_ID]
+			    = &part->name[0];
+			locale->part_impl[(size_t)_CATEGORY_ID]
+			    = part->impl;
+			_PREFIX(build_cache)(locale->cache, part->impl);
+			if (locale == &_global_locale)
+				_PREFIX(fixup)(part->impl);
+		}
+	}
+	return locale->part_name[(size_t)_CATEGORY_ID];
+}
+
+#include "generic_lc_template.h"
+
+#endif /*_NB_LC_TEMPLATE_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/nb_lc_template_decl.h src/sys/kiconv/nb_lc_template_decl.h
--- src.orig/sys/kiconv/nb_lc_template_decl.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/nb_lc_template_decl.h	2011-06-03 16:29:07.000000000 +0900
@@ -0,0 +1,45 @@
+/* $NetBSD: nb_lc_template_decl.h,v 1.2 2009/01/11 02:46:29 christos Exp $ */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _NB_LC_TEMPLATE_DECL_H_
+#define _NB_LC_TEMPLATE_DECL_H_
+
+#include "generic_lc_template_decl.h"
+
+static __inline int
+_PREFIX(create_impl)(const char * __restrict,
+    const char * __restrict, _CATEGORY_TYPE ** __restrict);
+
+static __inline void
+_PREFIX(build_cache)(struct _klocale_cache_t * __restrict,
+    _CATEGORY_TYPE * __restrict);
+
+static __inline void
+_PREFIX(fixup)(_CATEGORY_TYPE *);
+
+#endif /*_NB_LC_TEMPLATE_DECL_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/rune.c src/sys/kiconv/rune.c
--- src.orig/sys/kiconv/rune.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/rune.c	2011-06-04 22:16:25.000000000 +0900
@@ -0,0 +1,310 @@
+/* $NetBSD$ */
+/* NetBSD: rune.c,v 1.42 2011/03/25 00:45:24 joerg Exp */
+
+/*-
+ * Copyright (c)2010 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <sys/endian.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#define __SETLOCALE_SOURCE__
+#include <locale.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#endif
+
+#include "setlocale_local.h"
+
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+
+#include "runetype_local.h"
+
+#include "multibyte.h"
+
+#include "rune.h"
+#include "_wctype_local.h"
+#include "_wctrans_local.h"
+
+typedef struct {
+	_RuneLocale rl;
+	unsigned char	rlp_ctype_tab  [_CTYPE_NUM_CHARS + 1];
+	short		rlp_tolower_tab[_CTYPE_NUM_CHARS + 1];
+	short		rlp_toupper_tab[_CTYPE_NUM_CHARS + 1];
+	char		rlp_codeset[33]; /* XXX */
+} _RuneLocalePriv;
+
+static __inline void
+_rune_wctype_init(_RuneLocale *rl)
+{
+	memcpy(&rl->rl_wctype, &_DefaultRuneLocale.rl_wctype,
+	    sizeof(rl->rl_wctype));
+}
+
+void
+_wctrans_init(_RuneLocale *rl)
+{
+	rl->rl_wctrans[_WCTRANS_INDEX_LOWER].te_name   = "tolower";
+	rl->rl_wctrans[_WCTRANS_INDEX_LOWER].te_cached = &rl->rl_maplower[0];
+	rl->rl_wctrans[_WCTRANS_INDEX_LOWER].te_extmap = &rl->rl_maplower_ext;
+	rl->rl_wctrans[_WCTRANS_INDEX_UPPER].te_name   = "toupper";
+	rl->rl_wctrans[_WCTRANS_INDEX_UPPER].te_cached = &rl->rl_mapupper[0];
+	rl->rl_wctrans[_WCTRANS_INDEX_UPPER].te_extmap = &rl->rl_mapupper_ext;
+}
+
+static __inline void
+_rune_init_priv(_RuneLocalePriv *rlp)
+{
+#if _CTYPE_CACHE_SIZE != _CTYPE_NUM_CHARS
+	int i;
+
+	for (i = _CTYPE_CACHE_SIZE; i < _CTYPE_NUM_CHARS; ++i) {
+		rlp->rlp_ctype_tab  [i + 1] = 0;
+		rlp->rlp_tolower_tab[i + 1] = i;
+		rlp->rlp_toupper_tab[i + 1] = i;
+	}
+#endif
+	rlp->rlp_ctype_tab  [0] = 0;
+	rlp->rlp_tolower_tab[0] = EOF;
+	rlp->rlp_toupper_tab[0] = EOF;
+
+	rlp->rl.rl_ctype_tab   = (const unsigned char *)&rlp->rlp_ctype_tab[0];
+	rlp->rl.rl_tolower_tab = (const short *)&rlp->rlp_tolower_tab[0];
+	rlp->rl.rl_toupper_tab = (const short *)&rlp->rlp_toupper_tab[0];
+	rlp->rl.rl_codeset     = (const char *)&rlp->rlp_codeset[0];
+
+	_rune_wctype_init(&rlp->rl);
+	_wctrans_init(&rlp->rl);
+}
+
+static __inline void
+_rune_find_codeset(char *s, size_t n,
+    char *var, size_t *plenvar)
+{
+	size_t lenvar;
+	const char *endvar;
+
+#define _RUNE_CODESET_LEN (sizeof(_RUNE_CODESET)-1)
+
+	lenvar = *plenvar;
+	for (/**/; lenvar > _RUNE_CODESET_LEN; ++var, --lenvar) {
+		if (!memcmp(var, _RUNE_CODESET, _RUNE_CODESET_LEN)) {
+			*var = '\0';
+			*plenvar -= lenvar;
+			endvar = &var[_RUNE_CODESET_LEN];
+			while (n-- > 1 && lenvar-- > _RUNE_CODESET_LEN) {
+				if (*endvar == ' ' || *endvar == '\t')
+					break;
+				*s++ = *endvar++;
+			}
+			break;
+		}
+	}
+	*s = '\0';
+}
+
+static __inline int
+_rune_read_file(const char * __restrict var, size_t lenvar,
+    _RuneLocale ** __restrict prl)
+{
+	int ret, i;
+	const _FileRuneLocale *frl;
+	const _FileRuneEntry *fre;
+	const uint32_t *frune;
+	_RuneLocalePriv *rlp;
+	_RuneLocale *rl;
+	_RuneEntry *re;
+	uint32_t *rune;
+	uint32_t runetype_len, maplower_len, mapupper_len, variable_len;
+	size_t len, n;
+
+	if (lenvar < sizeof(*frl))
+		return EFTYPE;
+	lenvar -= sizeof(*frl);
+	frl = (const _FileRuneLocale *)(const void *)var;
+	if (memcmp(_RUNECT10_MAGIC, &frl->frl_magic[0], sizeof(frl->frl_magic)))
+		return EFTYPE;
+
+	runetype_len = be32toh(frl->frl_runetype_ext.frr_nranges);
+	maplower_len = be32toh(frl->frl_maplower_ext.frr_nranges);
+	mapupper_len = be32toh(frl->frl_mapupper_ext.frr_nranges);
+	len = runetype_len + maplower_len + mapupper_len;
+
+	fre = (const _FileRuneEntry *)(const void *)(frl + 1);
+	frune = (const uint32_t *)(const void *)(fre + len);
+
+	variable_len = be32toh((uint32_t)frl->frl_variable_len);
+
+	n = (len * sizeof(*fre)) + variable_len;
+	if (lenvar < n)
+		return EFTYPE;
+	lenvar -= n;
+
+	n = sizeof(*rlp) + (len * sizeof(*re)) + lenvar;
+	rlp = (_RuneLocalePriv *)malloc(n, M_KICONV, M_WAITOK);
+	_rune_init_priv(rlp);
+
+	rl = &rlp->rl;
+	re = (_RuneEntry *)(void *)(rlp + 1);
+	rune = (uint32_t *)(void *)(re + len);
+
+	for (i = 0; i < _CTYPE_CACHE_SIZE; ++i) {
+		rl->rl_runetype[i] = be32toh(frl->frl_runetype[i]);
+		rl->rl_maplower[i] = be32toh((uint32_t)frl->frl_maplower[i]);
+		rl->rl_mapupper[i] = be32toh((uint32_t)frl->frl_mapupper[i]);
+	}
+
+#define READ_RANGE(name)						\
+do {									\
+	const _FileRuneEntry *end_fre;					\
+	const uint32_t *end_frune;					\
+									\
+	rl->rl_##name##_ext.rr_nranges = name##_len;			\
+	rl->rl_##name##_ext.rr_rune_ranges = re;			\
+									\
+	end_fre = fre + name##_len;					\
+	while (fre < end_fre) {						\
+		re->re_min = be32toh((uint32_t)fre->fre_min);		\
+		re->re_max = be32toh((uint32_t)fre->fre_max);		\
+		re->re_map = be32toh((uint32_t)fre->fre_map);		\
+		if (re->re_map != 0) {					\
+			re->re_rune_types = NULL;			\
+		} else {						\
+			re->re_rune_types = rune;			\
+			len = re->re_max - re->re_min + 1;		\
+			n = len * sizeof(*frune);			\
+			if (lenvar < n) {				\
+				ret = EFTYPE;				\
+				goto err;				\
+			}						\
+			lenvar -= n;					\
+			end_frune = frune + len;			\
+			while (frune < end_frune)			\
+				*rune++ = be32toh(*frune++);		\
+		}							\
+		++fre, ++re;						\
+	}								\
+} while (/*CONSTCOND*/0)
+
+	READ_RANGE(runetype);
+	READ_RANGE(maplower);
+	READ_RANGE(mapupper);
+
+	memcpy((void *)rune, (void const *)frune, variable_len);
+	rl->rl_variable_len = variable_len;
+	rl->rl_variable = (void *)rune;
+
+	if (lenvar > 0) {
+		ret = EFTYPE;
+		goto err;
+	}
+
+	_rune_find_codeset(rlp->rlp_codeset, sizeof(rlp->rlp_codeset),
+	    (char *)rl->rl_variable, &rl->rl_variable_len);
+
+	ret = _citrus_ctype_open(&rl->rl_citrus_ctype, frl->frl_encoding,
+	    rl->rl_variable, rl->rl_variable_len, _PRIVSIZE);
+	if (ret)
+		goto err;
+	if (__mb_len_max_runtime <
+	    _citrus_ctype_get_mb_cur_max(rl->rl_citrus_ctype)) {
+		ret = EINVAL;
+		goto err;
+	}
+
+	for (i = 0; i < _CTYPE_CACHE_SIZE; ++i) {
+		wint_t wc;
+
+		ret = _citrus_ctype_btowc(rl->rl_citrus_ctype, i, &wc);
+		if (ret)
+			goto err;
+		if (wc == WEOF) {
+			rlp->rlp_ctype_tab[i + 1] = 0;
+			rlp->rlp_tolower_tab[i + 1] = i;
+			rlp->rlp_toupper_tab[i + 1] = i;
+		} else {
+			rlp->rlp_ctype_tab[i + 1] = (unsigned char)
+			    _runetype_to_ctype(_runetype_priv(rl, wc));
+
+/* XXX: XXXNONAKA _towctrans_priv() */
+#define CONVERT_MAP(name)						\
+do {									\
+	wint_t map;							\
+	int c;								\
+									\
+	map = _towctrans_priv(NULL, wc, _wctrans_##name(rl));		\
+	if (map == wc || (_citrus_ctype_wctob(rl->rl_citrus_ctype,	\
+	    map, &c)  || c == EOF))					\
+		c = i;							\
+	rlp->rlp_to##name##_tab[i + 1] = (short)c;			\
+} while (/*CONSTCOND*/0)
+
+			CONVERT_MAP(lower);
+			CONVERT_MAP(upper);
+		}
+	}
+	*prl = rl;
+	return 0;
+
+err:
+	free(rlp, M_WAITOK);
+	return ret;
+}
+
+int
+_rune_load(const char * __restrict var, size_t lenvar,
+    _RuneLocale ** __restrict prl)
+{
+	int ret;
+
+	_DIAGASSERT(var != NULL || lenvar < 1);
+	_DIAGASSERT(prl != NULL);
+
+	if (lenvar < 1)
+		return EFTYPE;
+	switch (*var) {
+	case 'R':
+		ret = _rune_read_file(var, lenvar, prl);
+		break;
+	default:
+		ret = EFTYPE;
+	}
+	return ret;
+}
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/rune.h src/sys/kiconv/rune.h
--- src.orig/sys/kiconv/rune.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/rune.h	2011-06-04 12:51:26.000000000 +0900
@@ -0,0 +1 @@
+void _wctrans_init(_RuneLocale *rl);
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/runetable.c src/sys/kiconv/runetable.c
--- src.orig/sys/kiconv/runetable.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/runetable.c	2011-06-03 14:58:44.000000000 +0900
@@ -0,0 +1,360 @@
+/*	$NetBSD$	*/
+/*	NetBSD: runetable.c,v 1.27 2010/06/19 13:26:52 tnozaki Exp	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libc/locale/table.c,v 1.13 2000/02/08 07:43:25 obrien Exp $
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)table.c	8.1 (Berkeley) 6/27/93";
+#else
+__RCSID("NetBSD: runetable.c,v 1.27 2010/06/19 13:26:52 tnozaki Exp");
+#endif
+#endif /* LIBC_SCCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <sys/types.h>
+#include <assert.h>
+#include <wchar.h>
+#endif
+
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "runetype_local.h"
+
+const _RuneLocale _DefaultRuneLocale = {
+    {	/*00*/	_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+	/*08*/	_RUNETYPE_C,
+		_RUNETYPE_C|_RUNETYPE_S|_RUNETYPE_B,
+		_RUNETYPE_C|_RUNETYPE_S,
+		_RUNETYPE_C|_RUNETYPE_S,
+		_RUNETYPE_C|_RUNETYPE_S,
+		_RUNETYPE_C|_RUNETYPE_S,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+	/*10*/	_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+	/*18*/	_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+		_RUNETYPE_C,
+	/*20*/	_RUNETYPE_S|_RUNETYPE_B|_RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+	/*28*/	_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+	/*30*/	_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|0,
+		_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|1,
+		_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|2,
+		_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|3,
+		_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|4,
+		_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|5,
+		_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|6,
+		_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|7,
+	/*38*/	_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|8,
+		_RUNETYPE_D|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_X|_RUNETYPE_SW1|9,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+	/*40*/	_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|10,
+		_RUNETYPE_U|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|11,
+		_RUNETYPE_U|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|12,
+		_RUNETYPE_U|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|13,
+		_RUNETYPE_U|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|14,
+		_RUNETYPE_U|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|15,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+	/*48*/	_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+	/*50*/	_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+	/*58*/	_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_U|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+	/*60*/	_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|10,
+		_RUNETYPE_L|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|11,
+		_RUNETYPE_L|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|12,
+		_RUNETYPE_L|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|13,
+		_RUNETYPE_L|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|14,
+		_RUNETYPE_L|_RUNETYPE_X|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1|15,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+	/*68*/	_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+	/*70*/	_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+	/*78*/	_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_L|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_A|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_P|_RUNETYPE_R|_RUNETYPE_G|_RUNETYPE_SW1,
+		_RUNETYPE_C,
+#ifdef ALL_80_TO_FF_SW1
+	/*80*/	_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+	/*90*/	_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+	/*A0*/	_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+	/*B0*/	_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+	/*C0*/	_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+	/*D0*/	_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+	/*E0*/	_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+	/*F0*/	_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+		_RUNETYPE_R|_RUNETYPE_SW1, _RUNETYPE_R|_RUNETYPE_SW1,
+#endif
+    },
+    {	0x00,	0x01,	0x02,	0x03,	0x04,	0x05,	0x06,	0x07,
+     	0x08,	0x09,	0x0a,	0x0b,	0x0c,	0x0d,	0x0e,	0x0f,
+	0x10,	0x11,	0x12,	0x13,	0x14,	0x15,	0x16,	0x17,
+     	0x18,	0x19,	0x1a,	0x1b,	0x1c,	0x1d,	0x1e,	0x1f,
+	0x20,	0x21,	0x22,	0x23,	0x24,	0x25,	0x26,	0x27,
+     	0x28,	0x29,	0x2a,	0x2b,	0x2c,	0x2d,	0x2e,	0x2f,
+	0x30,	0x31,	0x32,	0x33,	0x34,	0x35,	0x36,	0x37,
+     	0x38,	0x39,	0x3a,	0x3b,	0x3c,	0x3d,	0x3e,	0x3f,
+	0x40,	'a',	'b',	'c',	'd',	'e',	'f',	'g',
+     	'h',	'i',	'j',	'k',	'l',	'm',	'n',	'o',
+	'p',	'q',	'r',	's',	't',	'u',	'v',	'w',
+     	'x',	'y',	'z',	0x5b,	0x5c,	0x5d,	0x5e,	0x5f,
+	0x60,	'a',	'b',	'c',	'd',	'e',	'f',	'g',
+     	'h',	'i',	'j',	'k',	'l',	'm',	'n',	'o',
+	'p',	'q',	'r',	's',	't',	'u',	'v',	'w',
+     	'x',	'y',	'z',	0x7b,	0x7c,	0x7d,	0x7e,	0x7f,
+	0x80,	0x81,	0x82,	0x83,	0x84,	0x85,	0x86,	0x87,
+     	0x88,	0x89,	0x8a,	0x8b,	0x8c,	0x8d,	0x8e,	0x8f,
+	0x90,	0x91,	0x92,	0x93,	0x94,	0x95,	0x96,	0x97,
+     	0x98,	0x99,	0x9a,	0x9b,	0x9c,	0x9d,	0x9e,	0x9f,
+	0xa0,	0xa1,	0xa2,	0xa3,	0xa4,	0xa5,	0xa6,	0xa7,
+     	0xa8,	0xa9,	0xaa,	0xab,	0xac,	0xad,	0xae,	0xaf,
+	0xb0,	0xb1,	0xb2,	0xb3,	0xb4,	0xb5,	0xb6,	0xb7,
+     	0xb8,	0xb9,	0xba,	0xbb,	0xbc,	0xbd,	0xbe,	0xbf,
+	0xc0,	0xc1,	0xc2,	0xc3,	0xc4,	0xc5,	0xc6,	0xc7,
+     	0xc8,	0xc9,	0xca,	0xcb,	0xcc,	0xcd,	0xce,	0xcf,
+	0xd0,	0xd1,	0xd2,	0xd3,	0xd4,	0xd5,	0xd6,	0xd7,
+     	0xd8,	0xd9,	0xda,	0xdb,	0xdc,	0xdd,	0xde,	0xdf,
+	0xe0,	0xe1,	0xe2,	0xe3,	0xe4,	0xe5,	0xe6,	0xe7,
+     	0xe8,	0xe9,	0xea,	0xeb,	0xec,	0xed,	0xee,	0xef,
+	0xf0,	0xf1,	0xf2,	0xf3,	0xf4,	0xf5,	0xf6,	0xf7,
+     	0xf8,	0xf9,	0xfa,	0xfb,	0xfc,	0xfd,	0xfe,	0xff,
+    },
+    {	0x00,	0x01,	0x02,	0x03,	0x04,	0x05,	0x06,	0x07,
+     	0x08,	0x09,	0x0a,	0x0b,	0x0c,	0x0d,	0x0e,	0x0f,
+	0x10,	0x11,	0x12,	0x13,	0x14,	0x15,	0x16,	0x17,
+     	0x18,	0x19,	0x1a,	0x1b,	0x1c,	0x1d,	0x1e,	0x1f,
+	0x20,	0x21,	0x22,	0x23,	0x24,	0x25,	0x26,	0x27,
+     	0x28,	0x29,	0x2a,	0x2b,	0x2c,	0x2d,	0x2e,	0x2f,
+	0x30,	0x31,	0x32,	0x33,	0x34,	0x35,	0x36,	0x37,
+     	0x38,	0x39,	0x3a,	0x3b,	0x3c,	0x3d,	0x3e,	0x3f,
+	0x40,	'A',	'B',	'C',	'D',	'E',	'F',	'G',
+     	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
+	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
+     	'X',	'Y',	'Z',	0x5b,	0x5c,	0x5d,	0x5e,	0x5f,
+	0x60,	'A',	'B',	'C',	'D',	'E',	'F',	'G',
+     	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
+	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
+     	'X',	'Y',	'Z',	0x7b,	0x7c,	0x7d,	0x7e,	0x7f,
+	0x80,	0x81,	0x82,	0x83,	0x84,	0x85,	0x86,	0x87,
+     	0x88,	0x89,	0x8a,	0x8b,	0x8c,	0x8d,	0x8e,	0x8f,
+	0x90,	0x91,	0x92,	0x93,	0x94,	0x95,	0x96,	0x97,
+     	0x98,	0x99,	0x9a,	0x9b,	0x9c,	0x9d,	0x9e,	0x9f,
+	0xa0,	0xa1,	0xa2,	0xa3,	0xa4,	0xa5,	0xa6,	0xa7,
+     	0xa8,	0xa9,	0xaa,	0xab,	0xac,	0xad,	0xae,	0xaf,
+	0xb0,	0xb1,	0xb2,	0xb3,	0xb4,	0xb5,	0xb6,	0xb7,
+     	0xb8,	0xb9,	0xba,	0xbb,	0xbc,	0xbd,	0xbe,	0xbf,
+	0xc0,	0xc1,	0xc2,	0xc3,	0xc4,	0xc5,	0xc6,	0xc7,
+     	0xc8,	0xc9,	0xca,	0xcb,	0xcc,	0xcd,	0xce,	0xcf,
+	0xd0,	0xd1,	0xd2,	0xd3,	0xd4,	0xd5,	0xd6,	0xd7,
+     	0xd8,	0xd9,	0xda,	0xdb,	0xdc,	0xdd,	0xde,	0xdf,
+	0xe0,	0xe1,	0xe2,	0xe3,	0xe4,	0xe5,	0xe6,	0xe7,
+     	0xe8,	0xe9,	0xea,	0xeb,	0xec,	0xed,	0xee,	0xef,
+	0xf0,	0xf1,	0xf2,	0xf3,	0xf4,	0xf5,	0xf6,	0xf7,
+     	0xf8,	0xf9,	0xfa,	0xfb,	0xfc,	0xfd,	0xfe,	0xff,
+    },
+    { 0, NULL },
+    { 0, NULL },
+    { 0, NULL },
+    NULL, 0,
+    "646",
+    &_citrus_ctype_default,
+    {
+	{   "towlower",
+	    __UNCONST(&_DefaultRuneLocale.rl_maplower[0]),
+	    __UNCONST(&_DefaultRuneLocale.rl_maplower_ext)
+	},
+	{   "towupper",
+	    __UNCONST(&_DefaultRuneLocale.rl_mapupper[0]),
+	    __UNCONST(&_DefaultRuneLocale.rl_mapupper_ext)
+	},
+    },
+    {
+	    { "alnum", _RUNETYPE_A|_RUNETYPE_D },
+	    { "alpha", _RUNETYPE_A },
+	    { "blank", _RUNETYPE_B },
+	    { "cntrl", _RUNETYPE_C },
+	    { "digit", _RUNETYPE_D },
+	    { "graph", _RUNETYPE_G },
+	    { "lower", _RUNETYPE_L },
+	    { "print", _RUNETYPE_R },
+	    { "punct", _RUNETYPE_P },
+	    { "space", _RUNETYPE_S },
+	    { "upper", _RUNETYPE_U },
+	    { "xdigit", _RUNETYPE_X },
+    },
+    _C_ctype_,
+    _C_tolower_,
+    _C_toupper_
+};
+
+const _RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale;
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/runetype_file.h src/sys/kiconv/runetype_file.h
--- src.orig/sys/kiconv/runetype_file.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/runetype_file.h	2011-06-03 14:24:19.000000000 +0900
@@ -0,0 +1,136 @@
+/* $NetBSD: runetype_file.h,v 1.3 2010/06/20 02:23:15 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)runetype.h	8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef	_RUNETYPE_FILE_H_
+#define	_RUNETYPE_FILE_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "ctype_local.h"
+
+/* for cross host tools on older systems */
+#ifndef UINT32_C
+/* assumes sizeof(unsigned int)>=4 */
+#define UINT32_C(c) ((uint32_t)(c##U))
+#endif
+
+typedef uint32_t	__nbrune_t;
+typedef uint64_t	__runepad_t;
+
+#define _DEFAULT_INVALID_RUNE ((__nbrune_t)-3)
+
+/*
+ * The lower 8 bits of runetype[] contain the digit value of the rune.
+ */
+typedef uint32_t _RuneType;
+#define	_RUNETYPE_A	UINT32_C(0x00000100)	/* Alpha */
+#define	_RUNETYPE_C	UINT32_C(0x00000200)	/* Control */
+#define	_RUNETYPE_D	UINT32_C(0x00000400)	/* Digit */
+#define	_RUNETYPE_G	UINT32_C(0x00000800)	/* Graph */
+#define	_RUNETYPE_L	UINT32_C(0x00001000)	/* Lower */
+#define	_RUNETYPE_P	UINT32_C(0x00002000)	/* Punct */
+#define	_RUNETYPE_S	UINT32_C(0x00004000)	/* Space */
+#define	_RUNETYPE_U	UINT32_C(0x00008000)	/* Upper */
+#define	_RUNETYPE_X	UINT32_C(0x00010000)	/* X digit */
+#define	_RUNETYPE_B	UINT32_C(0x00020000)	/* Blank */
+#define	_RUNETYPE_R	UINT32_C(0x00040000)	/* Print */
+#define	_RUNETYPE_I	UINT32_C(0x00080000)	/* Ideogram */
+#define	_RUNETYPE_T	UINT32_C(0x00100000)	/* Special */
+#define	_RUNETYPE_Q	UINT32_C(0x00200000)	/* Phonogram */
+#define	_RUNETYPE_SWM	UINT32_C(0xc0000000)/* Mask to get screen width data */
+#define	_RUNETYPE_SWS	30		/* Bits to shift to get width */
+#define	_RUNETYPE_SW0	UINT32_C(0x20000000)	/* 0 width character */
+#define	_RUNETYPE_SW1	UINT32_C(0x40000000)	/* 1 width character */
+#define	_RUNETYPE_SW2	UINT32_C(0x80000000)	/* 2 width character */
+#define	_RUNETYPE_SW3	UINT32_C(0xc0000000)	/* 3 width character */
+
+/*
+ * rune file format.  network endian.
+ */
+typedef struct {
+	int32_t		fre_min;	/* First rune of the range */
+	int32_t		fre_max;	/* Last rune (inclusive) of the range */
+	int32_t		fre_map;	/* What first maps to in maps */
+	uint32_t	fre_pad1;	/* backward compatibility */
+	__runepad_t	fre_pad2;	/* backward compatibility */
+} __packed _FileRuneEntry;
+
+
+typedef struct {
+	uint32_t	frr_nranges;	/* Number of ranges stored */
+	uint32_t	frr_pad1;	/* backward compatibility */
+	__runepad_t	frr_pad2;	/* backward compatibility */
+} __packed _FileRuneRange;
+
+
+typedef struct {
+	char		frl_magic[8];	/* Magic saying what version we are */
+	char		frl_encoding[32];/* ASCII name of this encoding */
+
+	__runepad_t	frl_pad1;	/* backward compatibility */
+	__runepad_t	frl_pad2;	/* backward compatibility */
+	int32_t		frl_invalid_rune;
+	uint32_t	frl_pad3;	/* backward compatibility */
+
+	_RuneType	frl_runetype[_CTYPE_CACHE_SIZE];
+	int32_t		frl_maplower[_CTYPE_CACHE_SIZE];
+	int32_t		frl_mapupper[_CTYPE_CACHE_SIZE];
+
+	/*
+	 * The following are to deal with Runes larger than _CTYPE_CACHE_SIZE - 1.
+	 * Their data is actually contiguous with this structure so as to make
+	 * it easier to read/write from/to disk.
+	 */
+	_FileRuneRange	frl_runetype_ext;
+	_FileRuneRange	frl_maplower_ext;
+	_FileRuneRange	frl_mapupper_ext;
+
+	__runepad_t	frl_pad4;	/* backward compatibility */
+	int32_t		frl_variable_len;/* how long that data is */
+	uint32_t	frl_pad5;	/* backward compatibility */
+
+	/* variable size data follows */
+} __packed _FileRuneLocale;
+
+
+/* magic number for LC_CTYPE (rune)locale declaration */
+#define	_RUNECT10_MAGIC	"RuneCT10"	/* Indicates version 0 of RuneLocale */
+
+/* codeset tag */
+#define _RUNE_CODESET "CODESET="
+
+#endif	/* !_RUNETYPE_FILE_H_ */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/runetype_local.h src/sys/kiconv/runetype_local.h
--- src.orig/sys/kiconv/runetype_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/runetype_local.h	2011-06-03 14:24:46.000000000 +0900
@@ -0,0 +1,137 @@
+/*	$NetBSD: runetype_local.h,v 1.12 2010/06/20 02:23:15 tnozaki Exp $	*/
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)rune.h	8.1 (Berkeley) 6/27/93
+ *	@(#)runetype.h	8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef	_RUNETYPE_LOCAL_H_
+#define	_RUNETYPE_LOCAL_H_
+
+#include "runetype_misc.h"
+
+#define _RUNE_ISCACHED(c)	((c)>=0 && (c)<_CTYPE_CACHE_SIZE)
+
+
+/*
+ * expanded rune locale declaration.  local to the host.  host endian.
+ */
+typedef struct {
+	__nbrune_t	re_min;		/* First rune of the range */
+	__nbrune_t	re_max;		/* Last rune (inclusive) of the range */
+	__nbrune_t	re_map;		/* What first maps to in maps */
+	_RuneType	*re_rune_types;	/* Array of types in range */
+} _RuneEntry;
+
+
+typedef struct {
+	uint32_t	rr_nranges;	/* Number of ranges stored */
+	_RuneEntry	*rr_rune_ranges;
+} _RuneRange;
+
+
+/*
+ * wctrans stuffs.
+ */
+typedef struct _WCTransEntry {
+	const char	*te_name;
+	__nbrune_t	*te_cached;
+	_RuneRange	*te_extmap;
+} _WCTransEntry;
+#define _WCTRANS_INDEX_LOWER	0
+#define _WCTRANS_INDEX_UPPER	1
+#define _WCTRANS_NINDEXES	2
+
+/*
+ * wctype stuffs.
+ */
+typedef struct _WCTypeEntry {
+	const char	*te_name;
+	_RuneType	te_mask;
+} _WCTypeEntry;
+#define _WCTYPE_INDEX_ALNUM	0
+#define _WCTYPE_INDEX_ALPHA	1
+#define _WCTYPE_INDEX_BLANK	2
+#define _WCTYPE_INDEX_CNTRL	3
+#define _WCTYPE_INDEX_DIGIT	4
+#define _WCTYPE_INDEX_GRAPH	5
+#define _WCTYPE_INDEX_LOWER	6
+#define _WCTYPE_INDEX_PRINT	7
+#define _WCTYPE_INDEX_PUNCT	8
+#define _WCTYPE_INDEX_SPACE	9
+#define _WCTYPE_INDEX_UPPER	10
+#define _WCTYPE_INDEX_XDIGIT	11
+#define _WCTYPE_NINDEXES	12
+
+/*
+ * ctype stuffs
+ */
+
+typedef struct _RuneLocale {
+	/*
+	 * copied from _FileRuneLocale
+	 */
+	_RuneType	rl_runetype[_CTYPE_CACHE_SIZE];
+	__nbrune_t	rl_maplower[_CTYPE_CACHE_SIZE];
+	__nbrune_t	rl_mapupper[_CTYPE_CACHE_SIZE];
+	_RuneRange	rl_runetype_ext;
+	_RuneRange	rl_maplower_ext;
+	_RuneRange	rl_mapupper_ext;
+
+	void		*rl_variable;
+	size_t		rl_variable_len;
+
+	/*
+	 * the following portion is generated on the fly
+	 */
+	const char			*rl_codeset;
+	struct _citrus_ctype_rec	*rl_citrus_ctype;
+	_WCTransEntry			rl_wctrans[_WCTRANS_NINDEXES];
+	_WCTypeEntry			rl_wctype[_WCTYPE_NINDEXES];
+
+	const unsigned char		*rl_ctype_tab;
+	const short			*rl_tolower_tab;
+	const short			*rl_toupper_tab;
+} _RuneLocale;
+
+/*
+ * global variables
+ */
+extern const _RuneLocale _DefaultRuneLocale;
+extern const _RuneLocale *_CurrentRuneLocale;
+
+__BEGIN_DECLS
+int _rune_load(const char * __restrict, size_t, _RuneLocale ** __restrict);
+__END_DECLS
+
+#endif	/* !_RUNETYPE_LOCAL_H_ */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/runetype_misc.h src/sys/kiconv/runetype_misc.h
--- src.orig/sys/kiconv/runetype_misc.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/runetype_misc.h	2011-06-03 14:24:07.000000000 +0900
@@ -0,0 +1,130 @@
+/* $NetBSD: runetype_misc.h,v 1.2 2010/12/14 02:28:57 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)runetype.h	8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef	_RUNETYPE_MISC_H_
+#define	_RUNETYPE_MISC_H_
+
+#include <sys/ctype_bits.h>
+#include "runetype_file.h"
+
+static __inline int
+_runetype_to_ctype(_RuneType bits)
+{
+	int ret;
+
+	if (bits == (_RuneType)0)
+		return 0;
+	ret = 0;
+	if (bits & _RUNETYPE_U)
+		ret |= _CTYPE_U;
+	if (bits & _RUNETYPE_L)
+		ret |= _CTYPE_L;
+	if (bits & _RUNETYPE_D)
+		ret |= _CTYPE_N;
+	if (bits & _RUNETYPE_S)
+		ret |= _CTYPE_S;
+	if (bits & _RUNETYPE_P)
+		ret |= _CTYPE_P;
+	if (bits & _RUNETYPE_C)
+		ret |= _CTYPE_C;
+	if (bits & _RUNETYPE_X)
+		ret |= _CTYPE_X;
+	/*
+	 * TWEAK!  _B has been used incorrectly (or with older
+	 * declaration) in ctype.h isprint() macro.
+	 * _B does not mean isblank, it means "isprint && !isgraph".
+	 * the following is okay since isblank() was hardcoded in
+	 * function (i.e. isblank() is inherently locale unfriendly).
+	 */
+#if 1
+	if ((bits & (_RUNETYPE_R | _RUNETYPE_G)) == _RUNETYPE_R)
+		ret |= _CTYPE_B;
+#else
+	if (bits & _RUNETYPE_B)
+		ret |= _CTYPE_B;
+#endif
+	return ret;
+}
+
+static __inline _RuneType
+_runetype_from_ctype(int bits, int ch)
+{
+        _RuneType ret;
+
+	/*
+	 * TWEAKS!
+	 * - old locale file declarations do not have proper _B
+	 *   in many cases.
+	 * - isprint() declaration in ctype.h incorrectly uses _B.
+	 *   _B means "isprint but !isgraph", not "isblank" with the
+	 *   declaration.
+	 * - _X and _RUNETYPE_X have negligible difference in meaning.
+	 * - we don't set digit value, fearing that it would be
+	 *   too much of hardcoding.  we may need to revisit it.
+	 */
+
+	ret = (_RuneType)0;
+	if (bits & _CTYPE_U)
+		ret |= _RUNETYPE_U;
+	if (bits & _CTYPE_L)
+		ret |= _RUNETYPE_L;
+	if (bits & _CTYPE_N)
+		ret |= _RUNETYPE_D;
+	if (bits & _CTYPE_S)
+		ret |= _RUNETYPE_S;
+	if (bits & _CTYPE_P)
+		ret |= _RUNETYPE_P;
+	if (bits & _CTYPE_C)
+		ret |= _RUNETYPE_C;
+	/* derived flag bits, duplicate of ctype.h */
+	if (bits & (_CTYPE_U|_CTYPE_L))
+		ret |= _RUNETYPE_A;
+	if (bits & (_CTYPE_N|_CTYPE_X))
+		ret |= _RUNETYPE_X;
+	if (bits & (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_N))
+		ret |= _RUNETYPE_G;
+	/* we don't really trust _B in the file.  see above. */
+	if (bits & _CTYPE_B)
+		ret |= _RUNETYPE_B;
+	if ((bits & (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_N|_CTYPE_B)) ||
+	    ch == ' ')
+		ret |= (_RUNETYPE_R | _RUNETYPE_SW1);
+	if (ch == ' ' || ch == '\t')
+		ret |= _RUNETYPE_B;
+	return ret;
+}
+
+#endif	/* !_RUNETYPE_MISC_H_ */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/setlocale_local.h src/sys/kiconv/setlocale_local.h
--- src.orig/sys/kiconv/setlocale_local.h	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/setlocale_local.h	2011-06-04 22:13:12.000000000 +0900
@@ -0,0 +1,84 @@
+/* $NetBSD: setlocale_local.h,v 1.7 2010/06/07 13:52:30 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SETLOCALE_LOCAL_H_
+#define _SETLOCALE_LOCAL_H_
+
+/* XXX: LC_CTYPE only */
+#define	LC_CTYPE	0
+#define	_LC_LAST	1
+
+#define _LOCALENAME_LEN_MAX 33
+
+#define _C_LOCALE		"C"
+#define _POSIX_LOCALE		"POSIX"
+
+extern const char		*_PathLocale;
+#define _LOCALE_ALIAS_NAME	"locale.alias"
+
+typedef void *_klocale_part_t;
+
+struct _klocale_cache_t {
+	const unsigned char *ctype_tab;
+	const short *tolower_tab;
+	const short *toupper_tab;
+	size_t mb_cur_max;
+};
+
+struct _klocale_impl_t {
+	struct _klocale_cache_t *cache;
+	char query[_LOCALENAME_LEN_MAX * _LC_LAST];
+	const char *part_name[_LC_LAST];
+	_klocale_part_t part_impl[_LC_LAST];
+};
+
+typedef const char *(*_klocale_set_t)(const char * __restrict,
+    struct _klocale_impl_t * __restrict);
+
+typedef struct {
+	const char* name;
+	int category;
+	_klocale_set_t setlocale;
+} _klocale_category_t;
+
+__BEGIN_DECLS
+struct _klocale_impl_t	**_current_locale(void);
+
+extern struct _klocale_impl_t _global_locale;
+__END_DECLS
+
+static __inline struct _klocale_impl_t *
+_locale_to_impl(klocale_t locale)
+{
+
+	if (locale == NULL)
+		return *_current_locale();
+	return (struct _klocale_impl_t *)locale;
+}
+
+#endif /*_SETLOCALE_LOCAL_H_*/
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/tolower_.c src/sys/kiconv/tolower_.c
--- src.orig/sys/kiconv/tolower_.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/tolower_.c	2011-06-03 15:10:15.000000000 +0900
@@ -0,0 +1,66 @@
+/*	$NetBSD$	*/
+/*	NetBSD: tolower_.c,v 1.13 2010/06/01 13:52:08 tnozaki Exp	*/
+
+/*
+ * Written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_RCS) && !defined(lint)
+__RCSID("NetBSD: tolower_.c,v 1.13 2010/06/01 13:52:08 tnozaki Exp");
+#endif /* LIBC_RCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/ctype_bits.h>
+#ifdef	_KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <stdio.h>
+#endif
+#include "ctype_local.h"
+
+#if EOF != -1
+#error "EOF != -1"
+#endif
+
+const short _C_tolower_[1 + _CTYPE_NUM_CHARS] = {
+	EOF,
+	0x00,	0x01,	0x02,	0x03,	0x04,	0x05,	0x06,	0x07,
+	0x08,	0x09,	0x0a,	0x0b,	0x0c,	0x0d,	0x0e,	0x0f,
+	0x10,	0x11,	0x12,	0x13,	0x14,	0x15,	0x16,	0x17,
+	0x18,	0x19,	0x1a,	0x1b,	0x1c,	0x1d,	0x1e,	0x1f,
+	0x20,	0x21,	0x22,	0x23,	0x24,	0x25,	0x26,	0x27,
+	0x28,	0x29,	0x2a,	0x2b,	0x2c,	0x2d,	0x2e,	0x2f,
+	0x30,	0x31,	0x32,	0x33,	0x34,	0x35,	0x36,	0x37,
+	0x38,	0x39,	0x3a,	0x3b,	0x3c,	0x3d,	0x3e,	0x3f,
+	0x40,	'a',	'b',	'c',	'd',	'e',	'f',	'g',
+	'h',	'i',	'j',	'k',	'l',	'm',	'n',	'o',
+	'p',	'q',	'r',	's',	't',	'u',	'v',	'w',
+	'x',	'y',	'z',	0x5b,	0x5c,	0x5d,	0x5e,	0x5f,
+	0x60,	0x61,	0x62,	0x63,	0x64,	0x65,	0x66,	0x67,
+	0x68,	0x69,	0x6a,	0x6b,	0x6c,	0x6d,	0x6e,	0x6f,
+	0x70,	0x71,	0x72,	0x73,	0x74,	0x75,	0x76,	0x77,
+	0x78,	0x79,	0x7a,	0x7b,	0x7c,	0x7d,	0x7e,	0x7f,
+	0x80,	0x81,	0x82,	0x83,	0x84,	0x85,	0x86,	0x87,
+	0x88,	0x89,	0x8a,	0x8b,	0x8c,	0x8d,	0x8e,	0x8f,
+	0x90,	0x91,	0x92,	0x93,	0x94,	0x95,	0x96,	0x97,
+	0x98,	0x99,	0x9a,	0x9b,	0x9c,	0x9d,	0x9e,	0x9f,
+	0xa0,	0xa1,	0xa2,	0xa3,	0xa4,	0xa5,	0xa6,	0xa7,
+	0xa8,	0xa9,	0xaa,	0xab,	0xac,	0xad,	0xae,	0xaf,
+	0xb0,	0xb1,	0xb2,	0xb3,	0xb4,	0xb5,	0xb6,	0xb7,
+	0xb8,	0xb9,	0xba,	0xbb,	0xbc,	0xbd,	0xbe,	0xbf,
+	0xc0,	0xc1,	0xc2,	0xc3,	0xc4,	0xc5,	0xc6,	0xc7,
+	0xc8,	0xc9,	0xca,	0xcb,	0xcc,	0xcd,	0xce,	0xcf,
+	0xd0,	0xd1,	0xd2,	0xd3,	0xd4,	0xd5,	0xd6,	0xd7,
+	0xd8,	0xd9,	0xda,	0xdb,	0xdc,	0xdd,	0xde,	0xdf,
+	0xe0,	0xe1,	0xe2,	0xe3,	0xe4,	0xe5,	0xe6,	0xe7,
+	0xe8,	0xe9,	0xea,	0xeb,	0xec,	0xed,	0xee,	0xef,
+	0xf0,	0xf1,	0xf2,	0xf3,	0xf4,	0xf5,	0xf6,	0xf7,
+	0xf8,	0xf9,	0xfa,	0xfb,	0xfc,	0xfd,	0xfe,	0xff
+};
+
+const short *_tolower_tab_ = &_C_tolower_[0];
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/kiconv/toupper_.c src/sys/kiconv/toupper_.c
--- src.orig/sys/kiconv/toupper_.c	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/kiconv/toupper_.c	2011-06-03 15:10:47.000000000 +0900
@@ -0,0 +1,66 @@
+/*	$NetBSD$	*/
+/*	NetBSD: toupper_.c,v 1.13 2010/06/01 13:52:08 tnozaki Exp	*/
+
+/*
+ * Written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_RCS) && !defined(lint)
+__RCSID("NetBSD: toupper_.c,v 1.13 2010/06/01 13:52:08 tnozaki Exp");
+#endif /* LIBC_RCS and not lint */
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/ctype_bits.h>
+#ifdef  _KERNEL
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <kiconv/kiconv.h>
+#else
+#include <stdio.h>
+#endif
+#include "ctype_local.h"
+
+#if EOF != -1
+#error "EOF != -1"
+#endif
+
+const short _C_toupper_[1 + _CTYPE_NUM_CHARS] = {
+	EOF,
+	0x00,	0x01,	0x02,	0x03,	0x04,	0x05,	0x06,	0x07,
+	0x08,	0x09,	0x0a,	0x0b,	0x0c,	0x0d,	0x0e,	0x0f,
+	0x10,	0x11,	0x12,	0x13,	0x14,	0x15,	0x16,	0x17,
+	0x18,	0x19,	0x1a,	0x1b,	0x1c,	0x1d,	0x1e,	0x1f,
+	0x20,	0x21,	0x22,	0x23,	0x24,	0x25,	0x26,	0x27,
+	0x28,	0x29,	0x2a,	0x2b,	0x2c,	0x2d,	0x2e,	0x2f,
+	0x30,	0x31,	0x32,	0x33,	0x34,	0x35,	0x36,	0x37,
+	0x38,	0x39,	0x3a,	0x3b,	0x3c,	0x3d,	0x3e,	0x3f,
+	0x40,	0x41,	0x42,	0x43,	0x44,	0x45,	0x46,	0x47,
+	0x48,	0x49,	0x4a,	0x4b,	0x4c,	0x4d,	0x4e,	0x4f,
+	0x50,	0x51,	0x52,	0x53,	0x54,	0x55,	0x56,	0x57,
+	0x58,	0x59,	0x5a,	0x5b,	0x5c,	0x5d,	0x5e,	0x5f,
+	0x60,	'A',	'B',	'C',	'D',	'E',	'F',	'G',
+	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
+	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
+	'X',	'Y',	'Z',	0x7b,	0x7c,	0x7d,	0x7e,	0x7f,
+	0x80,	0x81,	0x82,	0x83,	0x84,	0x85,	0x86,	0x87,
+	0x88,	0x89,	0x8a,	0x8b,	0x8c,	0x8d,	0x8e,	0x8f,
+	0x90,	0x91,	0x92,	0x93,	0x94,	0x95,	0x96,	0x97,
+	0x98,	0x99,	0x9a,	0x9b,	0x9c,	0x9d,	0x9e,	0x9f,
+	0xa0,	0xa1,	0xa2,	0xa3,	0xa4,	0xa5,	0xa6,	0xa7,
+	0xa8,	0xa9,	0xaa,	0xab,	0xac,	0xad,	0xae,	0xaf,
+	0xb0,	0xb1,	0xb2,	0xb3,	0xb4,	0xb5,	0xb6,	0xb7,
+	0xb8,	0xb9,	0xba,	0xbb,	0xbc,	0xbd,	0xbe,	0xbf,
+	0xc0,	0xc1,	0xc2,	0xc3,	0xc4,	0xc5,	0xc6,	0xc7,
+	0xc8,	0xc9,	0xca,	0xcb,	0xcc,	0xcd,	0xce,	0xcf,
+	0xd0,	0xd1,	0xd2,	0xd3,	0xd4,	0xd5,	0xd6,	0xd7,
+	0xd8,	0xd9,	0xda,	0xdb,	0xdc,	0xdd,	0xde,	0xdf,
+	0xe0,	0xe1,	0xe2,	0xe3,	0xe4,	0xe5,	0xe6,	0xe7,
+	0xe8,	0xe9,	0xea,	0xeb,	0xec,	0xed,	0xee,	0xef,
+	0xf0,	0xf1,	0xf2,	0xf3,	0xf4,	0xf5,	0xf6,	0xf7,
+	0xf8,	0xf9,	0xfa,	0xfb,	0xfc,	0xfd,	0xfe,	0xff
+};
+
+const short *_toupper_tab_ = &_C_toupper_[0];
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/Makefile src/sys/modules/Makefile
--- src.orig/sys/modules/Makefile	2011-10-07 20:42:04.000000000 +0900
+++ src/sys/modules/Makefile	2011-10-07 20:46:08.000000000 +0900
@@ -247,4 +247,31 @@
 SUBDIR+=	emdtv
 .endif
 
+.if (${MKKICONV} != "no")
+SUBDIR+=	kiconv
+SUBDIR+=	kiconv_BIG5
+SUBDIR+=	kiconv_DECHanyu
+SUBDIR+=	kiconv_EUC
+SUBDIR+=	kiconv_EUCTW
+SUBDIR+=	kiconv_GBK2K
+SUBDIR+=	kiconv_HZ
+SUBDIR+=	kiconv_ISO2022
+SUBDIR+=	kiconv_JOHAB
+SUBDIR+=	kiconv_MSKanji
+SUBDIR+=	kiconv_UES
+SUBDIR+=	kiconv_UTF1632
+SUBDIR+=	kiconv_UTF7
+SUBDIR+=	kiconv_UTF8
+SUBDIR+=	kiconv_VIQR
+SUBDIR+=	kiconv_ZW
+SUBDIR+=	kiconv_iconv_none
+SUBDIR+=	kiconv_iconv_std
+SUBDIR+=	kiconv_mapper_646
+SUBDIR+=	kiconv_mapper_none
+SUBDIR+=	kiconv_mapper_serial
+SUBDIR+=	kiconv_mapper_parallel
+SUBDIR+=	kiconv_mapper_std
+SUBDIR+=	kiconv_mapper_zone
+.endif
+
 .include <bsd.subdir.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv/Makefile src/sys/modules/kiconv/Makefile
--- src.orig/sys/modules/kiconv/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv/Makefile	2011-06-04 21:28:32.000000000 +0900
@@ -0,0 +1,41 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/Makefile.inc"
+
+KMOD=	kiconv
+SRCS=	kiconv.c \
+	citrus_bcs.c \
+	citrus_bcs_strtol.c \
+	citrus_bcs_strtoul.c \
+	citrus_csmapper.c \
+	citrus_ctype.c \
+	citrus_ctype_fallback.c \
+	citrus_db.c \
+	citrus_db_hash.c \
+	citrus_esdb.c \
+	citrus_hash.c \
+	citrus_iconv.c \
+	citrus_lc_ctype.c \
+	citrus_lookup.c \
+	citrus_mapper.c \
+	citrus_memstream.c \
+	citrus_mmap.c \
+	citrus_module.c \
+	citrus_none.c \
+	citrus_prop.c \
+	citrus_stdenc.c \
+	\
+	ctype_.c \
+	locale.c \
+	rune.c \
+	runetable.c \
+	tolower_.c \
+	toupper_.c \
+	_wctrans.c \
+	_wctype.c
+
+CPPFLAGS.citrus_bcs_strtol.c+= -I${NETBSDSRCDIR}/common/lib/libc/stdlib
+CPPFLAGS.citrus_bcs_strtoul.c+= -I${NETBSDSRCDIR}/common/lib/libc/stdlib
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_BIG5/Makefile src/sys/modules/kiconv_BIG5/Makefile
--- src.orig/sys/modules/kiconv_BIG5/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_BIG5/Makefile	2011-06-02 20:08:52.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_BIG5
+SRCS=	citrus_big5.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_DECHanyu/Makefile src/sys/modules/kiconv_DECHanyu/Makefile
--- src.orig/sys/modules/kiconv_DECHanyu/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_DECHanyu/Makefile	2011-06-02 20:13:53.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_DECHanyu
+SRCS=	citrus_dechanyu.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_EUC/Makefile src/sys/modules/kiconv_EUC/Makefile
--- src.orig/sys/modules/kiconv_EUC/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_EUC/Makefile	2011-06-01 08:12:55.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_EUC
+SRCS=	citrus_euc.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_EUCTW/Makefile src/sys/modules/kiconv_EUCTW/Makefile
--- src.orig/sys/modules/kiconv_EUCTW/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_EUCTW/Makefile	2011-06-02 20:19:22.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_EUCTW
+SRCS=	citrus_euctw.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_GBK2K/Makefile src/sys/modules/kiconv_GBK2K/Makefile
--- src.orig/sys/modules/kiconv_GBK2K/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_GBK2K/Makefile	2011-06-02 20:22:33.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_GBK2K
+SRCS=	citrus_gbk2k.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_HZ/Makefile src/sys/modules/kiconv_HZ/Makefile
--- src.orig/sys/modules/kiconv_HZ/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_HZ/Makefile	2011-06-02 20:23:59.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_HZ
+SRCS=	citrus_hz.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_ISO2022/Makefile src/sys/modules/kiconv_ISO2022/Makefile
--- src.orig/sys/modules/kiconv_ISO2022/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_ISO2022/Makefile	2011-06-02 20:27:59.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_ISO2022
+SRCS=	citrus_iso2022.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_JOHAB/Makefile src/sys/modules/kiconv_JOHAB/Makefile
--- src.orig/sys/modules/kiconv_JOHAB/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_JOHAB/Makefile	2011-06-02 20:41:40.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_JOHAB
+SRCS=	citrus_johab.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_MSKanji/Makefile src/sys/modules/kiconv_MSKanji/Makefile
--- src.orig/sys/modules/kiconv_MSKanji/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_MSKanji/Makefile	2011-06-01 08:13:09.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_MSKanji
+SRCS=	citrus_mskanji.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_UES/Makefile src/sys/modules/kiconv_UES/Makefile
--- src.orig/sys/modules/kiconv_UES/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_UES/Makefile	2011-06-02 00:16:26.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_UES
+SRCS=	citrus_ues.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_UTF1632/Makefile src/sys/modules/kiconv_UTF1632/Makefile
--- src.orig/sys/modules/kiconv_UTF1632/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_UTF1632/Makefile	2011-06-01 08:13:22.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_UTF1632
+SRCS=	citrus_utf1632.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_UTF7/Makefile src/sys/modules/kiconv_UTF7/Makefile
--- src.orig/sys/modules/kiconv_UTF7/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_UTF7/Makefile	2011-06-02 00:16:54.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_UTF7
+SRCS=	citrus_utf7.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_UTF8/Makefile src/sys/modules/kiconv_UTF8/Makefile
--- src.orig/sys/modules/kiconv_UTF8/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_UTF8/Makefile	2011-06-04 17:21:19.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_UTF8
+SRCS=	citrus_utf8.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_VIQR/Makefile src/sys/modules/kiconv_VIQR/Makefile
--- src.orig/sys/modules/kiconv_VIQR/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_VIQR/Makefile	2011-06-02 20:43:20.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_VIQR
+SRCS=	citrus_viqr.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_ZW/Makefile src/sys/modules/kiconv_ZW/Makefile
--- src.orig/sys/modules/kiconv_ZW/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_ZW/Makefile	2011-06-02 20:46:59.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_ZW
+SRCS=	citrus_zw.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_iconv_none/Makefile src/sys/modules/kiconv_iconv_none/Makefile
--- src.orig/sys/modules/kiconv_iconv_none/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_iconv_none/Makefile	2011-05-31 19:56:36.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_iconv_none
+SRCS=	citrus_iconv_none.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_iconv_std/Makefile src/sys/modules/kiconv_iconv_std/Makefile
--- src.orig/sys/modules/kiconv_iconv_std/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_iconv_std/Makefile	2011-06-04 17:21:08.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_iconv_std
+SRCS=	citrus_iconv_std.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_mapper_646/Makefile src/sys/modules/kiconv_mapper_646/Makefile
--- src.orig/sys/modules/kiconv_mapper_646/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_mapper_646/Makefile	2011-06-01 23:48:06.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_mapper_646
+SRCS=	citrus_mapper_646.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_mapper_none/Makefile src/sys/modules/kiconv_mapper_none/Makefile
--- src.orig/sys/modules/kiconv_mapper_none/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_mapper_none/Makefile	2011-05-31 19:56:55.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_mapper_none
+SRCS=	citrus_mapper_none.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_mapper_parallel/Makefile src/sys/modules/kiconv_mapper_parallel/Makefile
--- src.orig/sys/modules/kiconv_mapper_parallel/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_mapper_parallel/Makefile	2011-06-03 12:12:15.000000000 +0900
@@ -0,0 +1,11 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_mapper_parallel
+SRCS=	citrus_mapper_serial.c
+
+CPPFLAGS+= -DKICONV_MAPPER_ONLY_PARALLEL
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_mapper_serial/Makefile src/sys/modules/kiconv_mapper_serial/Makefile
--- src.orig/sys/modules/kiconv_mapper_serial/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_mapper_serial/Makefile	2011-06-03 12:11:50.000000000 +0900
@@ -0,0 +1,11 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_mapper_serial
+SRCS=	citrus_mapper_serial.c
+
+CPPFLAGS+= -DKICONV_MAPPER_ONLY_SERIAL
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_mapper_std/Makefile src/sys/modules/kiconv_mapper_std/Makefile
--- src.orig/sys/modules/kiconv_mapper_std/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_mapper_std/Makefile	2011-05-31 19:57:08.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_mapper_std
+SRCS=	citrus_mapper_std.c
+
+.include <bsd.kmodule.mk>
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/modules/kiconv_mapper_zone/Makefile src/sys/modules/kiconv_mapper_zone/Makefile
--- src.orig/sys/modules/kiconv_mapper_zone/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ src/sys/modules/kiconv_mapper_zone/Makefile	2011-06-01 23:50:17.000000000 +0900
@@ -0,0 +1,9 @@
+# $NetBSD$
+
+.include "../Makefile.inc"
+.include "../../kiconv/modules/Makefile.inc"
+
+KMOD=	kiconv_mapper_zone
+SRCS=	citrus_mapper_zone.c
+
+.include <bsd.kmodule.mk>
--- src.orig/share/mk/bsd.own.mk	2011-10-07 20:40:15.000000000 +0900
+++ src/share/mk/bsd.own.mk	2011-10-07 20:45:47.000000000 +0900
@@ -842,7 +842,7 @@
 #
 _MKVARS.no= \
 	MKBSDGREP MKBSDTAR MKCRYPTO_IDEA MKCRYPTO_MDC2 MKCRYPTO_RC5 MKDEBUG \
-	MKDEBUGLIB MKDTRACE MKEXTSRC \
+	MKDEBUGLIB MKDTRACE MKEXTSRC MKKICONV \
 	MKMANDOC MKMANZ MKOBJDIRS \
 	MKLLVM MKPCC \
 	MKPIGZGZIP \
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/fs/msdosfs/denode.h src/sys/fs/msdosfs/denode.h
--- src.orig/sys/fs/msdosfs/denode.h	2011-04-15 22:03:11.000000000 +0900
+++ src/sys/fs/msdosfs/denode.h	2011-06-06 19:05:06.000000000 +0900
@@ -287,10 +287,12 @@
 /*
  * Internal service routine prototypes.
  */
+struct msdosfs_winfn;
+
 int msdosfs_update(struct vnode *, const struct timespec *,
 	    const struct timespec *, int);
 int createde(struct denode *, struct denode *,
-		struct denode **, struct componentname *);
+		struct denode **, struct msdosfs_winfn *);
 int deextend(struct denode *, u_long, kauth_cred_t);
 int deget(struct msdosfsmount *, u_long, u_long, struct denode **);
 int detrunc(struct denode *, u_long, int, kauth_cred_t);
@@ -302,7 +304,7 @@
 		struct buf **, struct direntry **);
 void reinsert(struct denode *);
 int removede(struct denode *, struct denode *);
-int uniqdosname(struct denode *, struct componentname *, u_char *);
+int uniqdosname(struct denode *, struct msdosfs_winfn *, u_char *);
 int findwin95(struct denode *);
 int msdosfs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t);
 void msdosfs_gop_markupdate(struct vnode *, int);
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/fs/msdosfs/direntry.h src/sys/fs/msdosfs/direntry.h
--- src.orig/sys/fs/msdosfs/direntry.h	2005-12-04 02:34:43.000000000 +0900
+++ src/sys/fs/msdosfs/direntry.h	2011-09-09 23:37:58.000000000 +0900
@@ -66,7 +66,9 @@
 #define	ATTR_VOLUME	0x08		/* entry is a volume label */
 #define	ATTR_DIRECTORY	0x10		/* entry is a directory name */
 #define	ATTR_ARCHIVE	0x20		/* file is new or modified */
-	u_int8_t	deReserved;	/* reserved */
+	u_int8_t	deLowerCase;	/* NT VFAT lower case flags */
+#define	LCASE_BASE	0x08		/* filename base in lower case */
+#define	LCASE_EXT	0x10		/* filename extension in lower case */
 	u_int8_t	deCHundredth;	/* hundredth of seconds in CTime */
 	u_int8_t	deCTime[2];	/* create time */
 	u_int8_t	deCDate[2];	/* create date */
@@ -121,19 +123,29 @@
 #define DD_YEAR_SHIFT		9
 
 #ifdef _KERNEL
+struct msdosfsmount;
+struct msdosfs_winfn;
+
 void	unix2dostime(const struct timespec *tsp, int gmtoff, u_int16_t *ddp,
 	    u_int16_t *dtp, u_int8_t *dhp);
 void	dos2unixtime(u_int dd, u_int dt, u_int dh, int gmtoff,
 	    struct timespec *tsp);
-int	dos2unixfn(u_char dn[11], u_char *un, int lower);
-int	unix2dosfn(const u_char *un, u_char dn[12], int unlen,
-	    u_int gen);
-int	unix2winfn(const u_char *un, int unlen, struct winentry *wep,
-	    int cnt, int chksum);
-int	winChkName(const u_char *un, int unlen, struct winentry *wep,
-	    int chksum);
-int	win2unixfn(struct winentry *wep, struct dirent *dp, int chksum);
+int	dos2unixfn(u_char dn[11], u_char *un, int lower,
+	    struct msdosfsmount *pmp);
+int	unix2dosfn(struct msdosfs_winfn *fn, u_char dn[12], u_int gen,
+	    struct msdosfsmount *pmp);
+int	unix2winfn(struct msdosfs_winfn *fn, struct winentry *wep,
+	    int cnt, int chksum, struct msdosfsmount *pmp);
+int	winChkName(struct msdosfs_winfn *fn, struct winentry *wep,
+	    int chksum, struct msdosfsmount *pmp);
+int	win2unixfn(struct winentry *wep, struct dirent *dp, int chksum,
+	    struct msdosfsmount *pmp);
 u_int8_t winChksum(u_int8_t *name);
-int	winSlotCnt(const u_char *un, int unlen);
+int	winSlotCnt(struct msdosfs_winfn *fn, struct msdosfsmount *pmp);
+int	newwinfn(struct componentname *cnp, struct msdosfs_winfn **fnp,
+	    struct msdosfsmount *pmp);
+void	freewinfn(struct msdosfs_winfn *fn, struct msdosfsmount *pmp);
+int	msdosfs_initkiconv(struct msdosfsmount *pmp);
+void	msdosfs_finikiconv(struct msdosfsmount *pmp);
 #endif	/* _KERNEL */
 #endif /* _MSDOSFS_DIRENTRY_H_ */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/fs/msdosfs/msdosfs_conv.c src/sys/fs/msdosfs/msdosfs_conv.c
--- src.orig/sys/fs/msdosfs/msdosfs_conv.c	2009-03-16 22:46:39.000000000 +0900
+++ src/sys/fs/msdosfs/msdosfs_conv.c	2011-09-09 23:41:11.000000000 +0900
@@ -59,12 +59,31 @@
 #include <sys/kernel.h>
 #include <sys/dirent.h>
 #include <sys/vnode.h>
+#include <sys/malloc.h>
+#include <sys/namei.h>
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+#include <sys/kiconv.h>
+#endif
 
 /*
  * MSDOSFS include files.
  */
+#include <fs/msdosfs/bpb.h>
 #include <fs/msdosfs/direntry.h>
 #include <fs/msdosfs/denode.h>
+#include <fs/msdosfs/msdosfsmount.h>
+
+struct msdosfs_winfn {
+	const u_char *un;	/* unix filename */
+	int unlen;		/* unix filename length */
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+	u_char *wn;		/* UTF-16LE filename */
+	u_char *lcwn;		/* lower case UTF-16LE filename */
+	int wnlen;		/* win filename length */
+	wchar_t *wcs;
+	int wcslen;
+#endif
+};
 
 /*
  * Days in each month in a regular year.
@@ -338,18 +357,1114 @@
  * extension are not long enough to fill their respective fields.
  */
 
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+struct msdosfs_kiconv {
+	klocale_t l;	/* default locale */
+
+	kiconv_t cih;	/* codepage -> iocharset */
+	kiconv_t cdh;	/* codepage -> default encoding */
+	kiconv_t dch;	/* default encoding -> codepage */
+	kiconv_t idh;	/* iocharset -> default encoding */
+	kiconv_t dih;	/* default encoding -> iocharset */
+	kiconv_t udh;	/* UTF-16LE -> default encoding */
+	kiconv_t duh;	/* default encoding -> UTF-16LE */
+};
+
+int
+msdosfs_initkiconv(struct msdosfsmount *pmp)
+{
+	struct msdosfs_kiconv *fcp;
+	int errno;
+
+	if (pmp->pm_codepage[0] == '\0' || pmp->pm_iocharset[0] == '\0') {
+		pmp->pm_kiconvcookie = NULL;
+		pmp->pm_flags &= ~MSDOSFS_CONVERTFNAME;
+		return 0;
+	}
+
+	fcp = malloc(sizeof(*fcp), M_MSDOSFSTMP, M_WAITOK);
+	fcp->cih = fcp->cdh = fcp->dch = fcp->idh = fcp->dih =
+	    fcp->udh = fcp->duh = (kiconv_t)-1;
+
+	fcp->l = kiconv_newlocale(NULL, &errno);
+
+	fcp->cih = kiconv_open(pmp->pm_iocharset, pmp->pm_codepage, &errno);
+	if (fcp->cih == (kiconv_t)-1)
+		goto error;
+	fcp->cdh = kiconv_open(NULL, pmp->pm_codepage, &errno);
+	if (fcp->cdh == (kiconv_t)-1)
+		goto error;
+	fcp->dch = kiconv_open(pmp->pm_codepage, NULL, &errno);
+	if (fcp->dch == (kiconv_t)-1)
+		goto error;
+	fcp->dih = kiconv_open(pmp->pm_iocharset, NULL, &errno);
+	if (fcp->dih == (kiconv_t)-1)
+		goto error;
+	fcp->idh = kiconv_open(NULL, pmp->pm_iocharset, &errno);
+	if (fcp->idh == (kiconv_t)-1)
+		goto error;
+	fcp->udh = kiconv_open(NULL, "UTF-16LE", &errno);
+	if (fcp->udh == (kiconv_t)-1)
+		goto error;
+	fcp->duh = kiconv_open("UTF-16LE", NULL, &errno);
+	if (fcp->duh == (kiconv_t)-1)
+		goto error;
+
+	pmp->pm_kiconvcookie = fcp;
+	pmp->pm_flags |= MSDOSFS_CONVERTFNAME;
+	return 0;
+
+error:
+	if (fcp->duh != (kiconv_t)-1)
+		kiconv_close(fcp->duh, &errno);
+	if (fcp->udh != (kiconv_t)-1)
+		kiconv_close(fcp->udh, &errno);
+	if (fcp->idh != (kiconv_t)-1)
+		kiconv_close(fcp->idh, &errno);
+	if (fcp->dih != (kiconv_t)-1)
+		kiconv_close(fcp->dih, &errno);
+	if (fcp->dch != (kiconv_t)-1)
+		kiconv_close(fcp->dch, &errno);
+	if (fcp->cdh != (kiconv_t)-1)
+		kiconv_close(fcp->cdh, &errno);
+	if (fcp->cih != (kiconv_t)-1)
+		kiconv_close(fcp->cih, &errno);
+	kiconv_freelocale(fcp->l, &errno);
+	free(fcp, M_MSDOSFSTMP);
+	pmp->pm_kiconvcookie = NULL;
+	pmp->pm_flags &= ~MSDOSFS_CONVERTFNAME;
+	return -1;
+}
+
+void
+msdosfs_finikiconv(struct msdosfsmount *pmp)
+{
+	struct msdosfs_kiconv *fcp = pmp->pm_kiconvcookie;
+	int errno;
+
+	if (fcp) {
+		kiconv_close(fcp->duh, &errno);
+		kiconv_close(fcp->udh, &errno);
+		kiconv_close(fcp->idh, &errno);
+		kiconv_close(fcp->dih, &errno);
+		kiconv_close(fcp->dch, &errno);
+		kiconv_close(fcp->cdh, &errno);
+		kiconv_close(fcp->cih, &errno);
+		kiconv_freelocale(fcp->l, &errno);
+		free(fcp, M_MSDOSFSTMP);
+	}
+}
+#else	/* _RUMPKERNEL || _RUMP_NATIVE_ABI */
+int
+msdosfs_initkiconv(struct msdosfsmount *pmp)
+{
+
+	pmp->pm_kiconvcookie = NULL;
+	pmp->pm_flags &= ~MSDOSFS_CONVERTFNAME;
+	return 0;
+}
+
+/*ARGSUSED*/
+void
+msdosfs_finikiconv(struct msdosfsmount *pmp)
+{
+
+	/* Nothing to do */
+}
+#endif
+
 /*
  * Convert a DOS filename to a unix filename. And, return the number of
  * characters in the resulting unix filename excluding the terminating
  * null.
  */
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+static int
+dos2unixfn_kiconv(u_char dn[11], u_char *un, int lower,
+    struct msdosfsmount *pmp)
+{
+	struct msdosfs_kiconv *fcp = pmp->pm_kiconvcookie;
+	u_char *p, *tmptop;
+	const char *src;
+	char *dst;
+	wchar_t *wtop;
+	const wchar_t *wbuf;
+	size_t szsrc, szdst, szresult;
+	size_t sz, wsz;
+	mbstate_t mbs;
+	int has_ext = 0;
+	int errno;
+	size_t i;
+	int j;
+
+	/*
+	 * If first char of the filename is SLOT_E5 (0x05),
+	 * then the real first char of the filename should
+	 * be 0xe5. But, they couldn't just have a 0xe5
+	 * mean 0xe5 because that is used to mean a freed
+	 * directory slot. Another dos quirk.
+	 */
+	p = un;
+	*p++ = (*dn == SLOT_E5) ? SLOT_DELETED : *dn;
+
+	/*
+	 * Copy the rest into the unix filename string,
+	 * ignoring trailing blanks.
+	 */
+	for (j = 7; (j >= 0) && (dn[j] == ' '); j--)
+		continue;
+
+	for (i = 1; i <= j; i++)
+		*p++ = dn[i];
+	dn += 8;
+
+	/*
+	 * Now, if there is an extension then put in a period
+	 * and copy in the extension.
+	 */
+	if (*dn != ' ') {
+		has_ext = 1;
+		*p++ = '.';
+		for (i = 0; i < 3 && *dn != ' '; i++)
+			*p++ = *dn++;
+	}
+
+	if (!lower || (!(lower & LCASE_BASE) && !has_ext)) {
+		/* fast path */
+
+		/* initialize handle */
+		(void)kiconv_conv(fcp->cih, NULL, NULL, NULL, NULL, &errno);
+
+		/*
+		 * convert from codepage to iocharset
+		 */
+		src = un;
+		szsrc = p - un;
+		dst = tmptop = PNBUF_GET();
+		KASSERT(tmptop != NULL);
+		szdst = MAXNAMLEN + 1;
+		szresult = kiconv_conv(fcp->cih, &src, &szsrc, &dst, &szdst,
+		    &errno);
+		if (szresult == (size_t)-1) {
+			PNBUF_PUT(tmptop);
+			return -1;
+		}
+		sz = MAXNAMLEN + 1 - szdst;
+
+		memcpy(un, tmptop, sz);
+		un[sz] = '\0';
+		PNBUF_PUT(tmptop);
+
+		return sz;
+	}
+	/* slow path */
+
+	/* initialize handle */
+	(void)kiconv_conv(fcp->cdh, NULL, NULL, NULL, NULL, &errno);
+	(void)kiconv_conv(fcp->dih, NULL, NULL, NULL, NULL, &errno);
+
+	/*
+	 * convert from codepage to default encoding.
+	 */
+	src = un;
+	szsrc = p - un;
+	dst = tmptop = PNBUF_GET();
+	KASSERT(tmptop != NULL);
+	szdst = PATH_MAX;
+	szresult = kiconv_conv(fcp->cdh, &src, &szsrc, &dst, &szdst, &errno);
+	if (szresult == (size_t)-1)
+		goto free_tmp;
+	sz = PATH_MAX - szdst;
+	tmptop[sz] = '\0';
+
+	/*
+	 * convert default encoding to wchar_t
+	 */
+	src = tmptop;
+	wtop = WPNBUF_GET();
+	KASSERT(wtop != NULL);
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_mbsrtowcs_l(wtop, &src, PATH_MAX, &mbs, fcp->l,
+	    &errno);
+	if (szresult == (size_t)-1)
+		goto free_wbuf;
+	wsz = szresult;
+	wtop[wsz] = L'\0';
+
+	/*
+	 * tolower
+	 */
+	if (!has_ext) {
+		j = -1;
+		for (i = 0; i < wsz; i++) {
+			if (wtop[i] == L'.')
+				j = i + 1;
+		}
+		if (j < 0)
+			goto no_ext;
+
+		if (lower & LCASE_BASE) {
+			for (i = 0; i < j - 1; i++) {
+				if (kiconv_iswupper_l(wtop[i], fcp->l)) {
+					wtop[i] = kiconv_towlower_l(wtop[i],
+					    fcp->l);
+				}
+			}
+		}
+		if (lower & LCASE_EXT) {
+			for (i = j; i < wsz; i++) {
+				if (kiconv_iswupper_l(wtop[i], fcp->l)) {
+					wtop[i] = kiconv_towlower_l(wtop[i],
+					    fcp->l);
+				}
+			}
+		}
+	} else {
+no_ext:
+		if (lower & LCASE_BASE) {
+			for (i = 0; i < wsz; i++) {
+				if (kiconv_iswupper_l(wtop[i], fcp->l)) {
+					wtop[i] = kiconv_towlower_l(wtop[i],
+					    fcp->l);
+				}
+			}
+		}
+	}
+
+	/*
+	 * convert from wchar_t to default encoding
+	 */
+	wbuf = wtop;
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_wcsrtombs_l(tmptop, &wbuf, PATH_MAX, &mbs, fcp->l,
+	    &errno);
+	if (szresult == (size_t)-1)
+		goto free_wbuf;
+	WPNBUF_PUT(wtop);
+
+	/*
+	 * convert from default encoding to iocharset
+	 */
+	src = tmptop;
+	szsrc = szresult;
+	dst = un;
+	szdst = MAXNAMLEN + 1;
+	szresult = kiconv_conv(fcp->dih, &src, &szsrc, &dst, &szdst, &errno);
+	if (szresult == (size_t)-1)
+		goto free_tmp;
+	PNBUF_PUT(tmptop);
+	sz = MAXNAMLEN + 1 - szdst;
+	un[sz] = '\0';
+
+	return sz;
+
+free_wbuf:
+	WPNBUF_PUT(wtop);
+free_tmp:
+	PNBUF_PUT(tmptop);
+	return -1;
+}
+
+static __inline bool
+is_skip_char(wchar_t wc)
+{
+
+	return (wc == L' ') || (wc == L'.');
+}
+
+static __inline bool
+is_bad_char(wchar_t wc)
+{
+
+	/* XXX: 0x00-0x1f isn't PCS. use iswprint()? */
+	return (wc < 0x20)
+	    || (wc == L'"') || (wc == L'*') || (wc == L'/') || (wc == L':')
+	    || (wc == L'<') || (wc == L'=') || (wc == L'>') || (wc == L'?')
+	    || (wc == L'|') || (wc == L'\\');
+}
+
+static __inline wchar_t
+is_replace_char(wchar_t wc)
+{
+
+	return (wc == L'+') || (wc == L',') || (wc == L';')
+	    || (wc == L'[') || (wc == L']');
+}
+
+static size_t
+to_codepage_char(u_char *top, size_t len, wchar_t wc, int *conv, mbstate_t *mbs,
+    struct msdosfs_kiconv *fcp, int *errnop)
+{
+	u_char buf[MB_LEN_MAX];
+	wchar_t wtop[2];
+	const wchar_t *wbuf;
+	const char *src;
+	char *dst;
+	size_t szsrc, szdst, szresult;
+
+	if (is_skip_char(wc)) {
+		*conv = 3;
+		return 0;
+	}
+
+	if (is_replace_char(wc))
+		goto replace;
+
+	if (kiconv_iswlower_l(wc, fcp->l)) {
+		wc = kiconv_towupper_l(wc, fcp->l);
+		if (*conv != 3)
+			*conv = 2;
+	}
+
+	wtop[0] = wc;
+	wtop[1] = L'\0';
+	wbuf = wtop;
+	szresult = kiconv_wcsrtombs_l(buf, &wbuf, sizeof(buf), mbs, fcp->l,
+	    errnop);
+	if (szresult == (size_t)-1) {
+		memset(mbs, 0, sizeof(*mbs));
+		goto replace;
+	}
+
+	src = buf;
+	szsrc = szresult;
+	dst = top;
+	szdst = len;
+	szresult = kiconv_conv(fcp->dch, &src, &szsrc, &dst, &szdst, errnop);
+	if (szresult == (size_t)-1) {
+		int errno2;
+		(void)kiconv_conv(fcp->dch, NULL, NULL, NULL, NULL, &errno2);
+		goto replace;
+	}
+	return len - szdst;
+
+replace:
+	*conv = 3;
+	top[0] = '_';
+	return 1;
+}
+
+/*
+ * Returns
+ *	0 if name couldn't be converted
+ *	1 if the converted name is the same as the original
+ *	  (no long filename entry necessary for Win95)
+ *	2 if conversion was successful
+ *	3 if conversion was successful and generation number was inserted
+ */
+static int
+unix2dosfn_kiconv(struct msdosfs_winfn *fn, u_char dn[12], u_int gen,
+    struct msdosfsmount *pmp)
+{
+	struct msdosfs_kiconv *fcp = pmp->pm_kiconvcookie;
+	wchar_t *wcs = fn->wcs;
+	size_t wcslen = fn->wcslen;
+	u_char *base = &dn[0], *ext = &dn[8];
+	u_char gentext[6], *wcp;
+	u_char buf[12];
+	int coff[8], ncoff;
+	size_t szresult;
+	mbstate_t mbs;
+	wchar_t wc;
+	int errno;
+	const wchar_t *cp, *ep, *dp, *dp1;
+	int i, j, l;
+	int baselen, extlen;
+	int conv = 1;
+
+	/*
+	 * The filenames "." and ".." are handled specially, since they
+	 * don't follow dos filename rules.
+	 */
+	if (wcslen == 1 && wcs[0] == L'.') {
+		dn[0] = '.';
+		return gen <= 1;
+	}
+	if (wcslen == 2 && wcs[0] == L'.' && wcs[1] == L'.') {
+		dn[0] = '.';
+		dn[1] = '.';
+		return gen <= 1;
+	}
+
+	/*
+	 * Filenames with only blanks and dots are not allowed!
+	 * Also filenames with bad character are not allowed.
+	 */
+	for (cp = wcs, i = wcslen; --i >= 0; cp++) {
+		if (!is_skip_char(*cp)) {
+			if (is_bad_char(*cp))
+				return 0;
+			break;
+		}
+	}
+	if (i < 0)
+		return 0;
+
+	/*
+	 * Now find the extension.
+	 * Note: dot as first char doesn't start extension
+	 *	 and trailing dots and blanks are ignored
+	 */
+	dp = dp1 = NULL;
+	ep = wcs + wcslen;
+	for (cp = wcs + 1, i = wcslen - 1; --i >= 0;) {
+		wc = *cp++;
+		switch (wc) {
+		case L'.':
+			if (dp1 == NULL)
+				dp1 = cp;
+			break;
+		case L' ':
+			break;
+		default:
+			if (dp1) {
+				ep = dp1 - 1;
+				dp = dp1;
+			}
+			dp1 = NULL;
+			break;
+		}
+	}
+	if (dp) {
+		/* In "...test" case, extention as basename and no extention. */
+		for (cp = wcs; cp < dp; cp++) {
+			if (!is_skip_char(*cp))
+				break;
+		}
+		if (cp == dp) {
+			dp = NULL;
+			ep = wcs + wcslen;
+		}
+	}
+
+	/* initialize handle */
+	(void)kiconv_conv(fcp->dch, NULL, NULL, NULL, NULL, &errno);
+
+	/*
+	 * Now convert it
+	 */
+	/* base filename */
+	ncoff = 0;
+	baselen = 0;
+	memset(&mbs, 0, sizeof(mbs));
+	for (cp = wcs; cp < ep; cp++) {
+		szresult = to_codepage_char(buf, sizeof(buf), *cp, &conv, &mbs,
+		    fcp, &errno);
+		if (szresult == 0)
+			continue;
+
+		if (baselen >= 2)
+			coff[ncoff++] = baselen;
+		if (baselen + szresult > 8) {
+			conv = 3;
+			break;
+		}
+		memcpy(base + baselen, buf, szresult);
+		baselen += szresult;
+	}
+	if (baselen == 0)
+		return 0;
+
+	/* ext */
+	extlen = 0;
+	memset(&mbs, 0, sizeof(mbs));
+	if (dp) {
+		if (dp1)
+			l = dp1 - dp;
+		else
+			l = wcslen - (dp - wcs);
+		ep = dp + l;
+		for (cp = dp; cp < ep; cp++) {
+			szresult = to_codepage_char(buf, sizeof(buf), *cp,
+			    &conv, &mbs, fcp, &errno);
+			if (szresult == 0)
+				continue;
+
+			if (extlen + szresult > 3) {
+				conv = 3;
+				break;
+			}
+			memcpy(ext + extlen, buf, szresult);
+			extlen += szresult;
+		}
+	}
+
+	/*
+	 * The first character cannot be E5,
+	 * because that means a deleted entry
+	 */
+	if (base[0] == SLOT_DELETED)
+		base[0] = SLOT_E5;
+
+	/*
+	 * If there wasn't any char dropped,
+	 * there is no place for generation numbers
+	 */
+	if (conv != 3) {
+		if (gen > 1)
+			return 0;
+		return conv;
+	}
+
+	/*
+	 * Now insert the generation number into the filename part
+	 */
+	for (wcp = gentext + sizeof(gentext); wcp > gentext && gen; gen /= 10)
+		*--wcp = gen % 10 + '0';
+	if (gen)
+		return 0;
+	for (i = 8; dn[--i] == ' ';)
+		continue;
+	i++;
+	l = gentext + sizeof(gentext) - wcp + 1;
+	if (l > 8 - i) {
+		i = 8 - l;
+		if (ncoff > 0) {
+			for (j = ncoff; --j >= 0;) {
+				if (l <= 8 - coff[j]) {
+					i = coff[j];
+					break;
+				}
+			}
+			if (j < 0)
+				return 0;
+		}
+	}
+	dn[i++] = '~';
+	while (wcp < gentext + sizeof(gentext))
+		dn[i++] = *wcp++;
+	return 3;
+}
+
+static int
+unix2winfn_kiconv(struct msdosfs_winfn *fn, struct winentry *wep, int cnt,
+    int chksum, struct msdosfsmount *pmp)
+{
+	const u_char *wn = fn->wn;
+	int wnlen = fn->wnlen;
+	int sz;
+	uint8_t *wcp;
+	int i;
+
+	sz = (cnt - 1) * WIN_CHARS;
+	wn += sz * 2;
+	wnlen -= sz;
+
+	/*
+	 * Initialize winentry to some useful default
+	 */
+	memset(wep, 0xff, sizeof(*wep));
+	wep->weCnt = cnt;
+	wep->weAttributes = ATTR_WIN95;
+	wep->weReserved1 = 0;
+	wep->weChksum = chksum;
+	wep->weReserved2 = 0;
+
+	/*
+	 * Now convert the filename parts
+	 */
+	for (wcp = wep->wePart1, i = 0; i < sizeof(wep->wePart1) / 2; i++) {
+		if (--wnlen < 0)
+			goto done;
+		*wcp++ = *wn++;
+		*wcp++ = *wn++;
+	}
+	for (wcp = wep->wePart2, i = 0; i < sizeof(wep->wePart2) / 2; i++) {
+		if (--wnlen < 0)
+			goto done;
+		*wcp++ = *wn++;
+		*wcp++ = *wn++;
+	}
+	for (wcp = wep->wePart3, i = 0; i < sizeof(wep->wePart3) / 2; i++) {
+		if (--wnlen < 0)
+			goto done;
+		*wcp++ = *wn++;
+		*wcp++ = *wn++;
+	}
+	if (wnlen == 0)
+		wep->weCnt |= WIN_LAST;
+	return wnlen;
+
+done:
+	*wcp++ = '\0';
+	*wcp++ = '\0';
+	wep->weCnt |= WIN_LAST;
+	return 0;
+}
+
+static int
+win2unixfn_kiconv(struct winentry *wep, struct dirent *dp, int chksum,
+    struct msdosfsmount *pmp)
+{
+	struct msdosfs_kiconv *fcp = pmp->pm_kiconvcookie;
+	uint8_t buf[sizeof(wep->wePart1) + sizeof(wep->wePart2) + sizeof(wep->wePart3)];
+	char *p, *tmptop, *untop;
+	const char *src;
+	char *dst;
+	wchar_t *wtop;
+	const wchar_t *wbuf;
+	size_t szsrc, szdst, szresult;
+	size_t sz, wsz;
+	mbstate_t mbs;
+	int errno;
+	size_t i;
+
+	/*
+	 * First compare checksums
+	 */
+	if (wep->weCnt & WIN_LAST) {
+		chksum = wep->weChksum;
+		dp->d_namlen = 0;
+	} else if (chksum != wep->weChksum)
+		chksum = -1;
+	if (chksum == -1)
+		goto error;
+
+	p = buf; sz = sizeof(wep->wePart1); memcpy(p, wep->wePart1, sz);
+	p += sz; sz = sizeof(wep->wePart2); memcpy(p, wep->wePart2, sz);
+	p += sz; sz = sizeof(wep->wePart3); memcpy(p, wep->wePart3, sz);
+
+	/* initialize handle */
+	(void)kiconv_conv(fcp->udh, NULL, NULL, NULL, NULL, &errno);
+	(void)kiconv_conv(fcp->dih, NULL, NULL, NULL, NULL, &errno);
+
+	/*
+	 * convert from UTF-16LE to default encoding.
+	 */
+	src = buf;
+	szsrc = sizeof(buf);
+	dst = tmptop = PNBUF_GET();
+	KASSERT(tmptop != NULL);
+	szdst = PATH_MAX;
+	szresult = kiconv_conv(fcp->udh, &src, &szsrc, &dst, &szdst, &errno);
+	if (szresult == (size_t)-1)
+		goto free_tmp;
+	sz = PATH_MAX - szdst;
+	tmptop[sz] = '\0';
+
+	/*
+	 * convert default encoding to wchar_t
+	 */
+	src = tmptop;
+	wtop = WPNBUF_GET();
+	KASSERT(wtop != NULL);
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_mbsrtowcs_l(wtop, &src, PATH_MAX, &mbs, fcp->l,
+	    &errno);
+	if (szresult == (size_t)-1)
+		goto free_wbuf;
+	wsz = szresult;
+	wtop[wsz] = L'\0';
+
+	/*
+	 * Convert the name parts
+	 */
+	for (i = 0; i < wsz; i++) {
+		if (wtop[i] == L'/') {
+			goto free_wbuf;
+		}
+	}
+
+	/*
+	 * convert from wchar_t to default encoding
+	 */
+	wbuf = wtop;
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_wcsrtombs_l(tmptop, &wbuf, sizeof(dp->d_name), &mbs,
+	    fcp->l, &errno);
+	if (szresult == (size_t)-1)
+		goto free_wbuf;
+	WPNBUF_PUT(wtop);
+
+	/*
+	 * convert from default encoding to iocharset
+	 */
+	src = tmptop;
+	szsrc = szresult;
+	dst = untop = PNBUF_GET();
+	KASSERT(untop != NULL);
+	szdst = sizeof(dp->d_name) - dp->d_namlen;
+	szresult = kiconv_conv(fcp->dih, &src, &szsrc, &dst, &szdst, &errno);
+	if (szresult == (size_t)-1) {
+		PNBUF_PUT(untop);
+		goto free_tmp;
+	}
+	PNBUF_PUT(tmptop);
+	sz = sizeof(dp->d_name) - dp->d_namlen - szdst;
+	memmove(dp->d_name + sz, dp->d_name, dp->d_namlen);
+	memcpy(dp->d_name, untop, sz);
+	PNBUF_PUT(untop);
+	dp->d_namlen += sz;
+	dp->d_name[dp->d_namlen] = '\0';
+
+	return chksum;
+
+free_wbuf:
+	WPNBUF_PUT(wtop);
+free_tmp:
+	PNBUF_PUT(tmptop);
+error:
+	return -1;
+}
+
+static int
+winChkName_kiconv(struct msdosfs_winfn *fn, struct winentry *wep, int chksum,
+    struct msdosfsmount *pmp)
+{
+	struct msdosfs_kiconv *fcp = pmp->pm_kiconvcookie;
+	const u_char *wn = fn->lcwn;
+	int wnlen = fn->wnlen;
+	uint8_t buf[sizeof(wep->wePart1) + sizeof(wep->wePart2) + sizeof(wep->wePart3)];
+	u_char *p, *tmptop;
+	const char *src;
+	char *dst;
+	wchar_t *wtop;
+	const wchar_t *wbuf;
+	size_t szsrc, szdst, szresult;
+	size_t sz, wsz;
+	mbstate_t mbs;
+	int errno;
+	size_t i;
+
+	/*
+	 * Offset of this entry
+	 */
+	i = ((wep->weCnt & WIN_CNT) - 1) * WIN_CHARS;
+	wn += i * 2;
+	wnlen -= i;
+	if (wnlen < 0)
+		goto error;
+
+	/*
+	 * Ignore redundant winentries (those with only \0\0 on start in them).
+	 * An appearance of such entry is a bug; unknown if in NetBSD msdosfs
+	 * or MS Windows.
+	 */
+	if (wnlen == 0) {
+		if (wep->wePart1[0] == '\0' && wep->wePart1[1] == '\0')
+			goto done;
+		goto error;
+	}
+
+	if ((wep->weCnt & WIN_LAST) && wnlen > WIN_CHARS)
+		goto error;
+
+	p = buf; sz = sizeof(wep->wePart1); memcpy(p, wep->wePart1, sz);
+	p += sz; sz = sizeof(wep->wePart2); memcpy(p, wep->wePart2, sz);
+	p += sz; sz = sizeof(wep->wePart3); memcpy(p, wep->wePart3, sz);
+
+	/* initialize handle */
+	(void)kiconv_conv(fcp->udh, NULL, NULL, NULL, NULL, &errno);
+	(void)kiconv_conv(fcp->duh, NULL, NULL, NULL, NULL, &errno);
+
+	/*
+	 * convert from UTF-16LE to default encoding.
+	 */
+	src = buf;
+	szsrc = sizeof(buf);
+	dst = tmptop = PNBUF_GET();
+	KASSERT(tmptop != NULL);
+	szdst = PATH_MAX;
+	szresult = kiconv_conv(fcp->udh, &src, &szsrc, &dst, &szdst, &errno);
+	if (szresult == (size_t)-1)
+		goto free_tmp;
+	sz = PATH_MAX - szdst;
+	tmptop[sz] = '\0';
+
+	/*
+	 * convert default encoding to wchar_t
+	 */
+	src = tmptop;
+	wtop = WPNBUF_GET();
+	KASSERT(wtop != NULL);
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_mbsrtowcs_l(wtop, &src, PATH_MAX, &mbs, fcp->l,
+	    &errno);
+	if (szresult == (size_t)-1)
+		goto free_wbuf;
+	wsz = szresult;
+	wtop[wsz] = L'\0';
+
+	/*
+	 * tolower
+	 */
+	for (i = 0; i < wsz; i++) {
+		if (kiconv_iswupper_l(wtop[i], fcp->l)) {
+			wtop[i] = kiconv_towlower_l(wtop[i], fcp->l);
+		}
+	}
+
+	/*
+	 * convert from wchar_t to default encoding (lower-case)
+	 */
+	wbuf = wtop;
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_wcsrtombs_l(tmptop, &wbuf, PATH_MAX, &mbs, fcp->l,
+	    &errno);
+	WPNBUF_PUT(wtop);
+	if (szresult == (size_t)-1)
+		goto free_tmp;
+
+	/*
+	 * convert from default encoding to UTF-16LE (lower-case)
+	 */
+	src = tmptop;
+	szsrc = szresult;
+	dst = buf;
+	szdst = sizeof(buf);
+	szresult = kiconv_conv(fcp->duh, &src, &szsrc, &dst, &szdst, &errno);
+	PNBUF_PUT(tmptop);
+	if (szresult == (size_t)-1)
+		goto error;
+	KASSERT((sizeof(buf) - szdst) == sizeof(buf));
+
+	/*
+	 * Compare the name parts
+	 */
+	sz = min(wnlen, sizeof(buf) / 2);
+	if (memcmp(buf, wn, sz * 2))
+		goto error;
+	wnlen -= sz;
+	wn += sz * 2;
+	if (wnlen == 0 && sz != (sizeof(buf) / 2))
+		if (wn[0] != '\0' || wn[1] != '\0')
+			goto error;
+
+done:
+	return chksum;
+
+free_wbuf:
+	WPNBUF_PUT(wtop);
+free_tmp:
+	PNBUF_PUT(tmptop);
+error:
+	return -1;
+}
+
+static int
+newwinfn_kiconv(struct componentname *cnp, struct msdosfs_winfn **fnp,
+    struct msdosfsmount *pmp)
+{
+	struct msdosfs_kiconv *fcp = pmp->pm_kiconvcookie;
+	struct msdosfs_winfn *fn;
+	char *tmptop, *wintop, *winlctop;
+	const char *src;
+	char *dst;
+	wchar_t *wtop, *wtmp;
+	const wchar_t *wbuf;
+	size_t szsrc, szdst, szresult;
+	size_t sz, lcsz, wsz, orig_wsz;
+	mbstate_t mbs;
+	int errno;
+	int error;
+	size_t i;
+
+	/* initialize handle */
+	(void)kiconv_conv(fcp->idh, NULL, NULL, NULL, NULL, &errno);
+	(void)kiconv_conv(fcp->duh, NULL, NULL, NULL, NULL, &errno);
+
+	/*
+	 * convert from iocharset to default encoding.
+	 */
+	src = (const u_char *)cnp->cn_nameptr;
+	szsrc = cnp->cn_namelen;
+	dst = tmptop = PNBUF_GET();
+	KASSERT(tmptop != NULL);
+	szdst = PATH_MAX;
+	szresult = kiconv_conv(fcp->idh, &src, &szsrc, &dst, &szdst, &errno);
+	if (szresult == (size_t)-1) {
+		error = errno;
+		goto free_tmp;
+	}
+	sz = PATH_MAX - szdst;
+	tmptop[sz] = '\0';
+
+	/*
+	 * convert default encoding to wchar_t
+	 */
+	src = tmptop;
+	wtop = WPNBUF_GET();
+	KASSERT(wtop != NULL);
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_mbsrtowcs_l(wtop, &src, PATH_MAX, &mbs, fcp->l,
+	    &errno);
+	if (szresult == (size_t)-1) {
+		error = errno;
+		goto free_wbuf;
+	}
+	wsz = szresult;
+	wtop[wsz] =L'\0';
+
+	/*
+	 * Drop trailing blanks and dots for namelen
+	 */
+	wtmp = WPNBUF_GET();
+	KASSERT(wtmp != NULL);
+	memcpy(wtmp, wtop, PATH_MAX * sizeof(wchar_t));
+	orig_wsz = wsz;
+	for (wbuf = wtmp + wsz; wsz > 0; wsz--) {
+		if (*--wbuf != L' ' && *wbuf != L'.') {
+			break;
+		}
+	}
+	wtmp[wsz] = L'\0';
+
+	/*
+	 * convert from wchar_t to default encoding for namelen.
+	 */
+	wbuf = wtmp;
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_wcsrtombs_l(tmptop, &wbuf, PATH_MAX, &mbs, fcp->l,
+	    &errno);
+	if (szresult == (size_t)-1) {
+		error = errno;
+		goto free_wtmp;
+	}
+
+	/*
+	 * convert from default encoding to UTF-16LE for namelen
+	 */
+	src = tmptop;
+	szsrc = szresult;
+	dst = wintop = PNBUF_GET();
+	KASSERT(wintop != NULL);
+	szdst = PATH_MAX;
+	szresult = kiconv_conv(fcp->duh, &src, &szsrc, &dst, &szdst, &errno);
+	if (szresult == (size_t)-1) {
+		error = errno;
+		goto free_wintop;
+	}
+	sz = PATH_MAX - szdst;
+	KASSERT((sz % 2) == 0);
+	sz /= 2;
+
+	if (sz > WIN_MAXLEN) {
+		error = ENAMETOOLONG;
+		goto free_wintop;
+	}
+	wsz = orig_wsz;
+
+	/*
+	 * convert from wchar_t to default encoding
+	 */
+	wbuf = wtop;
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_wcsrtombs_l(tmptop, &wbuf, PATH_MAX, &mbs, fcp->l,
+	    &errno);
+	if (szresult == (size_t)-1) {
+		error = errno;
+		goto free_wintop;
+	}
+
+	/*
+	 * convert from default encoding to UTF-16LE
+	 */
+	/* initialize handle */
+	(void)kiconv_conv(fcp->duh, NULL, NULL, NULL, NULL, &errno);
+	src = tmptop;
+	szsrc = szresult;
+	dst = wintop;
+	szdst = PATH_MAX;
+	szresult = kiconv_conv(fcp->duh, &src, &szsrc, &dst, &szdst, &errno);
+	if (szresult == (size_t)-1) {
+		error = errno;
+		goto free_wintop;
+	}
+	sz = PATH_MAX - szdst;
+	KASSERT((sz % 2) == 0);
+	wintop[sz] = wintop[sz + 1] = '\0';
+	sz /= 2;
+
+	/*
+	 * tolower
+	 */
+	memcpy(wtmp, wtop, PATH_MAX * sizeof(wchar_t));
+	for (i = 0; i < wsz; i++) {
+		if (kiconv_iswupper_l(wtmp[i], fcp->l)) {
+			wtmp[i] = kiconv_towlower_l(wtmp[i], fcp->l);
+		}
+	}
+
+	/*
+	 * convert from wchar_t to default encoding (lower-case)
+	 */
+	wbuf = wtmp;
+	memset(&mbs, 0, sizeof(mbs));
+	szresult = kiconv_wcsrtombs_l(tmptop, &wbuf, PATH_MAX, &mbs, fcp->l,
+	    &errno);
+	if (szresult == (size_t)-1) {
+		error = errno;
+		goto free_wintop;
+	}
+
+	/*
+	 * convert from default encoding to UTF-16LE (lower-case)
+	 */
+	/* initialize handle */
+	(void)kiconv_conv(fcp->duh, NULL, NULL, NULL, NULL, &errno);
+	src = tmptop;
+	szsrc = szresult;
+	dst = winlctop = PNBUF_GET();
+	KASSERT(winlctop != NULL);
+	szdst = PATH_MAX;
+	szresult = kiconv_conv(fcp->duh, &src, &szsrc, &dst, &szdst, &errno);
+	if (szresult == (size_t)-1) {
+		error = errno;
+		goto free_winlctop;
+	}
+	lcsz = PATH_MAX - szdst;
+	KASSERT((lcsz % 2) == 0);
+	KASSERT((lcsz / 2) == sz);
+	winlctop[lcsz] = winlctop[lcsz + 1] = '\0';
+
+	WPNBUF_PUT(wtmp);
+	PNBUF_PUT(tmptop);
+
+	fn = malloc(sizeof(*fn), M_MSDOSFSTMP, M_WAITOK);
+	fn->un = (const u_char *)cnp->cn_nameptr;
+	fn->unlen = cnp->cn_namelen;
+	fn->wn = wintop;
+	fn->lcwn = winlctop;
+	fn->wnlen = sz;
+	fn->wcs = wtop;
+	fn->wcslen = wsz;
+
+	*fnp = fn;
+	return 0;
+
+free_winlctop:
+	PNBUF_PUT(winlctop);
+free_wintop:
+	PNBUF_PUT(wintop);
+free_wtmp:
+	WPNBUF_PUT(wtmp);
+free_wbuf:
+	WPNBUF_PUT(wtop);
+free_tmp:
+	PNBUF_PUT(tmptop);
+	return error;
+}
+#endif
+
 int
-dos2unixfn(u_char dn[11], u_char *un, int lower)
+dos2unixfn(u_char dn[11], u_char *un, int lower, struct msdosfsmount *pmp)
 {
 	int i, j;
-	int thislong = 1;
+	int thislong;
 	u_char c;
 
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+	if (pmp->pm_flags & MSDOSFS_CONVERTFNAME) {
+		thislong = dos2unixfn_kiconv(dn, un, lower, pmp);
+		if (thislong >= 0)
+			return thislong;
+		/*FALLTHROUGH*/
+		printf("%s: warning: filename convertion failure.\n", __func__);
+	}
+#endif
+
+	thislong = 1;
+
 	/*
 	 * If first char of the filename is SLOT_E5 (0x05), then the real
 	 * first char of the filename should be 0xe5. But, they couldn't
@@ -357,10 +1472,10 @@
 	 * directory slot. Another dos quirk.
 	 */
 	if (*dn == SLOT_E5)
-		c = dos2unix[0xe5];
+		c = dos2unix[SLOT_DELETED];
 	else
 		c = dos2unix[*dn];
-	*un++ = lower ? u2l[c] : c;
+	*un++ = (lower & LCASE_BASE) ? u2l[c] : c;
 
 	/*
 	 * Copy the rest into the unix filename string, ignoring
@@ -372,7 +1487,7 @@
 
 	for (i = 1; i <= j; i++) {
 		c = dos2unix[dn[i]];
-		*un++ = lower ? u2l[c] : c;
+		*un++ = (lower & LCASE_BASE) ? u2l[c] : c;
 		thislong++;
 	}
 	dn += 8;
@@ -386,7 +1501,7 @@
 		thislong++;
 		for (i = 0; i < 3 && *dn != ' '; i++) {
 			c = dos2unix[*dn++];
-			*un++ = lower ? u2l[c] : c;
+			*un++ = (lower & LCASE_EXT) ? u2l[c] : c;
 			thislong++;
 		}
 	}
@@ -407,8 +1522,11 @@
  *	3 if conversion was successful and generation number was inserted
  */
 int
-unix2dosfn(const u_char *un, u_char dn[12], int unlen, u_int gen)
+unix2dosfn(struct msdosfs_winfn *fn, u_char dn[12], u_int gen,
+    struct msdosfsmount *pmp)
 {
+	const u_char *un = fn->un;
+	int unlen = fn->unlen;
 	int i, j, l;
 	int conv = 1;
 	const u_char *cp, *dp, *dp1;
@@ -423,6 +1541,11 @@
 		dn[i] = ' ';
 	dn[11] = 0;
 
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+	if (pmp->pm_flags & MSDOSFS_CONVERTFNAME)
+		return unix2dosfn_kiconv(fn, dn, gen, pmp);
+#endif
+
 	/*
 	 * The filenames "." and ".." are handled specially, since they
 	 * don't follow dos filename rules.
@@ -524,7 +1647,7 @@
 	 * The first character cannot be E5,
 	 * because that means a deleted entry
 	 */
-	if (dn[0] == 0xe5)
+	if (dn[0] == SLOT_DELETED)
 		dn[0] = SLOT_E5;
 
 	/*
@@ -560,12 +1683,23 @@
  *	 i.e. doesn't consist solely of blanks and dots
  */
 int
-unix2winfn(const u_char *un, int unlen, struct winentry *wep, int cnt, int chksum)
+unix2winfn(struct msdosfs_winfn *fn, struct winentry *wep, int cnt, int chksum,
+    struct msdosfsmount *pmp)
 {
+	const u_char *un;
+	int unlen;
 	const u_int8_t *cp;
 	u_int8_t *wcp;
 	int i;
 
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+	if (pmp->pm_flags & MSDOSFS_CONVERTFNAME)
+		return unix2winfn_kiconv(fn, wep, cnt, chksum, pmp);
+#endif
+
+	un = fn->un;
+	unlen = fn->unlen;
+
 	/*
 	 * Drop trailing blanks and dots
 	 */
@@ -621,8 +1755,11 @@
  * Returns the checksum or -1 if no match
  */
 int
-winChkName(const u_char *un, int unlen, struct winentry *wep, int chksum)
+winChkName(struct msdosfs_winfn *fn, struct winentry *wep, int chksum,
+    struct msdosfsmount *pmp)
 {
+	const u_char *un;
+	int unlen;
 	u_int8_t *cp;
 	int i;
 
@@ -636,9 +1773,16 @@
 	if (chksum == -1)
 		return -1;
 
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+	if (pmp->pm_flags & MSDOSFS_CONVERTFNAME)
+		return winChkName_kiconv(fn, wep, chksum, pmp);
+#endif
+
 	/*
 	 * Offset of this entry
 	 */
+	un = fn->un;
+	unlen = fn->unlen;
 	i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS;
 	un += i;
 	if ((unlen -= i) < 0)
@@ -697,16 +1841,22 @@
  * Returns the checksum or -1 if impossible
  */
 int
-win2unixfn(struct winentry *wep, struct dirent *dp, int chksum)
+win2unixfn(struct winentry *wep, struct dirent *dp, int chksum,
+    struct msdosfsmount *pmp)
 {
 	u_int8_t *cp;
-	u_int8_t *np, *ep = dp->d_name + WIN_MAXLEN;
+	u_int8_t *np, *ep;
 	int i;
 
 	if ((wep->weCnt&WIN_CNT) > howmany(WIN_MAXLEN, WIN_CHARS)
 	    || !(wep->weCnt&WIN_CNT))
 		return -1;
 
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+	if (pmp->pm_flags & MSDOSFS_CONVERTFNAME)
+		return win2unixfn_kiconv(wep, dp, chksum, pmp);
+#endif
+
 	/*
 	 * First compare checksums
 	 */
@@ -726,6 +1876,7 @@
 	 */
 	i = ((wep->weCnt&WIN_CNT) - 1) * WIN_CHARS;
 	np = (u_int8_t *)dp->d_name + i;
+	ep = dp->d_name + WIN_MAXLEN;
 
 	/*
 	 * Convert the name parts
@@ -814,12 +1965,64 @@
  * Determine the number of slots necessary for Win95 names
  */
 int
-winSlotCnt(const u_char *un, int unlen)
+winSlotCnt(struct msdosfs_winfn *fn, struct msdosfsmount *pmp)
+{
+
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+	if (pmp->pm_flags & MSDOSFS_CONVERTFNAME)
+		return howmany(fn->wnlen, WIN_CHARS);
+#endif
+	return howmany(fn->unlen, WIN_CHARS);
+}
+
+int
+newwinfn(struct componentname *cnp, struct msdosfs_winfn **fnp,
+    struct msdosfsmount *pmp)
 {
+	struct msdosfs_winfn *fn;
+	const u_char *un;
+	int unlen;
+
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+	if (pmp->pm_flags & MSDOSFS_CONVERTFNAME)
+		return newwinfn_kiconv(cnp, fnp, pmp);
+#endif
+
+	un = (const u_char *)cnp->cn_nameptr;
+	unlen = cnp->cn_namelen;
 	for (un += unlen; unlen > 0; unlen--)
 		if (*--un != ' ' && *un != '.')
 			break;
 	if (unlen > WIN_MAXLEN)
-		return 0;
-	return howmany(unlen, WIN_CHARS);
+		return ENAMETOOLONG;
+
+	fn = malloc(sizeof(*fn), M_MSDOSFSTMP, M_WAITOK);
+	fn->un = (const u_char *)cnp->cn_nameptr;
+	fn->unlen = cnp->cn_namelen;
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+	fn->wn = fn->lcwn = NULL;
+	fn->wnlen = 0;
+	fn->wcs = NULL;
+	fn->wcslen = 0;
+#endif
+
+	*fnp = fn;
+	return 0;
+}
+
+void
+freewinfn(struct msdosfs_winfn *fn, struct msdosfsmount *pmp)
+{
+
+	if (fn) {
+#if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI)
+		if (fn->wn)
+			PNBUF_PUT(fn->wn);
+		if (fn->lcwn)
+			PNBUF_PUT(fn->lcwn);
+		if (fn->wcs)
+			WPNBUF_PUT(fn->wcs);
+#endif
+		free(fn, M_MSDOSFSTMP);
+	}
 }
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/fs/msdosfs/msdosfs_lookup.c src/sys/fs/msdosfs/msdosfs_lookup.c
--- src.orig/sys/fs/msdosfs/msdosfs_lookup.c	2010-12-11 17:59:45.000000000 +0900
+++ src/sys/fs/msdosfs/msdosfs_lookup.c	2011-06-07 00:10:35.000000000 +0900
@@ -109,6 +109,7 @@
 	struct buf *bp = 0;
 	struct direntry *dep;
 	u_char dosfilename[12];
+	struct msdosfs_winfn *fn = NULL;
 	int flags;
 	int nameiop = cnp->cn_nameiop;
 	int wincnt = 1;
@@ -133,11 +134,13 @@
 	 * Check accessiblity of directory.
 	 */
 	if ((error = VOP_ACCESS(vdp, VEXEC, cnp->cn_cred)) != 0)
-		return (error);
+		goto error;
 
 	if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
-	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
-		return (EROFS);
+	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
+		error = EROFS;
+		goto error;
+	}
 
 	/*
 	 * We now have a segment name to search for, and a directory to search.
@@ -147,7 +150,7 @@
 	 * we are looking for is known already.
 	 */
 	if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
-		return (error);
+		goto error;
 
 	/*
 	 * If they are going after the . or .. entry in the root directory,
@@ -167,20 +170,22 @@
 		goto foundroot;
 	}
 
-	switch (unix2dosfn((const u_char *)cnp->cn_nameptr, dosfilename,
-	    cnp->cn_namelen, 0)) {
+	error = newwinfn(cnp, &fn, pmp);
+	if (error)
+		goto error;
+
+	switch (unix2dosfn(fn, dosfilename, 0, pmp)) {
 	case 0:
-		return (EINVAL);
+		error = EINVAL;
+		goto error;
 	case 1:
 		break;
 	case 2:
-		wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
-		    cnp->cn_namelen) + 1;
+		wincnt = winSlotCnt(fn, pmp) + 1;
 		break;
 	case 3:
 		olddos = 0;
-		wincnt = winSlotCnt((const u_char *)cnp->cn_nameptr,
-		    cnp->cn_namelen) + 1;
+		wincnt = winSlotCnt(fn, pmp) + 1;
 		break;
 	}
 	if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
@@ -217,13 +222,13 @@
 		if ((error = pcbmap(dp, frcn, &bn, &cluster, &blsize)) != 0) {
 			if (error == E2BIG)
 				break;
-			return (error);
+			goto error;
 		}
 		error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, NOCRED,
 		    0, &bp);
 		if (error) {
 			brelse(bp, 0);
-			return (error);
+			goto error;
 		}
 		for (blkoff = 0; blkoff < blsize;
 		     blkoff += sizeof(struct direntry),
@@ -268,10 +273,9 @@
 					if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
 						continue;
 
-					chksum = winChkName((const u_char *)cnp->cn_nameptr,
-							    cnp->cn_namelen,
-							    (struct winentry *)dep,
-							    chksum);
+					chksum = winChkName(fn,
+					    (struct winentry *)dep,
+					    chksum, pmp);
 					continue;
 				}
 
@@ -351,7 +355,7 @@
 		 */
 		error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred);
 		if (error)
-			return (error);
+			goto error;
 
 		/*
 		 * Fixup the slot description to point to the place where
@@ -385,7 +389,8 @@
 		 * NB - if the directory is unlocked, then this
 		 * information cannot be used.
 		 */
-		return (EJUSTRETURN);
+		error = EJUSTRETURN;
+		goto error;
 	}
 
 #if 0
@@ -403,7 +408,8 @@
 		cache_enter(vdp, *vpp, cnp);
 #endif
 
-	return (ENOENT);
+	error = ENOENT;
+	goto error;
 
 found:
 	/*
@@ -457,15 +463,17 @@
 		/*
 		 * Don't allow deleting the root.
 		 */
-		if (blkoff == MSDOSFSROOT_OFS)
-			return EINVAL;
+		if (blkoff == MSDOSFSROOT_OFS) {
+			error = EINVAL;
+			goto error;
+		}
 
 		/*
 		 * Write access to directory required to delete files.
 		 */
 		error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred);
 		if (error)
-			return (error);
+			goto error;
 
 		/*
 		 * Return pointer to current entry in dp->i_offset.
@@ -474,12 +482,12 @@
 		if (dp->de_StartCluster == scn && isadir) {	/* "." */
 			vref(vdp);
 			*vpp = vdp;
-			return (0);
+			goto done;
 		}
 		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
-			return (error);
+			goto error;
 		*vpp = DETOV(tdp);
-		return (0);
+		goto done;
 	}
 
 	/*
@@ -490,27 +498,33 @@
 	 */
 	if (nameiop == RENAME && (flags & ISLASTCN)) {
 
-		if (vdp->v_mount->mnt_flag & MNT_RDONLY)
-			return (EROFS);
+		if (vdp->v_mount->mnt_flag & MNT_RDONLY) {
+			error = EROFS;
+			goto error;
+		}
 
-		if (blkoff == MSDOSFSROOT_OFS)
-			return EINVAL;
+		if (blkoff == MSDOSFSROOT_OFS) {
+			error = EINVAL;
+			goto error;
+		}
 
 		error = VOP_ACCESS(vdp, VWRITE, cnp->cn_cred);
 		if (error)
-			return (error);
+			goto error;
 
 		/*
 		 * Careful about locking second inode.
 		 * This can only occur if the target is ".".
 		 */
-		if (dp->de_StartCluster == scn && isadir)
-			return (EISDIR);
+		if (dp->de_StartCluster == scn && isadir) {
+			error = EISDIR;
+			goto error;
+		}
 
 		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
-			return (error);
+			goto error;
 		*vpp = DETOV(tdp);
-		return (0);
+		goto done;
 	}
 
 	/*
@@ -537,16 +551,15 @@
 		VOP_UNLOCK(pdp);	/* race to get the inode */
 		error = deget(pmp, cluster, blkoff, &tdp);
 		vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY);
-		if (error) {
-			return error;
-		}
+		if (error) 
+			goto error;
 		*vpp = DETOV(tdp);
 	} else if (dp->de_StartCluster == scn && isadir) {
 		vref(vdp);	/* we want ourself, ie "." */
 		*vpp = vdp;
 	} else {
 		if ((error = deget(pmp, cluster, blkoff, &tdp)) != 0)
-			return (error);
+			goto error;
 		*vpp = DETOV(tdp);
 	}
 
@@ -556,7 +569,13 @@
 	if (cnp->cn_flags & MAKEENTRY)
 		cache_enter(vdp, *vpp, cnp);
 
+done:
+	freewinfn(fn, pmp);
 	return (0);
+
+error:
+	freewinfn(fn, pmp);
+	return error;
 }
 
 /*
@@ -564,10 +583,10 @@
  * ddep - directory to add to
  * depp - return the address of the denode for the created directory entry
  *	  if depp != 0
- * cnp  - componentname needed for Win95 long filenames
+ * fn   - componentname needed for Win95 long filenames
  */
 int
-createde(struct denode *dep, struct denode *ddep, struct denode **depp, struct componentname *cnp)
+createde(struct denode *dep, struct denode *ddep, struct denode **depp, struct msdosfs_winfn *fn)
 {
 	int error, rberror;
 	u_long dirclust, clusoffset;
@@ -580,8 +599,8 @@
 	int async = ddep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC;
 
 #ifdef MSDOSFS_DEBUG
-	printf("createde(dep %p, ddep %p, depp %p, cnp %p)\n",
-	    dep, ddep, depp, cnp);
+	printf("createde(dep %p, ddep %p, depp %p, fn %p)\n",
+	    dep, ddep, depp, fn);
 #endif
 
 	/*
@@ -633,8 +652,6 @@
 	 */
 	if (ddep->de_fndcnt > 0) {
 		u_int8_t chksum = winChksum(ndep->deName);
-		const u_char *un = (const u_char *)cnp->cn_nameptr;
-		int unlen = cnp->cn_namelen;
 		u_long xhavecnt;
 
 		fndoffset = ddep->de_fndoffset;
@@ -669,8 +686,8 @@
 				ndep--;
 				fndoffset -= sizeof(struct direntry);
 			}
-			if (!unix2winfn(un, unlen, (struct winentry *)ndep,
-						wcnt, chksum))
+			if (!unix2winfn(fn, (struct winentry *)ndep,
+						wcnt, chksum, pmp))
 				break;
 		}
 	}
@@ -1045,7 +1062,7 @@
  * Create a unique DOS name in dvp
  */
 int
-uniqdosname(struct denode *dep, struct componentname *cnp, u_char *cp)
+uniqdosname(struct denode *dep, struct msdosfs_winfn *fn, u_char *cp)
 {
 	struct msdosfsmount *pmp = dep->de_pmp;
 	struct direntry *dentp;
@@ -1060,8 +1077,7 @@
 		/*
 		 * Generate DOS name with generation number
 		 */
-		if (!unix2dosfn((const u_char *)cnp->cn_nameptr, cp,
-		    cnp->cn_namelen, gen))
+		if (!unix2dosfn(fn, cp, gen, pmp))
 			return gen == 1 ? EINVAL : EEXIST;
 
 		/*
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/fs/msdosfs/msdosfs_vfsops.c src/sys/fs/msdosfs/msdosfs_vfsops.c
--- src.orig/sys/fs/msdosfs/msdosfs_vfsops.c	2011-10-07 20:41:58.000000000 +0900
+++ src/sys/fs/msdosfs/msdosfs_vfsops.c	2011-10-07 20:46:07.000000000 +0900
@@ -200,6 +200,8 @@
 	pmp->pm_gmtoff = argp->gmtoff;
 	pmp->pm_flags |= argp->flags & MSDOSFSMNT_MNTOPT;
 
+	/* XXX: XXXNONAKA update codepage/iocharset */
+
 	/*
 	 * GEMDOS knows nothing about win95 long filenames
 	 */
@@ -254,6 +256,8 @@
 	args.mask = 0777;
 	args.version = MSDOSFSMNT_VERSION;
 	args.dirmask = 0777;
+	args.codepage[0] = '\0';
+	args.iocharset[0] = '\0';
 
 	if ((error = msdosfs_mountfs(rootvp, mp, l, &args)) != 0) {
 		vfs_unbusy(mp, false, NULL);
@@ -308,6 +312,10 @@
 		args->version = MSDOSFSMNT_VERSION;
 		args->dirmask = pmp->pm_dirmask;
 		args->gmtoff = pmp->pm_gmtoff;
+		strlcpy(args->codepage, pmp->pm_codepage,
+		    sizeof(args->codepage));
+		strlcpy(args->iocharset, pmp->pm_iocharset,
+		    sizeof(args->iocharset));
 		*data_len = sizeof *args;
 		return 0;
 	}
@@ -328,6 +336,14 @@
 		args->gmtoff = 0;
 
 	/*
+	 * Unset codepage/iocharset for pre-v4 mount structure args.
+	 */
+	if (args->version < 4) {
+		args->codepage[0] = '\0';
+		args->iocharset[0] = '\0';
+	}
+
+	/*
 	 * If updating, check whether changing from read-only to
 	 * read/write; if there is no device name, that's all we do.
 	 */
@@ -796,6 +812,19 @@
 		pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;
 
 	/*
+	 * Copy codepage/iocharset args.
+	 */
+	strlcpy(pmp->pm_codepage, argp->codepage, sizeof(pmp->pm_codepage));
+	strlcpy(pmp->pm_iocharset, argp->iocharset, sizeof(pmp->pm_iocharset));
+	if (msdosfs_initkiconv(pmp)) {
+		/* Disable filename convertion */
+		pmp->pm_flags &= ~MSDOSFS_CONVERTFNAME;
+		printf("warning: filename convertion is disabled. "
+		    "(codepage=%s, iocharset=%s)\n",
+		    pmp->pm_codepage, pmp->pm_iocharset);
+	}
+
+	/*
 	 * Finish up.
 	 */
 	if (ronly)
@@ -888,6 +917,7 @@
 	    pmp->pm_flags & MSDOSFSMNT_RONLY ? FREAD : FREAD|FWRITE, NOCRED);
 	vput(pmp->pm_devvp);
 	msdosfs_fh_destroy(pmp);
+	msdosfs_finikiconv(pmp);
 	free(pmp->pm_inusemap, M_MSDOSFSFAT);
 	free(pmp, M_MSDOSFSMNT);
 	mp->mnt_data = NULL;
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/fs/msdosfs/msdosfs_vnops.c src/sys/fs/msdosfs/msdosfs_vnops.c
--- src.orig/sys/fs/msdosfs/msdosfs_vnops.c	2011-07-20 21:30:30.000000000 +0900
+++ src/sys/fs/msdosfs/msdosfs_vnops.c	2011-07-20 21:38:46.000000000 +0900
@@ -114,6 +114,8 @@
 	struct denode ndirent;
 	struct denode *dep;
 	struct denode *pdep = VTODE(ap->a_dvp);
+	struct msdosfsmount *pmp = pdep->de_pmp;
+	struct msdosfs_winfn *fn = NULL;
 	int error;
 
 #ifdef MSDOSFS_DEBUG
@@ -138,8 +140,10 @@
 	 * use the absence of the owner write bit to make the file
 	 * readonly.
 	 */
+	if ((error = newwinfn(cnp, &fn, pmp)) != 0)
+		goto bad;
 	memset(&ndirent, 0, sizeof(ndirent));
-	if ((error = uniqdosname(pdep, cnp, ndirent.de_Name)) != 0)
+	if ((error = uniqdosname(pdep, fn, ndirent.de_Name)) != 0)
 		goto bad;
 
 	ndirent.de_Attributes = (ap->a_vap->va_mode & S_IWUSR) ?
@@ -151,8 +155,9 @@
 	ndirent.de_pmp = pdep->de_pmp;
 	ndirent.de_flag = DE_ACCESS | DE_CREATE | DE_UPDATE;
 	DETIMES(&ndirent, NULL, NULL, NULL, pdep->de_pmp->pm_gmtoff);
-	if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0)
+	if ((error = createde(&ndirent, pdep, &dep, fn)) != 0)
 		goto bad;
+	freewinfn(fn, pmp);
 	fstrans_done(ap->a_dvp->v_mount);
 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
 	vput(ap->a_dvp);
@@ -160,6 +165,7 @@
 	return (0);
 
 bad:
+	freewinfn(fn, pmp);
 	fstrans_done(ap->a_dvp->v_mount);
 	vput(ap->a_dvp);
 	return (error);
@@ -835,6 +841,7 @@
 	struct msdosfsmount *pmp;
 	struct direntry *dotdotp;
 	struct buf *bp;
+	struct msdosfs_winfn *tfn = NULL;
 
 	pmp = VFSTOMSDOSFS(fdvp->v_mount);
 
@@ -985,7 +992,9 @@
 	 * into the denode and directory entry for the destination
 	 * file/directory.
 	 */
-	if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) {
+	if ((error = newwinfn(tcnp, &tfn, pmp)) != 0)
+		goto abortit;
+	if ((error = uniqdosname(VTODE(tdvp), tfn, toname)) != 0) {
 		fstrans_done(fdvp->v_mount);
 		goto abortit;
 	}
@@ -1002,8 +1011,7 @@
 		VOP_UNLOCK(fdvp);
 		vrele(ap->a_fvp);
 		vrele(tdvp);
-		fstrans_done(fdvp->v_mount);
-		return (error);
+		goto out;
 	}
 	if (fvp == NULL) {
 		/*
@@ -1014,8 +1022,8 @@
 		vput(fdvp);
 		vrele(ap->a_fvp);
 		vrele(tdvp);
-		fstrans_done(fdvp->v_mount);
-		return 0;
+		error = 0;
+		goto out;
 	}
 	VOP_UNLOCK(fdvp);
 	xp = VTODE(fvp);
@@ -1051,7 +1059,7 @@
 		memcpy(ip->de_Name, toname, 11);	/* update denode */
 		dp->de_fndoffset = to_diroffset;
 		dp->de_fndcnt = to_count;
-		error = createde(ip, dp, (struct denode **)0, tcnp);
+		error = createde(ip, dp, (struct denode **)0, tfn);
 		if (error) {
 			memcpy(ip->de_Name, oldname, 11);
 			VOP_UNLOCK(fvp);
@@ -1123,6 +1131,8 @@
 	ip->de_flag &= ~DE_RENAME;
 	vrele(fdvp);
 	vrele(fvp);
+out:
+	freewinfn(tfn, pmp);
 	fstrans_done(fdvp->v_mount);
 	return (error);
 
@@ -1179,6 +1189,7 @@
 	struct msdosfsmount *pmp = pdep->de_pmp;
 	struct buf *bp;
 	int async = pdep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC;
+	struct msdosfs_winfn *fn = NULL;
 
 	fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED);
 	/*
@@ -1251,7 +1262,9 @@
 	 * cluster.  This will be written to an empty slot in the parent
 	 * directory.
 	 */
-	if ((error = uniqdosname(pdep, cnp, ndirent.de_Name)) != 0)
+	if ((error = newwinfn(cnp, &fn, pmp)) != 0)
+		goto bad;
+	if ((error = uniqdosname(pdep, fn, ndirent.de_Name)) != 0)
 		goto bad;
 
 	ndirent.de_Attributes = ATTR_DIRECTORY;
@@ -1259,11 +1272,12 @@
 	ndirent.de_FileSize = 0;
 	ndirent.de_dev = pdep->de_dev;
 	ndirent.de_devvp = pdep->de_devvp;
-	if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0)
+	if ((error = createde(&ndirent, pdep, &dep, fn)) != 0)
 		goto bad;
 	VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK);
 	vput(ap->a_dvp);
 	*ap->a_vpp = DETOV(dep);
+	freewinfn(fn, pmp);
 	fstrans_done(ap->a_dvp->v_mount);
 	return (0);
 
@@ -1271,6 +1285,7 @@
 	clusterfree(pmp, newcluster, NULL);
 bad2:
 	vput(ap->a_dvp);
+	freewinfn(fn, pmp);
 	fstrans_done(ap->a_dvp->v_mount);
 	return (error);
 }
@@ -1526,7 +1541,7 @@
 				if (pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
 					continue;
 				chksum = win2unixfn((struct winentry *)dentp,
-				    dirbuf, chksum);
+				    dirbuf, chksum, pmp);
 				continue;
 			}
 
@@ -1566,7 +1581,10 @@
 			if (chksum != winChksum(dentp->deName))
 				dirbuf->d_namlen = dos2unixfn(dentp->deName,
 				    (u_char *)dirbuf->d_name,
-				    pmp->pm_flags & MSDOSFSMNT_SHORTNAME);
+				    dentp->deLowerCase |
+				      ((pmp->pm_flags & MSDOSFSMNT_SHORTNAME)
+				        ? (LCASE_BASE | LCASE_EXT) : 0),
+				    pmp);
 			else
 				dirbuf->d_name[dirbuf->d_namlen] = 0;
 			chksum = -1;
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sys/fs/msdosfs/msdosfsmount.h src/sys/fs/msdosfs/msdosfsmount.h
--- src.orig/sys/fs/msdosfs/msdosfsmount.h	2008-07-05 09:24:57.000000000 +0900
+++ src/sys/fs/msdosfs/msdosfsmount.h	2011-09-09 23:38:38.000000000 +0900
@@ -63,9 +63,11 @@
 
 	/* Following items added after versioning support */
 	int	version;	/* version of the struct */
-#define MSDOSFSMNT_VERSION	3
+#define MSDOSFSMNT_VERSION	4
 	mode_t  dirmask;	/* v2: mask to be applied for msdosfs perms */
 	int	gmtoff;		/* v3: offset from UTC in seconds */
+	char	codepage[32];	/* v4: short filename codepage */
+	char	iocharset[32];	/* v4: user-visible filename encoding */
 };
 
 /*
@@ -84,11 +86,12 @@
 
 #define	MSDOSFSMNT_RONLY	0x80000000	/* mounted read-only	*/
 #define	MSDOSFSMNT_WAITONFAT	0x40000000	/* mounted synchronous	*/
-#define	MSDOSFS_FATMIRROR	0x20000000	/* FAT is mirrored */
+#define	MSDOSFS_FATMIRROR	0x20000000	/* FAT is mirrored	*/
+#define	MSDOSFS_CONVERTFNAME	0x10000000	/* convert filename	*/
 
 #define MSDOSFSMNT_BITS "\177\20" \
     "b\00shortname\0b\01longname\0b\02nowin95\0b\03gemdosfs\0b\04mntversioned\0" \
-    "b\037ronly\0b\036waitonfat\0b\035fatmirror\0"
+    "b\037ronly\0b\036waitonfat\0b\035fatmirror\0b\034convertfname\0"
 
 #ifdef _KERNEL
 #include <sys/mallocvar.h>
@@ -133,6 +136,9 @@
 	u_int pm_fatdiv;	/*	offset computation */
 	u_int pm_curfat;	/* current fat for FAT32 (0 otherwise) */
 	u_int *pm_inusemap;	/* ptr to bitmap of in-use clusters */
+	char pm_codepage[32];	/* short filename codepage */
+	char pm_iocharset[32];	/* user-visible filename encoding */
+	void *pm_kiconvcookie;	/* cookie of convert filename */
 	u_int pm_flags;		/* see below */
 };
 /* Byte offset in FAT on filesystem pmp, cluster cn */
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sbin/mount_msdos/mount_msdos.8 src/sbin/mount_msdos/mount_msdos.8
--- src.orig/sbin/mount_msdos/mount_msdos.8	2011-09-29 23:02:59.000000000 +0900
+++ src/sbin/mount_msdos/mount_msdos.8	2011-09-29 23:14:59.000000000 +0900
@@ -41,7 +41,9 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl 9Gls
+.Op Fl C Ar codepage
 .Op Fl g Ar gid
+.Op Fl I Ar iocharset
 .Op Fl M Ar mask
 .Op Fl m Ar mask
 .Op Fl o Ar options
@@ -79,6 +81,9 @@
 if deleting or renaming a file.
 This forces
 .Fl s .
+.It Fl C Ar codepage
+Specify the MS-DOS code page (aka IBM/OEM code page) name used for
+file name conversions for DOS names.
 .It Fl G
 This option causes the filesystem to be interpreted as an Atari-Gemdos
 filesystem.
@@ -91,6 +96,8 @@
 .Ar gid .
 The default group is the group of the directory
 on which the file system is being mounted.
+.It Fl I Ar iocharset
+Specify the I/O charset name used for file name conversions.
 .It Fl l
 Force listing and generation of
 Win'95 long filenames
@@ -167,11 +174,20 @@
 .It
 mount_msdos -m 0644 -M 0755 /dev/wd0e /msdos
 .El
+.Pp
+To mount a Japanese MS-DOS file system:
+.Bl -item -offset indent
+.It
+mount_msdos -C cp932 /dev/sd0e /msdos
+.El
 .Sh SEE ALSO
 .Xr mount 2 ,
 .Xr unmount 2 ,
 .Xr fstab 5 ,
 .Xr mount 8
+.Pp
+List of Localized MS Operating Systems:
+.Pa http://msdn.microsoft.com/ja-jp/goglobal/cc563921.aspx
 .Sh HISTORY
 The
 .Nm
diff --exclude=CVS --exclude='.#*' --exclude='obj.*' --exclude='makeBuild*' -uNr src.orig/sbin/mount_msdos/mount_msdos.c src/sbin/mount_msdos/mount_msdos.c
--- src.orig/sbin/mount_msdos/mount_msdos.c	2009-10-31 23:10:46.000000000 +0900
+++ src/sbin/mount_msdos/mount_msdos.c	2011-06-06 21:13:20.000000000 +0900
@@ -45,12 +45,16 @@
 #include <msdosfs/msdosfsmount.h>
 #include <err.h>
 #include <grp.h>
+#include <locale.h>
+#include <iconv.h>
+#include <langinfo.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <ctype.h>
 #include <util.h>
 
 #include <mntopts.h>
@@ -90,11 +94,12 @@
 	time_t now;
 	struct tm *tm;
 	mntoptparse_t mp;
+	size_t len;
 
 	*mntflags = set_gid = set_uid = set_mask = set_dirmask = set_gmtoff = 0;
 	(void)memset(args, '\0', sizeof(*args));
 
-	while ((c = getopt(argc, argv, "Gsl9u:g:m:M:o:t:")) != -1) {
+	while ((c = getopt(argc, argv, "Gsl9u:g:m:M:o:t:C:I:")) != -1) {
 		switch (c) {
 		case 'G':
 			args->flags |= MSDOSFSMNT_GEMDOSFS;
@@ -134,6 +139,25 @@
 			args->gmtoff = atoi(optarg);
 			set_gmtoff = 1;
 			break;
+		case 'C':
+			len = strlen(optarg);
+			if (len >= sizeof(args->codepage)) {
+				fprintf(stderr, "error: codepage(%s) is "
+				    "too long.\n", optarg);
+				exit(1);
+			}
+			strlcpy(args->codepage, optarg, sizeof(args->codepage));
+			break;
+		case 'I':
+			len = strlen(optarg);
+			if (len >= sizeof(args->iocharset)) {
+				fprintf(stderr, "error: iocharset(%s) is "
+				    "too long.\n", optarg);
+				exit(1);
+			}
+			strlcpy(args->iocharset, optarg,
+			    sizeof(args->iocharset));
+			break;
 		case '?':
 		default:
 			usage();
@@ -180,6 +204,32 @@
 		args->gmtoff = tm->tm_gmtoff;
 
 	}
+
+	if (args->codepage[0] != '\0' && args->iocharset[0] == '\0') {
+		const char *codeset = nl_langinfo(CODESET);
+		if (strlen(codeset) >= sizeof(args->iocharset)) {
+			fprintf(stderr, "warning: current codeset(%s) "
+			    "is too long.\n", codeset);
+			goto disabled;
+		}
+		strlcpy(args->iocharset, codeset, sizeof(args->iocharset));
+	}
+	if (args->codepage[0] != '\0' && args->iocharset[0] != '\0') {
+		iconv_t ic = iconv_open(args->iocharset, args->codepage);
+		if (ic == (iconv_t)-1) {
+			fprintf(stderr, "warning: unusable codepage(%s) or "
+			    "iocharset(%s).\n",
+			    args->codepage, args->iocharset);
+			goto disabled;
+		}
+		iconv_close(ic);
+	} else if (args->codepage[0] != '\0' || args->iocharset[0] != '\0') {
+disabled:
+		/* disable filename convertion */
+		fprintf(stderr, "warning: disable filename conversion.\n");
+		args->codepage[0] = args->iocharset[0] = '\0';
+	}
+
 	args->flags |= MSDOSFSMNT_VERSIONED;
 	args->version = MSDOSFSMNT_VERSION;
 }
@@ -191,6 +241,8 @@
 	char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
 	int mntflags;
 
+	setlocale(LC_CTYPE, "");
+
 	mount_msdos_parseargs(argc, argv, &args, &mntflags,
 	    canon_dev, canon_dir);
 
@@ -200,8 +252,10 @@
 	if (mntflags & MNT_GETARGS) {
 		char buf[1024];
 		(void)snprintb(buf, sizeof(buf), MSDOSFSMNT_BITS, args.flags);
-		printf("uid=%d, gid=%d, mask=0%o, dirmask=0%o, flags=%s\n",
-		    args.uid, args.gid, args.mask, args.dirmask, buf);
+		printf("uid=%d, gid=%d, mask=0%o, dirmask=0%o, gmtoff=%d, "
+		    "codepage=%s, codeset=%s, flags=%s\n",
+		    args.uid, args.gid, args.mask, args.dirmask, args.gmtoff,
+		    args.codepage, args.iocharset, buf);
 	}
 
 	exit (0);
@@ -211,8 +265,8 @@
 usage(void)
 {
 
-	fprintf(stderr, "usage: %s [-9Gls] [-g gid] [-M mask] [-m mask] "
-	    "[-o options]\n\t[-t gmtoff] [-u uid] special mountpath\n",
+	fprintf(stderr, "usage: %s [-9Gls] [-C codepage] [-g gid] [-M mask]\n"
+	    "\t[-m mask] [-o options] [-t gmtoff] [-u uid] special mountpath\n",
 	    getprogname());
 	exit(1);
 }
--- src.orig/distrib/sets/lists/modules/mi	2011-10-07 20:35:35.000000000 +0900
+++ src/distrib/sets/lists/modules/mi	2011-10-07 20:44:57.000000000 +0900
@@ -77,6 +77,54 @@
 ./@MODULEDIR@/iic/iic.kmod			base-kernel-modules	kmod
 ./@MODULEDIR@/kernfs				base-kernel-modules	kmod
 ./@MODULEDIR@/kernfs/kernfs.kmod		base-kernel-modules	kmod
+./@MODULEDIR@/kiconv				base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv/kiconv.kmod		base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_BIG5			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_BIG5/kiconv_BIG5.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_DECHanyu			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_DECHanyu/kiconv_DECHanyu.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_EUC			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_EUC/kiconv_EUC.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_EUCTW			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_EUCTW/kiconv_EUCTW.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_GBK2K			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_GBK2K/kiconv_GBK2K.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_HZ				base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_HZ/kiconv_HZ.kmod		base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_ISO2022			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_ISO2022/kiconv_ISO2022.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_JOHAB			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_JOHAB/kiconv_JOHAB.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_MSKanji			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_MSKanji/kiconv_MSKanji.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_UES			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_UES/kiconv_UES.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_UTF1632			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_UTF1632/kiconv_UTF1632.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_UTF7			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_UTF7/kiconv_UTF7.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_UTF8			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_UTF8/kiconv_UTF8.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_VIQR			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_VIQR/kiconv_VIQR.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_ZW				base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_ZW/kiconv_ZW.kmod		base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_iconv_none			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_iconv_none/kiconv_iconv_none.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_iconv_std			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_iconv_std/kiconv_iconv_std.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_646			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_646/kiconv_mapper_646.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_none		base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_none/kiconv_mapper_none.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_parallel		base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_parallel/kiconv_mapper_parallel.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_serial		base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_serial/kiconv_mapper_serial.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_std			base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_std/kiconv_mapper_std.kmod	base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_zone		base-kernel-modules	kmod,kiconv
+./@MODULEDIR@/kiconv_mapper_zone/kiconv_mapper_zone.kmod	base-kernel-modules	kmod,kiconv
 ./@MODULEDIR@/ksem				base-kernel-modules	kmod
 ./@MODULEDIR@/ksem/ksem.kmod			base-kernel-modules	kmod
 ./@MODULEDIR@/layerfs				base-kernel-modules	kmod
