Module Name:    src
Committed By:   tnozaki
Date:           Sat Jun 19 13:26:52 UTC 2010

Modified Files:
        src/lib/libc/citrus: citrus_lc_ctype.c
        src/lib/libc/locale: Makefile.inc bsdctype.c bsdctype_local.h
            global_locale.c localeio.c localeio.h localeio_lc_ctype.c rune.c
            runetable.c runetype_file.h runetype_local.h
Removed Files:
        src/lib/libc/locale: runeglue.c

Log Message:
1. refactoring new locale-db(RuneCT10) loading method with mmap(2).
2. remove unused field from _RuneLocale.
3. localeio(CITRUS=no) can read new locale-db(RuneCT10) now.


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/lib/libc/citrus/citrus_lc_ctype.c
cvs rdiff -u -r1.57 -r1.58 src/lib/libc/locale/Makefile.inc
cvs rdiff -u -r1.7 -r1.8 src/lib/libc/locale/bsdctype.c
cvs rdiff -u -r1.1 -r1.2 src/lib/libc/locale/bsdctype_local.h \
    src/lib/libc/locale/runetype_file.h
cvs rdiff -u -r1.10 -r1.11 src/lib/libc/locale/global_locale.c \
    src/lib/libc/locale/runetype_local.h
cvs rdiff -u -r1.4 -r1.5 src/lib/libc/locale/localeio.c
cvs rdiff -u -r1.3 -r1.4 src/lib/libc/locale/localeio.h
cvs rdiff -u -r1.5 -r1.6 src/lib/libc/locale/localeio_lc_ctype.c
cvs rdiff -u -r1.38 -r1.39 src/lib/libc/locale/rune.c
cvs rdiff -u -r1.20 -r0 src/lib/libc/locale/runeglue.c
cvs rdiff -u -r1.26 -r1.27 src/lib/libc/locale/runetable.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/citrus/citrus_lc_ctype.c
diff -u src/lib/libc/citrus/citrus_lc_ctype.c:1.8 src/lib/libc/citrus/citrus_lc_ctype.c:1.9
--- src/lib/libc/citrus/citrus_lc_ctype.c:1.8	Sun Jun 13 04:14:56 2010
+++ src/lib/libc/citrus/citrus_lc_ctype.c	Sat Jun 19 13:26:51 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: citrus_lc_ctype.c,v 1.8 2010/06/13 04:14:56 tnozaki Exp $ */
+/* $NetBSD: citrus_lc_ctype.c,v 1.9 2010/06/19 13:26:51 tnozaki Exp $ */
 
 /*-
  * Copyright (c)2008 Citrus Project,
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: citrus_lc_ctype.c,v 1.8 2010/06/13 04:14:56 tnozaki Exp $");
+__RCSID("$NetBSD: citrus_lc_ctype.c,v 1.9 2010/06/19 13:26:51 tnozaki Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include "reentrant.h"
@@ -56,6 +56,7 @@
 #include "citrus_aliasname_local.h"
 #include "citrus_module.h"
 #include "citrus_ctype.h"
+#include "citrus_mmap.h"
 
 #include "runetype_local.h"
 #include "multibyte.h"
@@ -77,9 +78,8 @@
     const char * __restrict name, _RuneLocale ** __restrict pdata)
 {
 	char path[PATH_MAX + 1];
-	FILE *fp;
-	_RuneLocale *data;
 	int ret;
+	struct _region r;
 
 	_DIAGASSERT(root != NULL);
 	_DIAGASSERT(name != NULL);
@@ -87,37 +87,12 @@
 
 	snprintf(path, sizeof(path),
 	    "%s/%s/LC_CTYPE", root, name);
-	fp = fopen(path, "r");
-	if (fp == NULL)
-		return ENOENT;
-	data = _Read_RuneMagi(fp);
-	if (data == NULL) {
-		data = _Read_CTypeAsRune(fp);
-		if (data == NULL) {
-			fclose(fp);
-			return EFTYPE;
-		}
+	ret = _citrus_map_file(&r, path);
+	if (!ret) {
+		ret = _rune_load((const char *)r.r_head, r.r_size, pdata);
+		_citrus_unmap_file(&r);
 	}
-	fclose(fp);
-	ret = _citrus_ctype_open(&data->rl_citrus_ctype, data->rl_encoding,
-	   data->rl_variable, data->rl_variable_len, _PRIVSIZE);
-	if (!ret)
-		ret = __runetable_to_netbsd_ctype(data);
-	if (ret || __mb_len_max_runtime <
-	    _citrus_ctype_get_mb_cur_max(data->rl_citrus_ctype)) {
-		_NukeRune(data);
-		return EINVAL;
-	}
-	data->rl_wctrans[_WCTRANS_INDEX_LOWER].te_name = "tolower";
-	data->rl_wctrans[_WCTRANS_INDEX_LOWER].te_cached = &data->rl_maplower[0];
-	data->rl_wctrans[_WCTRANS_INDEX_LOWER].te_extmap = &data->rl_maplower_ext;
-
-	data->rl_wctrans[_WCTRANS_INDEX_UPPER].te_name = "toupper";
-	data->rl_wctrans[_WCTRANS_INDEX_UPPER].te_cached = &data->rl_mapupper[0];
-	data->rl_wctrans[_WCTRANS_INDEX_UPPER].te_extmap = &data->rl_mapupper_ext;
-
-	*pdata = data;
-	return 0;
+	return ret;
 }
 
 static __inline void

Index: src/lib/libc/locale/Makefile.inc
diff -u src/lib/libc/locale/Makefile.inc:1.57 src/lib/libc/locale/Makefile.inc:1.58
--- src/lib/libc/locale/Makefile.inc:1.57	Mon Jun  7 13:52:30 2010
+++ src/lib/libc/locale/Makefile.inc	Sat Jun 19 13:26:52 2010
@@ -1,5 +1,5 @@
 #	from: @(#)Makefile.inc	5.1 (Berkeley) 2/18/91
-#	$NetBSD: Makefile.inc,v 1.57 2010/06/07 13:52:30 tnozaki Exp $
+#	$NetBSD: Makefile.inc,v 1.58 2010/06/19 13:26:52 tnozaki Exp $
 
 # locale sources
 .PATH: ${ARCHDIR}/locale ${.CURDIR}/locale
@@ -16,10 +16,9 @@
 # citrus multibyte locale support
 # we have quirk for libc.a - see the last part of lib/libc/Makefile
 CPPFLAGS+=	-DWITH_RUNE -I${.CURDIR}
-SRCS+=	_wctrans.c _wctype.c rune.c runeglue.c runetable.c \
+SRCS+=	_wctrans.c _wctype.c rune.c runetable.c \
 	multibyte_c90.c multibyte_amd1.c iswctype_mb.c
 CPPFLAGS.rune.c+=		-I${LIBCDIR}/citrus
-CPPFLAGS.runeglue.c+=		-I${LIBCDIR}/citrus
 CPPFLAGS.runetable.c+=		-I${LIBCDIR}/citrus
 CPPFLAGS.multibyte_c90.c+=	-I${LIBCDIR}/citrus
 CPPFLAGS.multibyte_amd1.c+=	-I${LIBCDIR}/citrus

Index: src/lib/libc/locale/bsdctype.c
diff -u src/lib/libc/locale/bsdctype.c:1.7 src/lib/libc/locale/bsdctype.c:1.8
--- src/lib/libc/locale/bsdctype.c:1.7	Sun Jun 13 04:14:57 2010
+++ src/lib/libc/locale/bsdctype.c	Sat Jun 19 13:26:52 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: bsdctype.c,v 1.7 2010/06/13 04:14:57 tnozaki Exp $ */
+/* $NetBSD: bsdctype.c,v 1.8 2010/06/19 13:26:52 tnozaki Exp $ */
 
 /*-
  * Copyright (c)2008 Citrus Project,
@@ -28,11 +28,10 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: bsdctype.c,v 1.7 2010/06/13 04:14:57 tnozaki Exp $");
+__RCSID("$NetBSD: bsdctype.c,v 1.8 2010/06/19 13:26:52 tnozaki Exp $");
 #endif /* LIBC_SCCS and not lint */
 
-#include <sys/stat.h>
-#include <sys/mman.h>
+#include <sys/endian.h>
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -42,6 +41,7 @@
 #include <unistd.h>
 
 #include "bsdctype_local.h"
+#include "runetype_file.h"
 
 const _BSDCTypeLocale _DefaultBSDCTypeLocale = {
     _C_ctype_,
@@ -61,6 +61,15 @@
 static __inline void
 _bsdctype_init_priv(_BSDCTypeLocalePriv *blp)
 {
+#if _CTYPE_CACHE_SIZE != _CTYPE_NUM_CHARS
+	int i;
+
+	for (i = _CTYPE_CACHE_SIZE; i < _CTYPE_NUM_CHARS; ++i) {
+		blp->blp_ctype_tab  [i + 1] = 0;
+		blp->blp_tolower_tab[i + 1] = i;
+		blp->blp_toupper_tab[i + 1] = i;
+	}
+#endif
 	blp->blp_ctype_tab  [0] = 0;
 	blp->blp_tolower_tab[0] = EOF;
 	blp->blp_toupper_tab[0] = EOF;
@@ -77,103 +86,93 @@
 	uint32_t value;
 	int i;
 
+	_DIAGASSERT(blp != NULL);
+
 	if (lenvar < sizeof(*fbl))
 		return EFTYPE;
 	fbl = (const _FileBSDCTypeLocale *)(const void *)var;
 	if (memcmp(&fbl->fbl_id[0], _CTYPE_ID, sizeof(fbl->fbl_id)))
 		return EFTYPE;
-	value = ntohl(fbl->fbl_rev);
+	value = be32toh(fbl->fbl_rev);
 	if (value != _CTYPE_REV)
 		return EFTYPE;
-	value = ntohl(fbl->fbl_num_chars);
+	value = be32toh(fbl->fbl_num_chars);
 	if (value != _CTYPE_CACHE_SIZE)
 		return EFTYPE;
 	for (i = 0; i < _CTYPE_CACHE_SIZE; ++i) {
 		blp->blp_ctype_tab  [i + 1] = fbl->fbl_ctype_tab[i];
-		blp->blp_tolower_tab[i + 1] = ntohs(fbl->fbl_tolower_tab[i]);
-		blp->blp_toupper_tab[i + 1] = ntohs(fbl->fbl_toupper_tab[i]);
+		blp->blp_tolower_tab[i + 1] = be16toh(fbl->fbl_tolower_tab[i]);
+		blp->blp_toupper_tab[i + 1] = be16toh(fbl->fbl_toupper_tab[i]);
 	}
-#if _CTYPE_CACHE_SIZE != _CTYPE_NUM_CHARS
-	for (i = _CTYPE_CACHE_SIZE; i < _CTYPE_NUM_CHARS; ++i) {
-		blp->blp_ctype_tab  [i + 1] = 0;
-		blp->blp_tolower_tab[i + 1] = i;
-		blp->blp_toupper_tab[i + 1] = i;
-	}
-#endif
 	return 0;
 }
 
 static __inline int
-_bsdctype_load_priv(const char * __restrict path,
+_bsdctype_read_runetype(const char * __restrict var, size_t lenvar,
     _BSDCTypeLocalePriv * __restrict blp)
 {
-	int fd, ret;
-	struct stat st;
-	size_t lenvar;
-	char *var;
-
-	fd = open(path, O_RDONLY);
-	if (fd == -1)
-		goto err;
-	if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
-		goto err;
-	if (fstat(fd, &st) == -1)
-		goto err;
-	if (!S_ISREG(st.st_mode)) {
-		close(fd);
-		return EBADF;
-	}
-	lenvar = (size_t)st.st_size;
-	if (lenvar < 1) {
-		close(fd);
+	const _FileRuneLocale *frl;
+	int i;
+
+	_DIAGASSERT(blp != NULL);
+
+	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;
+	if (frl->frl_encoding[0] != 'N' || frl->frl_encoding[1] != 'O' ||
+	    frl->frl_encoding[2] != 'N' || frl->frl_encoding[3] != 'E' ||
+	    frl->frl_encoding[4] != '\0') /* XXX */
+		return EFTYPE;
+	if (be32toh(frl->frl_runetype_ext.frr_nranges) != 0 ||
+	    be32toh(frl->frl_maplower_ext.frr_nranges) != 0 ||
+	    be32toh(frl->frl_mapupper_ext.frr_nranges) != 0)
+		return EFTYPE;
+	if (lenvar < be32toh((uint32_t)frl->frl_variable_len))
+		return EFTYPE;
+	for (i = 0; i < _CTYPE_CACHE_SIZE; ++i) {
+		blp->blp_ctype_tab  [i + 1] = (unsigned char)
+		    _runetype_to_ctype((_RuneType)
+		    be32toh(frl->frl_runetype[i]));
+		blp->blp_tolower_tab[i + 1] = (short)
+		    be32toh((uint32_t)frl->frl_maplower[i]);
+		blp->blp_toupper_tab[i + 1] = (short)
+		    be32toh((uint32_t)frl->frl_mapupper[i]);
 	}
-	var = mmap(NULL, lenvar, PROT_READ,
-	    MAP_FILE|MAP_PRIVATE, fd, (off_t)0);
-	if (var == MAP_FAILED)
-		goto err;
-	if (close(fd) == -1) {
-		ret = errno;
-		munmap(var, lenvar);
-		return ret;
-	}
-	switch (*var) {
-	case 'B':
-		ret = _bsdctype_read_file(var, lenvar, blp);
-		break;
-	default:
-		ret = EFTYPE;
-	}
-	munmap(var, lenvar);
-	return ret;
-err:
-	ret = errno;
-	close(fd);
-	return ret;
+	return 0;
 }
 
 int
-_bsdctype_load(const char * __restrict path,
+_bsdctype_load(const char * __restrict var, size_t lenvar,
     _BSDCTypeLocale ** __restrict pbl)
 {
-	int sverr, ret;
+	int ret;
 	_BSDCTypeLocalePriv *blp;
 
-	sverr = errno;
-	errno = 0;
+	_DIAGASSERT(var != NULL || lenvar < 1);
+	_DIAGASSERT(pbl != NULL);
+
+	if (lenvar < 1)
+		return EFTYPE;
 	blp = malloc(sizeof(*blp));
-	if (blp == NULL) {
-		ret = errno;
-		errno = sverr;
-		return ret;
-	}
+	if (blp == NULL)
+		return errno;
 	_bsdctype_init_priv(blp);
-	ret = _bsdctype_load_priv(path, blp);
-	if (ret) {
-		free(blp);
-		errno = sverr;
-		return ret;
+	switch (*var) {
+	case 'B':
+		_bsdctype_read_file(var, lenvar, blp);
+		break;
+	case 'R':
+		_bsdctype_read_runetype(var, lenvar, blp);
+		break;
+	default:
+		ret = EFTYPE;
 	}
-	*pbl = &blp->bl;
-	return 0;
+	if (ret)
+		free(blp);
+	else
+		*pbl = &blp->bl;
+	return ret;
 }

Index: src/lib/libc/locale/bsdctype_local.h
diff -u src/lib/libc/locale/bsdctype_local.h:1.1 src/lib/libc/locale/bsdctype_local.h:1.2
--- src/lib/libc/locale/bsdctype_local.h:1.1	Sun Jun 13 04:14:57 2010
+++ src/lib/libc/locale/bsdctype_local.h	Sat Jun 19 13:26:52 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: bsdctype_local.h,v 1.1 2010/06/13 04:14:57 tnozaki Exp $ */
+/* $NetBSD: bsdctype_local.h,v 1.2 2010/06/19 13:26:52 tnozaki Exp $ */
 
 /*-
  * Copyright (c)2008 Citrus Project,
@@ -41,7 +41,8 @@
 extern const _BSDCTypeLocale *_CurrentBSDCTypeLocale;
 
 __BEGIN_DECLS
-int _bsdctype_load(const char * __restrict, _BSDCTypeLocale ** __restrict);
+int _bsdctype_load(const char * __restrict, size_t,
+    _BSDCTypeLocale ** __restrict);
 __END_DECLS
 
 #endif /*_BSDCTYPE_LOCAL_H_*/
Index: src/lib/libc/locale/runetype_file.h
diff -u src/lib/libc/locale/runetype_file.h:1.1 src/lib/libc/locale/runetype_file.h:1.2
--- src/lib/libc/locale/runetype_file.h:1.1	Sun Jun 13 04:14:57 2010
+++ src/lib/libc/locale/runetype_file.h	Sat Jun 19 13:26:52 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: runetype_file.h,v 1.1 2010/06/13 04:14:57 tnozaki Exp $ */
+/* $NetBSD: runetype_file.h,v 1.2 2010/06/19 13:26:52 tnozaki Exp $ */
 
 /*-
  * Copyright (c) 1993
@@ -39,6 +39,7 @@
 
 #include <sys/cdefs.h>
 #include <sys/types.h>
+#include <sys/ctype_bits.h>
 
 #include "ctype_local.h"
 
@@ -78,6 +79,92 @@
 #define	_RUNETYPE_SW2	UINT32_C(0x80000000)	/* 2 width character */
 #define	_RUNETYPE_SW3	UINT32_C(0xc0000000)	/* 3 width character */
 
+static __inline int
+_runetype_to_ctype(_RuneType bits)
+{
+	int ret;
+
+	if (bits == (_RuneType)0)
+		return 0;
+	ret = 0;
+	if (bits & _RUNETYPE_U)
+		ret |= _U;
+	if (bits & _RUNETYPE_L)
+		ret |= _L;
+	if (bits & _RUNETYPE_D)
+		ret |= _N;
+	if (bits & _RUNETYPE_S)
+		ret |= _S;
+	if (bits & _RUNETYPE_P)
+		ret |= _P;
+	if (bits & _RUNETYPE_C)
+		ret |= _C;
+	if (bits & _RUNETYPE_X)
+		ret |= _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 |= _B;
+#else
+	if (bits & _RUNETYPE_B)
+		ret |= _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 & _U)
+		ret |= _RUNETYPE_U;
+	if (bits & _L)
+		ret |= _RUNETYPE_L;
+	if (bits & _N)
+		ret |= _RUNETYPE_D;
+	if (bits & _S)
+		ret |= _RUNETYPE_S;
+	if (bits & _P)
+		ret |= _RUNETYPE_P;
+	if (bits & _C)
+		ret |= _RUNETYPE_C;
+	/* derived flag bits, duplicate of ctype.h */
+	if (bits & (_U|_L))
+		ret |= _RUNETYPE_A;
+	if (bits & (_N|_X))
+		ret |= _RUNETYPE_X;
+	if (bits & (_P|_U|_L|_N))
+		ret |= _RUNETYPE_G;
+	/* we don't really trust _B in the file.  see above. */
+	if (bits & _B)
+		ret |= _RUNETYPE_B;
+	if ((bits & (_P|_U|_L|_N|_B)) || ch == ' ')
+		ret |= (_RUNETYPE_R | _RUNETYPE_SW1);
+	if (ch == ' ' || ch == '\t')
+		ret |= _RUNETYPE_B;
+	return ret;
+}
+
 
 /*
  * rune file format.  network endian.

Index: src/lib/libc/locale/global_locale.c
diff -u src/lib/libc/locale/global_locale.c:1.10 src/lib/libc/locale/global_locale.c:1.11
--- src/lib/libc/locale/global_locale.c:1.10	Sun Jun 13 04:14:57 2010
+++ src/lib/libc/locale/global_locale.c	Sat Jun 19 13:26:52 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: global_locale.c,v 1.10 2010/06/13 04:14:57 tnozaki Exp $ */
+/* $NetBSD: global_locale.c,v 1.11 2010/06/19 13:26:52 tnozaki Exp $ */
 
 /*-
  * Copyright (c)2008 Citrus Project,
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: global_locale.c,v 1.10 2010/06/13 04:14:57 tnozaki Exp $");
+__RCSID("$NetBSD: global_locale.c,v 1.11 2010/06/19 13:26:52 tnozaki Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/types.h>
@@ -42,7 +42,7 @@
 #ifdef WITH_RUNE
 #include "runetype_local.h"
 #else
-#include "bsdctype_locale.h"
+#include "bsdctype_local.h"
 #endif
 
 #include "setlocale_local.h"
Index: src/lib/libc/locale/runetype_local.h
diff -u src/lib/libc/locale/runetype_local.h:1.10 src/lib/libc/locale/runetype_local.h:1.11
--- src/lib/libc/locale/runetype_local.h:1.10	Sun Jun 13 04:14:57 2010
+++ src/lib/libc/locale/runetype_local.h	Sat Jun 19 13:26:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: runetype_local.h,v 1.10 2010/06/13 04:14:57 tnozaki Exp $	*/
+/*	$NetBSD: runetype_local.h,v 1.11 2010/06/19 13:26:52 tnozaki Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -105,9 +105,6 @@
 	/*
 	 * copied from _FileRuneLocale
 	 */
-	char		rl_magic[8];	/* Magic saying what version we are */
-	char		rl_encoding[32];/* ASCII name of this encoding */
-	__nbrune_t	rl_invalid_rune;
 	_RuneType	rl_runetype[_CTYPE_CACHE_SIZE];
 	__nbrune_t	rl_maplower[_CTYPE_CACHE_SIZE];
 	__nbrune_t	rl_mapupper[_CTYPE_CACHE_SIZE];
@@ -138,13 +135,7 @@
 extern const _RuneLocale *_CurrentRuneLocale;
 
 __BEGIN_DECLS
-/* rune.c */
-extern _RuneLocale *_Read_RuneMagi(FILE *fp);
-extern _RuneLocale *_Read_CTypeAsRune(FILE *fp);
-extern void _NukeRune(_RuneLocale *);
-
-/* runeglue.c */
-extern int __runetable_to_netbsd_ctype(_RuneLocale *);
+int _rune_load(const char * __restrict, size_t, _RuneLocale ** __restrict);
 __END_DECLS
 
 #endif	/* !_RUNETYPE_LOCAL_H_ */

Index: src/lib/libc/locale/localeio.c
diff -u src/lib/libc/locale/localeio.c:1.4 src/lib/libc/locale/localeio.c:1.5
--- src/lib/libc/locale/localeio.c:1.4	Sun May 30 08:28:53 2010
+++ src/lib/libc/locale/localeio.c	Sat Jun 19 13:26:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: localeio.c,v 1.4 2010/05/30 08:28:53 tnozaki Exp $	*/
+/*	$NetBSD: localeio.c,v 1.5 2010/06/19 13:26:52 tnozaki Exp $	*/
 /*
  * Copyright (c) 2008, The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -30,13 +30,14 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: localeio.c,v 1.4 2010/05/30 08:28:53 tnozaki Exp $");
+__RCSID("$NetBSD: localeio.c,v 1.5 2010/06/19 13:26:52 tnozaki Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
 
 #include <assert.h>
 #include <errno.h>
@@ -51,6 +52,54 @@
 #include "localeio.h"
 
 int
+_localeio_map_file(const char * __restrict path,
+    void ** __restrict pvar, size_t * __restrict plenvar)
+{
+	int fd, ret;
+	struct stat st;
+	void *var;
+	size_t lenvar;
+
+	_DIAGASSERT(path != NULL);
+	_DIAGASSERT(pvar != NULL);
+	_DIAGASSERT(plenvar != NULL);
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1)
+		return errno;
+	if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 || fstat(fd, &st) == 1) {
+		ret = errno;
+		goto error;
+	}
+	if (!S_ISREG(st.st_mode)) {
+		ret = EBADF;
+		goto error;
+	}
+	lenvar = (size_t)st.st_size;
+	if (lenvar < 1) {
+		ret = EFTYPE;
+		goto error;
+	}
+	var = mmap(NULL, lenvar, PROT_READ,
+	    MAP_FILE|MAP_PRIVATE, fd, (off_t)0);
+	if (var == MAP_FAILED) {
+		ret = errno;
+		goto error;
+	}
+	*pvar = var;
+	*plenvar = lenvar;
+	return 0;
+error:
+	return ret;
+}
+
+void
+_localeio_unmap_file(void *var, size_t lenvar)
+{
+	munmap(var, lenvar);
+}
+
+int
 __loadlocale(const char *name, size_t nstr, size_t nbytes,
     size_t localesize, void *currentlocale)
 {

Index: src/lib/libc/locale/localeio.h
diff -u src/lib/libc/locale/localeio.h:1.3 src/lib/libc/locale/localeio.h:1.4
--- src/lib/libc/locale/localeio.h:1.3	Sun Jan 11 02:46:28 2009
+++ src/lib/libc/locale/localeio.h	Sat Jun 19 13:26:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: localeio.h,v 1.3 2009/01/11 02:46:28 christos Exp $	*/
+/*	$NetBSD: localeio.h,v 1.4 2010/06/19 13:26:52 tnozaki Exp $	*/
 /*
  * Copyright (c) 2008, The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -29,5 +29,8 @@
  */
 
 __BEGIN_DECLS
+int _localeio_map_file(const char * __restrict,
+    void ** __restrict, size_t * __restrict);
+void _localeio_unmap_file(void *, size_t);
 int __loadlocale(const char *, size_t, size_t, size_t, void *);
 __END_DECLS

Index: src/lib/libc/locale/localeio_lc_ctype.c
diff -u src/lib/libc/locale/localeio_lc_ctype.c:1.5 src/lib/libc/locale/localeio_lc_ctype.c:1.6
--- src/lib/libc/locale/localeio_lc_ctype.c:1.5	Sun Jun 13 04:14:57 2010
+++ src/lib/libc/locale/localeio_lc_ctype.c	Sat Jun 19 13:26:52 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: localeio_lc_ctype.c,v 1.5 2010/06/13 04:14:57 tnozaki Exp $ */
+/* $NetBSD: localeio_lc_ctype.c,v 1.6 2010/06/19 13:26:52 tnozaki Exp $ */
 
 /*-
  * Copyright (c)2008 Citrus Project,
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: localeio_lc_ctype.c,v 1.5 2010/06/13 04:14:57 tnozaki Exp $");
+__RCSID("$NetBSD: localeio_lc_ctype.c,v 1.6 2010/06/19 13:26:52 tnozaki Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include "reentrant.h"
@@ -47,6 +47,7 @@
 
 #include "bsdctype_local.h"
 #include "aliasname_local.h"
+#include "localeio.h"
 
 #include "setlocale_local.h"
 
@@ -68,6 +69,9 @@
     const char * __restrict name, _BSDCTypeLocale ** __restrict pdata)
 {
 	char path[PATH_MAX + 1];
+	void *var;
+	size_t lenvar;
+	int ret;
 
 	_DIAGASSERT(root != NULL);
 	_DIAGASSERT(name != NULL);
@@ -75,7 +79,12 @@
 
 	snprintf(path, sizeof(path),
 	    "%s/%s/LC_CTYPE", root, name);
-	return _bsdctype_load(path, pdata);
+	ret = _localeio_map_file(path, &var, &lenvar);
+	if (!ret) {
+		ret = _bsdctype_load((const char *)var, lenvar, pdata);
+		_localeio_unmap_file(var, lenvar);
+	}
+	return ret;
 }
 
 static __inline void

Index: src/lib/libc/locale/rune.c
diff -u src/lib/libc/locale/rune.c:1.38 src/lib/libc/locale/rune.c:1.39
--- src/lib/libc/locale/rune.c:1.38	Sun Jun 13 04:14:57 2010
+++ src/lib/libc/locale/rune.c	Sat Jun 19 13:26:52 2010
@@ -1,7 +1,7 @@
-/*	$NetBSD: rune.c,v 1.38 2010/06/13 04:14:57 tnozaki Exp $	*/
+/* $NetBSD: rune.c,v 1.39 2010/06/19 13:26:52 tnozaki Exp $ */
 
 /*-
- * Copyright (c)1999 Citrus Project,
+ * Copyright (c)2010 Citrus Project,
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,468 +26,321 @@
  * 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)
-#if 0
-static char sccsid[] = "@(#)rune.c	8.1 (Berkeley) 6/4/93";
-#else
-__RCSID("$NetBSD: rune.c,v 1.38 2010/06/13 04:14:57 tnozaki Exp $");
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include "namespace.h"
-#include <sys/types.h>
-#include <sys/ctype_bits.h>
+#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>
 
+#include "setlocale_local.h"
+
 #include "citrus_module.h"
 #include "citrus_ctype.h"
 
-#include "bsdctype_local.h"
 #include "runetype_local.h"
+#include "bsdctype_local.h"
 
-static int readrange __P((_RuneLocale *, _RuneRange *, _FileRuneRange *, void *, FILE *));
-static void _freeentry __P((_RuneRange *));
-static void _wctype_init __P((_RuneLocale *rl));
-
-static int
-readrange(_RuneLocale *rl, _RuneRange *rr, _FileRuneRange *frr, void *lastp,
-	FILE *fp)
-{
-	uint32_t i;
-	_RuneEntry *re;
-	_FileRuneEntry fre;
+#include "multibyte.h"
 
-	_DIAGASSERT(rl != NULL);
-	_DIAGASSERT(rr != NULL);
-	_DIAGASSERT(frr != NULL);
-	_DIAGASSERT(lastp != NULL);
-	_DIAGASSERT(fp != NULL);
-
-	re = (_RuneEntry *)rl->rl_variable;
-
-	rr->rr_nranges = ntohl(frr->frr_nranges);
-	if (rr->rr_nranges == 0) {
-		rr->rr_rune_ranges = NULL;
-		return 0;
-	}
+#include "_wctype_local.h"
+#include "_wctrans_local.h"
 
-	rr->rr_rune_ranges = re;
-	for (i = 0; i < rr->rr_nranges; i++) {
-		if (fread(&fre, sizeof(fre), 1, fp) != 1)
-			return -1;
-
-		re->re_min = ntohl((u_int32_t)fre.fre_min);
-		re->re_max = ntohl((u_int32_t)fre.fre_max);
-		re->re_map = ntohl((u_int32_t)fre.fre_map);
-		re++;
+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;
 
-		if ((void *)re > lastp)
-			return -1;
-	}
-	rl->rl_variable = re;
-	return 0;
+static __inline void
+_rune_wctype_init(_RuneLocale *rl)
+{
+	memcpy(&rl->rl_wctype, &_DefaultRuneLocale.rl_wctype,
+	    sizeof(rl->rl_wctype));
 }
 
-static int
-readentry(_RuneRange *rr, FILE *fp)
+static __inline void
+_rune_wctrans_init(_RuneLocale *rl)
 {
-	_RuneEntry *re;
-	size_t l, i, j;
-	int error;
-
-	_DIAGASSERT(rr != NULL);
-	_DIAGASSERT(fp != NULL);
-
-	re = rr->rr_rune_ranges;
-	for (i = 0; i < rr->rr_nranges; i++) {
-		if (re[i].re_map != 0) {
-			re[i].re_rune_types = NULL;
-			continue;
-		}
-
-		l = re[i].re_max - re[i].re_min + 1;
-		re[i].re_rune_types = malloc(l * sizeof(_RuneType));
-		if (!re[i].re_rune_types) {
-			error = ENOMEM;
-			goto fail;
-		}
-		memset(re[i].re_rune_types, 0, l * sizeof(_RuneType));
-
-		if (fread(re[i].re_rune_types, sizeof(_RuneType), l, fp) != l)
-			goto fail2;
-
-		for (j = 0; j < l; j++)
-			re[i].re_rune_types[j] = ntohl(re[i].re_rune_types[j]);
-	}
-	return 0;
-
-fail:
-	for (j = 0; j < i; j++) {
-		free(re[j].re_rune_types);
-		re[j].re_rune_types = NULL;
-	}
-	return error;
-fail2:
-	for (j = 0; j <= i; j++) {
-		free(re[j].re_rune_types);
-		re[j].re_rune_types = NULL;
-	}
-	return errno;
+	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;
 }
 
-/* XXX: temporary implementation */
-static void
-find_codeset(_RuneLocale *rl)
+static __inline void
+_rune_init_priv(_RuneLocalePriv *rlp)
 {
-	char *top, *codeset, *tail, *ep;
+#if _CTYPE_CACHE_SIZE != _CTYPE_NUM_CHARS
+	int i;
 
-	/* end of rl_variable region */
-	ep = (char *)rl->rl_variable;
-	ep += rl->rl_variable_len;
-	rl->rl_codeset = NULL;
-	if (!(top = strstr(rl->rl_variable, _RUNE_CODESET)))
-		return;
-	tail = strpbrk(top, " \t");
-	codeset = top + sizeof(_RUNE_CODESET) - 1;
-	if (tail) {
-		*top = *tail;
-		*tail = '\0';
-		rl->rl_codeset = strdup(codeset);
-		strlcpy(top + 1, tail + 1, (unsigned)(ep - (top + 1)));
-	} else {
-		*top = '\0';
-		rl->rl_codeset = strdup(codeset);
+	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);
+	_rune_wctrans_init(&rlp->rl);
 }
 
-void
-_freeentry(_RuneRange *rr)
+static __inline void
+_rune_find_codeset(char *s, size_t n,
+    const char *var, size_t lenvar)
 {
-	_RuneEntry *re;
-	uint32_t i;
+	const char *endvar;
 
-	_DIAGASSERT(rr != NULL);
+#define _RUNE_CODESET_LEN (sizeof(_RUNE_CODESET)-1)
 
-	re = rr->rr_rune_ranges;
-	for (i = 0; i < rr->rr_nranges; i++) {
-		if (re[i].re_rune_types)
-			free(re[i].re_rune_types);
-		re[i].re_rune_types = NULL;
+	for (/**/; lenvar > _RUNE_CODESET_LEN; ++var, --lenvar) {
+		if (!memcmp(var, _RUNE_CODESET, _RUNE_CODESET_LEN)) {
+			endvar = &var[_RUNE_CODESET_LEN];
+			while (n-- > 1 && lenvar-- > _RUNE_CODESET_LEN) {
+				if (*endvar == ' ' || *endvar == '\t')
+					break;
+				*s++ = *endvar++;
+			}
+			break;
+		}
 	}
+	*s = '\0';
 }
 
-void
-_wctype_init(_RuneLocale *rl)
+static __inline int
+_rune_read_file(const char * __restrict var, size_t lenvar,
+    _RuneLocale ** __restrict prl)
 {
-	memcpy(&rl->rl_wctype, &_DefaultRuneLocale.rl_wctype,
-	       sizeof(rl->rl_wctype));
-}
-
-
-_RuneLocale *
-_Read_RuneMagi(fp)
-	FILE *fp;
-{
-	/* file */
-	_FileRuneLocale frl;
-	/* host data */
-	char *hostdata;
-	size_t hostdatalen;
-	void *lastp;
+	int ret, i;
+	const _FileRuneLocale *frl;
+	const _FileRuneEntry *fre;
+	const uint32_t *frune;
+	_RuneLocalePriv *rlp;
 	_RuneLocale *rl;
-	struct stat sb;
-	int x;
-
-	_DIAGASSERT(fp != NULL);
-
-	if (fstat(fileno(fp), &sb) < 0)
-		return NULL;
-
-	if (sb.st_size < (off_t)sizeof(_FileRuneLocale))
-		return NULL;
-	/* XXX more validation? */
-
-	/* Someone might have read the magic number once already */
-	rewind(fp);
-
-	if (fread(&frl, sizeof(frl), 1, fp) != 1)
-		return NULL;
-	if (memcmp(frl.frl_magic, _RUNECT10_MAGIC, sizeof(frl.frl_magic)))
-		return NULL;
-
-	hostdatalen = sizeof(*rl) + ntohl((u_int32_t)frl.frl_variable_len) +
-	    ntohl(frl.frl_runetype_ext.frr_nranges) * sizeof(_RuneEntry) +
-	    ntohl(frl.frl_maplower_ext.frr_nranges) * sizeof(_RuneEntry) +
-	    ntohl(frl.frl_mapupper_ext.frr_nranges) * sizeof(_RuneEntry);
-
-	if ((hostdata = malloc(hostdatalen)) == NULL)
-		return NULL;
-	memset(hostdata, 0, hostdatalen);
-	lastp = hostdata + hostdatalen;
-
-	rl = (_RuneLocale *)(void *)hostdata;
-	rl->rl_variable = rl + 1;
-
-	memcpy(rl->rl_magic, frl.frl_magic, sizeof(rl->rl_magic));
-	memcpy(rl->rl_encoding, frl.frl_encoding, sizeof(rl->rl_encoding));
-
-	rl->rl_invalid_rune = ntohl((u_int32_t)frl.frl_invalid_rune);
-	rl->rl_variable_len = ntohl((u_int32_t)frl.frl_variable_len);
-
-	for (x = 0; x < _CTYPE_CACHE_SIZE; ++x) {
-		rl->rl_runetype[x] = ntohl(frl.frl_runetype[x]);
-
-		/* XXX assumes rune_t = u_int32_t */
-		rl->rl_maplower[x] = ntohl((u_int32_t)frl.frl_maplower[x]);
-		rl->rl_mapupper[x] = ntohl((u_int32_t)frl.frl_mapupper[x]);
-	}
-
-	if (readrange(rl, &rl->rl_runetype_ext, &frl.frl_runetype_ext, lastp, fp))
-	{
-		free(hostdata);
-		return NULL;
-	}
-	if (readrange(rl, &rl->rl_maplower_ext, &frl.frl_maplower_ext, lastp, fp))
-	{
-		free(hostdata);
-		return NULL;
-	}
-	if (readrange(rl, &rl->rl_mapupper_ext, &frl.frl_mapupper_ext, lastp, fp))
-	{
-		free(hostdata);
-		return NULL;
-	}
-
-	if (readentry(&rl->rl_runetype_ext, fp) != 0) {
-		free(hostdata);
-		return NULL;
-	}
-
-	if ((u_int8_t *)rl->rl_variable + rl->rl_variable_len >
-	    (u_int8_t *)lastp) {
-		_freeentry(&rl->rl_runetype_ext);
-		free(hostdata);
-		return NULL;
-	}
-	if (rl->rl_variable_len == 0)
-		rl->rl_variable = NULL;
-	if (rl->rl_variable == NULL ||
-	    fread(rl->rl_variable, rl->rl_variable_len, 1, fp) != 1) {
-		_freeentry(&rl->rl_runetype_ext);
-		free(hostdata);
-		return NULL;
-	}
-	find_codeset(rl);
-	_wctype_init(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);
+	if (rlp == NULL)
+		return ENOMEM;
+	_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),
+	    (const 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));
+
+#define CONVERT_MAP(name)						\
+do {									\
+	wint_t map;							\
+	int c;								\
+									\
+	map = _towctrans_priv(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)
 
-	/* error if we have junk at the tail */
-	if (ftell(fp) != sb.st_size) {
-		_freeentry(&rl->rl_runetype_ext);
-		free(hostdata);
-		return NULL;
+			CONVERT_MAP(lower);
+			CONVERT_MAP(upper);
+		}
 	}
+	*prl = rl;
+	return 0;
 
-	return(rl);
+err:
+	free(rlp);
+	return ret;
 }
 
-void
-_NukeRune(rl)
-	_RuneLocale *rl;
+static __inline int
+_rune_read_bsdctype(const char * __restrict var, size_t lenvar,
+    _RuneLocale ** __restrict prl)
 {
+	const _FileBSDCTypeLocale *fbl;
+	uint32_t value;
+	int i, bits;
+	uint16_t lower, upper;
+	_RuneLocalePriv *rlp;
+	_RuneLocale *rl;
 
-	_DIAGASSERT(rl != NULL);
-
-	if (rl != &_DefaultRuneLocale) {
-		_freeentry(&rl->rl_runetype_ext);
-		if (rl->rl_codeset)
-			free(__UNCONST(rl->rl_codeset));
-		if (rl->rl_citrus_ctype)
-			_citrus_ctype_close(rl->rl_citrus_ctype);
-		free(__UNCONST(rl->rl_ctype_tab));
-		free(__UNCONST(rl->rl_tolower_tab));
-		free(__UNCONST(rl->rl_toupper_tab));
-		free(rl);
+        if (lenvar < sizeof(*fbl))
+		return EFTYPE;
+	fbl = (const _FileBSDCTypeLocale *)(const void *)var;
+	if (memcmp(&fbl->fbl_id[0], _CTYPE_ID, sizeof(fbl->fbl_id)))
+		return EFTYPE;
+	value = be32toh(fbl->fbl_rev);
+	if (value != _CTYPE_REV)
+		return EFTYPE;
+	value = be32toh(fbl->fbl_num_chars);
+	if (value != _CTYPE_CACHE_SIZE)
+		return EFTYPE;
+	rlp = (_RuneLocalePriv *)malloc(sizeof(*rlp));
+	if (rlp == NULL)
+		return ENOMEM;
+	_rune_init_priv(rlp);
+
+	rl = &rlp->rl;
+	for (i = 0; i < _CTYPE_CACHE_SIZE; ++i) {
+		bits  = fbl->fbl_ctype_tab[i];
+		lower = be16toh(fbl->fbl_tolower_tab[i]);
+		upper = be16toh(fbl->fbl_toupper_tab[i]);
+
+		rlp->rlp_ctype_tab  [i + 1] = (unsigned char)bits;
+		rlp->rlp_tolower_tab[i + 1] = (short)lower;
+		rlp->rlp_toupper_tab[i + 1] = (short)upper;
+
+		rl->rl_runetype[i] = _runetype_from_ctype(bits, i);
+		rl->rl_maplower[i] = (__nbrune_t)lower;
+		rl->rl_mapupper[i] = (__nbrune_t)upper;
 	}
+	*prl = rl;
+	return 0;
 }
 
-/*
- * read in old LC_CTYPE declaration file, convert into runelocale info
- */
-_RuneLocale *
-_Read_CTypeAsRune(fp)
-	FILE *fp;
+int
+_rune_load(const char * __restrict var, size_t lenvar,
+    _RuneLocale ** __restrict prl)
 {
-	char id[sizeof(_CTYPE_ID) - 1];
-	u_int32_t i, len;
-	u_int8_t *new_ctype = NULL;
-	int16_t *new_toupper = NULL, *new_tolower = NULL;
-	/* host data */
-	char *hostdata = NULL;
-	size_t hostdatalen;
-	_RuneLocale *rl;
-	struct stat sb;
-	int x;
-
-	_DIAGASSERT(fp != NULL);
+	int ret;
 
-	if (fstat(fileno(fp), &sb) < 0)
-		return NULL;
+	_DIAGASSERT(var != NULL || lenvar < 1);
+	_DIAGASSERT(prl != NULL);
 
-	if (sb.st_size < (off_t)sizeof(id))
-		return NULL;
-	/* XXX more validation? */
-
-	/* Someone might have read the magic number once already */
-	rewind(fp);
-
-	if (fread(id, sizeof(id), 1, fp) != 1)
-		goto bad;
-	if (memcmp(id, _CTYPE_ID, sizeof(id)) != 0)
-		goto bad;
-
-	if (fread(&i, sizeof(u_int32_t), 1, fp) != 1) 
-		goto bad;
-	if ((i = ntohl(i)) != _CTYPE_REV)
-		goto bad;
-
-	if (fread(&len, sizeof(u_int32_t), 1, fp) != 1)
-		goto bad;
-	if ((len = ntohl(len)) != _CTYPE_CACHE_SIZE)
-		goto bad;
-
-	if ((new_ctype = malloc(sizeof(u_int8_t) * (1 + len))) == NULL ||
-	    (new_toupper = malloc(sizeof(int16_t) * (1 + len))) == NULL ||
-	    (new_tolower = malloc(sizeof(int16_t) * (1 + len))) == NULL)
-		goto bad;
-	new_ctype[0] = 0;
-	if (fread(&new_ctype[1], sizeof(u_int8_t), len, fp) != len)
-		goto bad;
-	new_toupper[0] = EOF;
-	if (fread(&new_toupper[1], sizeof(int16_t), len, fp) != len)
-		goto bad;
-	new_tolower[0] = EOF;
-	if (fread(&new_tolower[1], sizeof(int16_t), len, fp) != len)
-		goto bad;
-
-	hostdatalen = sizeof(*rl);
-
-	if ((hostdata = malloc(hostdatalen)) == NULL)
-		goto bad;
-	memset(hostdata, 0, hostdatalen);
-	rl = (_RuneLocale *)(void *)hostdata;
-	rl->rl_variable = NULL;
-
-	memcpy(rl->rl_magic, _RUNECT10_MAGIC, sizeof(rl->rl_magic));
-	memcpy(rl->rl_encoding, "NONE", 4);
-
-	rl->rl_invalid_rune = _DefaultRuneLocale.rl_invalid_rune;	/*XXX*/
-	rl->rl_variable_len = 0;
-
-	for (x = 0; x < _CTYPE_CACHE_SIZE; ++x) {
-		if ((uint32_t) x > len)
-			continue;
-
-		/*
-		 * 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.
-		 */
-
-		if (new_ctype[1 + x] & _U)
-			rl->rl_runetype[x] |= _RUNETYPE_U;
-		if (new_ctype[1 + x] & _L)
-			rl->rl_runetype[x] |= _RUNETYPE_L;
-		if (new_ctype[1 + x] & _N)
-			rl->rl_runetype[x] |= _RUNETYPE_D;
-		if (new_ctype[1 + x] & _S)
-			rl->rl_runetype[x] |= _RUNETYPE_S;
-		if (new_ctype[1 + x] & _P)
-			rl->rl_runetype[x] |= _RUNETYPE_P;
-		if (new_ctype[1 + x] & _C)
-			rl->rl_runetype[x] |= _RUNETYPE_C;
-		/* derived flag bits, duplicate of ctype.h */
-		if (new_ctype[1 + x] & (_U | _L))
-			rl->rl_runetype[x] |= _RUNETYPE_A;
-		if (new_ctype[1 + x] & (_N | _X))
-			rl->rl_runetype[x] |= _RUNETYPE_X;
-		if (new_ctype[1 + x] & (_P|_U|_L|_N))
-			rl->rl_runetype[x] |= _RUNETYPE_G;
-		/* we don't really trust _B in the file.  see above. */
-		if (new_ctype[1 + x] & _B)
-			rl->rl_runetype[x] |= _RUNETYPE_B;
-		if ((new_ctype[1 + x] & (_P|_U|_L|_N|_B)) || x == ' ')
-			rl->rl_runetype[x] |= (_RUNETYPE_R | _RUNETYPE_SW1);
-		if (x == ' ' || x == '\t')
-			rl->rl_runetype[x] |= _RUNETYPE_B;
-
-		/* XXX may fail on non-8bit encoding only */
-		rl->rl_mapupper[x] = ntohs(new_toupper[1 + x]);
-		rl->rl_maplower[x] = ntohs(new_tolower[1 + x]);
+	if (lenvar < 1)
+		return EFTYPE;
+	switch (*var) {
+	case 'R':
+		ret = _rune_read_file(var, lenvar, prl);
+		break;
+	case 'B':
+		ret = _rune_read_bsdctype(var, lenvar, prl);
+		break;
+	default:
+		ret = EFTYPE;
 	}
-
-	_wctype_init(rl);
-
-	/*
-	 * __runetable_to_netbsd_ctype() will be called from
-	 * setrunelocale.c:_newrunelocale(), and fill old ctype table.
-	 */
-
-	free(new_ctype);
-	free(new_toupper);
-	free(new_tolower);
-	return(rl);
-
-bad:
-	if (new_ctype)
-		free(new_ctype);
-	if (new_toupper)
-		free(new_toupper);
-	if (new_tolower)
-		free(new_tolower);
-	return NULL;
+	return ret;
 }

Index: src/lib/libc/locale/runetable.c
diff -u src/lib/libc/locale/runetable.c:1.26 src/lib/libc/locale/runetable.c:1.27
--- src/lib/libc/locale/runetable.c:1.26	Sun Jun 13 04:14:57 2010
+++ src/lib/libc/locale/runetable.c	Sat Jun 19 13:26:52 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: runetable.c,v 1.26 2010/06/13 04:14:57 tnozaki Exp $	*/
+/*	$NetBSD: runetable.c,v 1.27 2010/06/19 13:26:52 tnozaki Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)table.c	8.1 (Berkeley) 6/27/93";
 #else
-__RCSID("$NetBSD: runetable.c,v 1.26 2010/06/13 04:14:57 tnozaki Exp $");
+__RCSID("$NetBSD: runetable.c,v 1.27 2010/06/19 13:26:52 tnozaki Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -52,10 +52,6 @@
 #include "runetype_local.h"
 
 const _RuneLocale _DefaultRuneLocale = {
-    _RUNECT10_MAGIC,
-    "NONE",
-    _DEFAULT_INVALID_RUNE,
-
     {	/*00*/	_RUNETYPE_C,
 		_RUNETYPE_C,
 		_RUNETYPE_C,

Reply via email to