Add citrus backend code and iconv front end. This is intentionally
authorJoerg Sonnenberger <joerg@dragonflybsd.org>
Fri, 11 Mar 2005 23:33:53 +0000 (23:33 +0000)
committerJoerg Sonnenberger <joerg@dragonflybsd.org>
Fri, 11 Mar 2005 23:33:53 +0000 (23:33 +0000)
not hooked into the build yet.

Obtained-from: NetBSD / Citrus Project

91 files changed:
include/iconv.h [new file with mode: 0644]
lib/libc/citrus/Makefile.inc [new file with mode: 0644]
lib/libc/citrus/citrus_bcs.c [new file with mode: 0644]
lib/libc/citrus/citrus_bcs.h [new file with mode: 0644]
lib/libc/citrus/citrus_csmapper.c [new file with mode: 0644]
lib/libc/citrus/citrus_csmapper.h [new file with mode: 0644]
lib/libc/citrus/citrus_ctype.c [new file with mode: 0644]
lib/libc/citrus/citrus_ctype.h [new file with mode: 0644]
lib/libc/citrus/citrus_ctype_fallback.c [new file with mode: 0644]
lib/libc/citrus/citrus_ctype_fallback.h [new file with mode: 0644]
lib/libc/citrus/citrus_ctype_local.h [new file with mode: 0644]
lib/libc/citrus/citrus_ctype_template.h [new file with mode: 0644]
lib/libc/citrus/citrus_db.c [new file with mode: 0644]
lib/libc/citrus/citrus_db.h [new file with mode: 0644]
lib/libc/citrus/citrus_db_factory.c [new file with mode: 0644]
lib/libc/citrus/citrus_db_factory.h [new file with mode: 0644]
lib/libc/citrus/citrus_db_file.h [new file with mode: 0644]
lib/libc/citrus/citrus_db_hash.c [new file with mode: 0644]
lib/libc/citrus/citrus_db_hash.h [new file with mode: 0644]
lib/libc/citrus/citrus_esdb.c [new file with mode: 0644]
lib/libc/citrus/citrus_esdb.h [new file with mode: 0644]
lib/libc/citrus/citrus_esdb_file.h [new file with mode: 0644]
lib/libc/citrus/citrus_hash.c [new file with mode: 0644]
lib/libc/citrus/citrus_hash.h [new file with mode: 0644]
lib/libc/citrus/citrus_iconv.c [new file with mode: 0644]
lib/libc/citrus/citrus_iconv.h [new file with mode: 0644]
lib/libc/citrus/citrus_iconv_local.h [new file with mode: 0644]
lib/libc/citrus/citrus_lookup.c [new file with mode: 0644]
lib/libc/citrus/citrus_lookup.h [new file with mode: 0644]
lib/libc/citrus/citrus_lookup_factory.c [new file with mode: 0644]
lib/libc/citrus/citrus_lookup_factory.h [new file with mode: 0644]
lib/libc/citrus/citrus_lookup_file.h [new file with mode: 0644]
lib/libc/citrus/citrus_mapper.c [new file with mode: 0644]
lib/libc/citrus/citrus_mapper.h [new file with mode: 0644]
lib/libc/citrus/citrus_mapper_local.h [new file with mode: 0644]
lib/libc/citrus/citrus_memstream.c [new file with mode: 0644]
lib/libc/citrus/citrus_memstream.h [new file with mode: 0644]
lib/libc/citrus/citrus_mmap.c [new file with mode: 0644]
lib/libc/citrus/citrus_mmap.h [new file with mode: 0644]
lib/libc/citrus/citrus_module.c [new file with mode: 0644]
lib/libc/citrus/citrus_module.h [new file with mode: 0644]
lib/libc/citrus/citrus_namespace.h [new file with mode: 0644]
lib/libc/citrus/citrus_none.c [new file with mode: 0644]
lib/libc/citrus/citrus_none.h [new file with mode: 0644]
lib/libc/citrus/citrus_pivot_factory.c [new file with mode: 0644]
lib/libc/citrus/citrus_pivot_factory.h [new file with mode: 0644]
lib/libc/citrus/citrus_pivot_file.h [new file with mode: 0644]
lib/libc/citrus/citrus_region.h [new file with mode: 0644]
lib/libc/citrus/citrus_stdenc.c [new file with mode: 0644]
lib/libc/citrus/citrus_stdenc.h [new file with mode: 0644]
lib/libc/citrus/citrus_stdenc_local.h [new file with mode: 0644]
lib/libc/citrus/citrus_stdenc_template.h [new file with mode: 0644]
lib/libc/citrus/citrus_types.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_big5.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_big5.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_euc.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_euc.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_euctw.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_euctw.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_gbk2k.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_gbk2k.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_iconv_none.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_iconv_none.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_iconv_std.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_iconv_std.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_iconv_std_local.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_iso2022.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_iso2022.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_646.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_646.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_none.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_none.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_serial.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_serial.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_std.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_std.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_std_file.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_std_local.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_zone.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mapper_zone.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mskanji.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_mskanji.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_utf1632.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_utf1632.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_utf7.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_utf7.h [new file with mode: 0644]
lib/libc/citrus/modules/citrus_utf8.c [new file with mode: 0644]
lib/libc/citrus/modules/citrus_utf8.h [new file with mode: 0644]
lib/libc/iconv/Makefile.inc [new file with mode: 0644]
lib/libc/iconv/iconv.3 [new file with mode: 0644]
lib/libc/iconv/iconv.c [new file with mode: 0644]

diff --git a/include/iconv.h b/include/iconv.h
new file mode 100644 (file)
index 0000000..29dee16
--- /dev/null
@@ -0,0 +1,54 @@
+/*     $NetBSD: iconv.h,v 1.3 2003/08/22 14:05:03 kleink Exp $ */
+/*     $DragonFly: src/include/iconv.h,v 1.1 2005/03/11 23:33:53 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.
+ *
+ */
+
+#ifndef _ICONV_H_
+#define _ICONV_H_
+
+#include <sys/types.h>
+
+struct __tag_iconv_t;
+typedef        struct __tag_iconv_t    *iconv_t;
+
+__BEGIN_DECLS
+iconv_t        iconv_open(const char *, const char *);
+size_t iconv(iconv_t, char ** __restrict, size_t * __restrict,
+             char ** __restrict, size_t * __restrict);
+int    iconv_close(iconv_t);
+/*
+ * non-portable interfaces for iconv
+ */
+int    __iconv_get_list(char ***, size_t *);
+void   __iconv_free_list(char **, size_t);
+size_t __iconv(iconv_t, const char **, size_t *, char **, size_t *,
+               __uint32_t, size_t *);
+#define __ICONV_F_HIDE_INVALID 0x0001
+__END_DECLS
+
+#endif /* !_ICONV_H_ */
diff --git a/lib/libc/citrus/Makefile.inc b/lib/libc/citrus/Makefile.inc
new file mode 100644 (file)
index 0000000..9a02571
--- /dev/null
@@ -0,0 +1,12 @@
+# $DragonFly: src/lib/libc/citrus/Makefile.inc,v 1.1 2005/03/11 23:33:53 joerg Exp $
+
+.PATH: ${.CURDIR}/../libc/citrus
+
+.include "../../i18n_module/Makefile.shlib"
+
+CFLAGS+=       -DI18NMODULE_MAJOR=${MODULE_SHLIB_MAJOR} -D_I18N_DYNAMIC
+
+SRCS+= citrus_bcs.c citrus_csmapper.c citrus_ctype.c citrus_ctype_fallback.c
+SRCS+= citrus_db.c citrus_db_hash.c citrus_esdb.c citrus_hash.c
+SRCS+= citrus_iconv.c citrus_lookup.c citrus_mapper.c citrus_memstream.c
+SRCS+= citrus_mmap.c citrus_module.c citrus_none.c citrus_stdenc.c
diff --git a/lib/libc/citrus/citrus_bcs.c b/lib/libc/citrus/citrus_bcs.c
new file mode 100644 (file)
index 0000000..776203f
--- /dev/null
@@ -0,0 +1,133 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_bcs.c,v 1.4 2004/01/02 21:49:35 itojun Exp $        */
+/*     $DragonFly: src/lib/libc/citrus/citrus_bcs.c,v 1.1 2005/03/11 23:33:53 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/types.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+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));
+}
+
+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));
+}
+
+const char *
+_citrus_bcs_skip_ws(const char *p)
+{
+
+       while (*p && _bcs_isspace(*p))
+               p++;
+
+       return (p);
+}
+
+const char *
+_citrus_bcs_skip_nonws(const char *p)
+{
+
+       while (*p && !_bcs_isspace(*p))
+               p++;
+
+       return (p);
+}
+
+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);
+}
+
+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);
+}
+
+void
+_citrus_bcs_trunc_rws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+       while (*len > 0 && _bcs_isspace(p[*len - 1]))
+               (*len)--;
+}
+
+void
+_citrus_bcs_convert_to_lower(char *s)
+{
+       while (*s) {
+               *s = _bcs_tolower(*s);
+               s++;
+       }
+}
+
+void _citrus_bcs_convert_to_upper(char *s)
+{
+       while (*s) {
+               *s = _bcs_toupper(*s);
+               s++;
+       }
+}
diff --git a/lib/libc/citrus/citrus_bcs.h b/lib/libc/citrus/citrus_bcs.h
new file mode 100644 (file)
index 0000000..972d53c
--- /dev/null
@@ -0,0 +1,81 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_bcs.h,v 1.2 2004/01/02 21:49:35 itojun Exp $        */
+/*     $DragonFly: src/lib/libc/citrus/citrus_bcs.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#ifndef _CITRUS_BCS_H_
+#define _CITRUS_BCS_H_
+
+/*
+ * predicate/conversion for basic character set.
+ */
+
+#define _CITRUS_BCS_PRED(_name_, _cond_) \
+static __inline int _citrus_bcs_##_name_(uint8_t c) { return (_cond_); }
+
+_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'))
+
+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 *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/citrus/citrus_csmapper.c b/lib/libc/citrus/citrus_csmapper.c
new file mode 100644 (file)
index 0000000..960f695
--- /dev/null
@@ -0,0 +1,388 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_csmapper.c,v 1.5 2004/12/30 05:01:50 christos Exp $ */
+/*     $DragonFly: src/lib/libc/citrus/citrus_csmapper.c,v 1.1 2005/03/11 23:33:53 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 "namespace.h"
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/queue.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+#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"
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+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), 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[LINE_MAX];
+       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;
+
+       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, sizeof(buf), "%.*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;
+       }
+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[PATH_MAX];
+       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, sizeof(pa->dst),
+                "%.*s", (int)(z1.end-z1.begin), z1.begin);
+       snprintf(buf, sizeof(buf),
+                "%.*s", (int)(z2.end-z2.begin), z2.begin);
+       pa->norm = 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;
+
+       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);
+       }
+       _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[PATH_MAX];
+
+       ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE);
+       if (ret)
+               return ret;
+
+       norm_min = ULONG_MAX;
+
+       /* find pivot code */
+       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, sizeof(pivot_min));
+               }
+               ret = _lookup_seq_next(cl, NULL, &data);
+       }
+       _lookup_seq_close(cl);
+
+       if (ret != ENOENT)
+               return ret;
+       if (norm_min == ULONG_MAX)
+               return ENOENT;
+       strlcpy(pivot, pivot_min, pvlen);
+       if (rnorm)
+               *rnorm = norm_min;
+
+       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[PATH_MAX];
+
+       snprintf(buf, sizeof(buf), "%s/%s,%s/%s", src, pivot, pivot, dst);
+
+       return _mapper_open_direct(ma, rcm, "mapper_serial", buf);
+}
+
+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;
+
+       if (__isthreaded)
+               _pthread_mutex_lock(&lock);
+
+       if (csm_none) {
+               *rcsm = csm_none;
+               ret = 0;
+               goto quit;
+       }
+
+       ret = _mapper_open_direct(ma, &csm_none, "mapper_none", "");
+       if (ret)
+               goto quit;
+       _mapper_set_persistent(csm_none);
+
+       *rcsm = csm_none;
+       ret = 0;
+quit:
+       if (__isthreaded)
+               _pthread_mutex_unlock(&lock);
+
+       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[PATH_MAX], buf2[PATH_MAX], key[PATH_MAX], pivot[PATH_MAX];
+       const char *realsrc, *realdst;
+       unsigned long norm;
+
+       ret = _citrus_mapper_create_area(&maparea, _PATH_CSMAPPER);
+       if (ret)
+               return ret;
+
+       realsrc = _lookup_alias(CS_ALIAS, src, buf1, sizeof(buf1),
+                               _LOOKUP_CASE_IGNORE);
+       realdst = _lookup_alias(CS_ALIAS, dst, buf2, sizeof(buf2),
+                               _LOOKUP_CASE_IGNORE);
+       if (!strcmp(realsrc, realdst)) {
+               ret = get_none(maparea, rcsm);
+               if (ret == 0 && rnorm != NULL)
+                       *rnorm = 0;
+               return ret;
+       }
+
+       snprintf(key, sizeof(key), "%s/%s", realsrc, realdst);
+
+       ret = _mapper_open(maparea, rcsm, key);
+       if (ret == 0) {
+               if (rnorm != NULL)
+                       *rnorm = 0;
+               return 0;
+       }
+       if (ret != ENOENT || (flags & _CSMAPPER_F_PREVENT_PIVOT)!=0)
+               return ret;
+
+       ret = find_best_pivot(realsrc, realdst, pivot, sizeof(pivot), &norm);
+       if (ret)
+               return ret;
+
+       ret = open_serial_mapper(maparea, rcsm, realsrc, pivot, realdst);
+       if (ret == 0 && rnorm != NULL)
+               *rnorm = norm;
+
+       return ret;
+}
diff --git a/lib/libc/citrus/citrus_csmapper.h b/lib/libc/citrus/citrus_csmapper.h
new file mode 100644 (file)
index 0000000..dd6c941
--- /dev/null
@@ -0,0 +1,49 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_csmapper.h,v 1.1 2003/06/25 09:51:27 tshiozak Exp $ */
+/*     $DragonFly: src/lib/libc/citrus/citrus_csmapper.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 --git a/lib/libc/citrus/citrus_ctype.c b/lib/libc/citrus/citrus_ctype.c
new file mode 100644 (file)
index 0000000..3c0b037
--- /dev/null
@@ -0,0 +1,207 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_ctype.c,v 1.4 2003/03/05 20:18:15 tshiozak Exp $    */
+/*     $DragonFly: src/lib/libc/citrus/citrus_ctype.c,v 1.1 2005/03/11 23:33:53 joerg 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/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <locale.h>
+#include <stddef.h>
+#include <wchar.h>
+#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 */
+};
+
+#ifdef _I18N_DYNAMIC
+
+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));
+       if (cc->cc_ops == NULL)
+               return (ENOMEM);
+
+       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)
+               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);
+       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 = calloc(1, sizeof(*cc));
+       if (!cc) {
+               _citrus_unload_module(handle);
+               return (errno);
+       }
+
+       ret = _initctypemodule(cc, encname, handle, variable, lenvar, szpriv);
+       if (ret) {
+               _citrus_unload_module(cc->cc_module);
+               free(cc);
+               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);
+       free(cc->cc_ops);
+       _citrus_unload_module(cc->cc_module);
+       free(cc);
+}
+
+#else
+/* !_I18N_DYNAMIC */
+
+int
+/*ARGSUSED*/
+_citrus_ctype_open(_citrus_ctype_t *rcc,
+                  char const *encname, void *variable, size_t lenvar,
+                  size_t szpriv)
+{
+       if (!strcmp(encname, _CITRUS_DEFAULT_CTYPE_NAME)) {
+               *rcc = &_citrus_ctype_default;
+               return (0);
+       }
+       return (EINVAL);
+}
+
+void
+/*ARGSUSED*/
+_citrus_ctype_close(_citrus_ctype_t cc)
+{
+}
+
+#endif
diff --git a/lib/libc/citrus/citrus_ctype.h b/lib/libc/citrus/citrus_ctype.h
new file mode 100644 (file)
index 0000000..e5be692
--- /dev/null
@@ -0,0 +1,171 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_ctype.h,v 1.2 2003/03/05 20:18:15 tshiozak Exp $    */
+/*     $DragonFly: src/lib/libc/citrus/citrus_ctype.h,v 1.1 2005/03/11 23:33:53 joerg 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 --git a/lib/libc/citrus/citrus_ctype_fallback.c b/lib/libc/citrus/citrus_ctype_fallback.c
new file mode 100644 (file)
index 0000000..dbbe9d5
--- /dev/null
@@ -0,0 +1,104 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_ctype_fallback.c,v 1.2 2003/06/27 14:52:25 yamt Exp $       */
+/*     $DragonFly: src/lib/libc/citrus/citrus_ctype_fallback.c,v 1.1 2005/03/11 23:33:53 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/types.h>
+#include <assert.h>
+#include <wchar.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+
+#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 --git a/lib/libc/citrus/citrus_ctype_fallback.h b/lib/libc/citrus/citrus_ctype_fallback.h
new file mode 100644 (file)
index 0000000..fcdaa64
--- /dev/null
@@ -0,0 +1,39 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_ctype_fallback.h,v 1.1 2003/03/05 20:18:15 tshiozak Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_ctype_fallback.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 --git a/lib/libc/citrus/citrus_ctype_local.h b/lib/libc/citrus/citrus_ctype_local.h
new file mode 100644 (file)
index 0000000..da5c332
--- /dev/null
@@ -0,0 +1,200 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_ctype_local.h,v 1.2 2003/03/05 20:18:15 tshiozak Exp $      */
+/*     $DragonFly: src/lib/libc/citrus/citrus_ctype_local.h,v 1.1 2005/03/11 23:33:53 joerg 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 --git a/lib/libc/citrus/citrus_ctype_template.h b/lib/libc/citrus/citrus_ctype_template.h
new file mode 100644 (file)
index 0000000..6ae064c
--- /dev/null
@@ -0,0 +1,769 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_ctype_template.h,v 1.32 2005/03/05 17:31:03 tnozaki Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_ctype_template.h,v 1.1 2005/03/11 23:33:53 joerg 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;
+       size_t nr;
+       int err = 0;
+
+       _DIAGASSERT(ei != NULL);
+       _DIAGASSERT(psenc != NULL);
+
+       if (s == NULL) {
+               *nresult = _ENCODING_IS_STATE_DEPENDENT;
+               return (0);
+       }
+
+       state = *psenc;
+       err = _FUNCNAME(mbrtowc_priv)(ei, pwc, (const char **)&s, n, psenc, &nr);
+       if (err) {
+               *nresult = -1;
+               return (err);
+       }
+       if (nr == (size_t)-2) {
+               *psenc = state;
+               *nresult = -1;
+               return (EILSEQ);
+       }
+
+       *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 = calloc(1, sizeof(_CTYPE_INFO));
+       if (cei == NULL)
+               return (ENOMEM);
+
+       *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);
+       }
+}
+
+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;
+       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, (const char **)&s, 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;
+       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, (const char **)&s, 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;
+
+       _DIAGASSERT(cl != NULL);
+
+       ei = _CEI_TO_EI(_TO_CEI(cl));
+       _FUNCNAME(init_state)(ei, &state);
+       err = _FUNCNAME(mbsrtowcs_priv)(ei, pwcs, (const char **)&s, 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;
+       int err;
+
+       _DIAGASSERT(cl != NULL);
+
+       ei = _CEI_TO_EI(_TO_CEI(cl));
+       _FUNCNAME(init_state)(ei, &state);
+       err = _FUNCNAME(wcsrtombs_priv)(ei, s, (const wchar_t **)&pwcs, 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 --git a/lib/libc/citrus/citrus_db.c b/lib/libc/citrus/citrus_db.c
new file mode 100644 (file)
index 0000000..dbdd4de
--- /dev/null
@@ -0,0 +1,338 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_db.c,v 1.3 2004/01/02 21:49:35 itojun Exp $ */
+/*     $DragonFly: src/lib/libc/citrus/citrus_db.c,v 1.1 2005/03/11 23:33:53 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/types.h>
+#include <sys/endian.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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));
+       if (db==NULL)
+               return errno;
+       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);
+}
+
+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;
+
+       /* LINTED: discard const */
+       _region_init(&r, (char *)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 --git a/lib/libc/citrus/citrus_db.h b/lib/libc/citrus/citrus_db.h
new file mode 100644 (file)
index 0000000..c2c9b26
--- /dev/null
@@ -0,0 +1,76 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_db.h,v 1.1 2003/06/25 09:51:29 tshiozak Exp $       */
+/*     $DragonFly: src/lib/libc/citrus/citrus_db.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#ifndef _CITRUS_DB_H_
+#define _CITRUS_DB_H_
+
+struct _citrus_db;
+struct _citrus_db_locator {
+       u_int32_t       dl_hashval;
+       size_t          dl_offset;
+};
+
+__BEGIN_DECLS
+int    _citrus_db_open(struct _citrus_db **, struct _citrus_region *,
+                       const char *,
+                       u_int32_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 *,
+                                    u_int8_t *,
+                                    struct _citrus_db_locator *);
+int    _citrus_db_lookup16_by_string(struct _citrus_db *, const char *,
+                                     u_int16_t *,
+                                     struct _citrus_db_locator *);
+int    _citrus_db_lookup32_by_string(struct _citrus_db *, const char *,
+                                     u_int32_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 --git a/lib/libc/citrus/citrus_db_factory.c b/lib/libc/citrus/citrus_db_factory.c
new file mode 100644 (file)
index 0000000..21400aa
--- /dev/null
@@ -0,0 +1,345 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_db_factory.c,v 1.8 2004/01/02 21:49:35 itojun Exp $ */
+/*     $DragonFly: src/lib/libc/citrus/citrus_db_factory.c,v 1.1 2005/03/11 23:33:53 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/types.h>
+#include <sys/queue.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_db_file.h"
+#include "citrus_db_factory.h"
+
+struct _citrus_db_factory_entry {
+       STAILQ_ENTRY(_citrus_db_factory_entry)  de_entry;
+       struct _citrus_db_factory_entry *de_next;
+       uint32_t de_hashvalue;
+       struct _region de_key;
+       int de_key_free;
+       struct _region de_data;
+       int de_data_free;
+       int de_idx;
+};
+
+struct _citrus_db_factory {
+       size_t df_num_entries;
+       STAILQ_HEAD(, _citrus_db_factory_entry) df_entries;
+       size_t df_total_key_size;
+       size_t df_total_data_size;
+       uint32_t (*df_hashfunc)(void *, struct _citrus_region *);
+       void *df_hashfunc_closure;
+};
+
+#define DB_ALIGN 16
+
+int
+_citrus_db_factory_create(struct _citrus_db_factory **rdf,
+                         _citrus_db_hash_func_t hashfunc,
+                         void *hashfunc_closure)
+{
+       struct _citrus_db_factory *df;
+
+       df = malloc(sizeof(*df));
+       if (df == NULL)
+               return errno;
+       df->df_num_entries = 0;
+       df->df_total_key_size = df->df_total_data_size = 0;
+       STAILQ_INIT(&df->df_entries);
+       df->df_hashfunc = hashfunc;
+       df->df_hashfunc_closure = hashfunc_closure;
+
+       *rdf = df;
+
+       return 0;
+}
+
+void
+_citrus_db_factory_free(struct _citrus_db_factory *df)
+{
+       struct _citrus_db_factory_entry *de;
+
+       while ((de = STAILQ_FIRST(&df->df_entries)) != NULL) {
+               STAILQ_REMOVE_HEAD(&df->df_entries, de_entry);
+               if (de->de_key_free)
+                       free(_region_head(&de->de_key));
+               if (de->de_data_free)
+                       free(_region_head(&de->de_data));
+               free(de);
+       }
+       free(df);
+}
+
+static __inline size_t
+ceilto(size_t sz)
+{
+       return (sz+DB_ALIGN-1) & ~(DB_ALIGN-1);
+}
+
+int
+_citrus_db_factory_add(struct _citrus_db_factory *df,
+                      struct _region *key, int keyfree,
+                      struct _region *data, int datafree)
+{
+       struct _citrus_db_factory_entry *de;
+
+       de = malloc(sizeof(*de));
+       if (de == NULL)
+               return -1;
+
+       de->de_hashvalue = df->df_hashfunc(df->df_hashfunc_closure, key);
+       de->de_key = *key;
+       de->de_key_free = keyfree;
+       de->de_data = *data;
+       de->de_data_free = datafree;
+       de->de_idx = -1;
+
+       STAILQ_INSERT_TAIL(&df->df_entries, de, de_entry);
+       df->df_total_key_size += _region_size(key);
+       df->df_total_data_size += ceilto(_region_size(data));
+       df->df_num_entries++;
+
+       return 0;
+
+}
+
+int
+_citrus_db_factory_add_by_string(struct _citrus_db_factory *df,
+                                const char *key,
+                                struct _citrus_region *data, int datafree)
+{
+       struct _region r;
+       char *tmp;
+       tmp = strdup(key);
+       if (tmp == NULL)
+               return errno;
+       _region_init(&r, tmp, strlen(key));
+       return _citrus_db_factory_add(df, &r, 1, data, datafree);
+}
+
+int
+_citrus_db_factory_add8_by_string(struct _citrus_db_factory *df,
+                                 const char *key, uint8_t val)
+{
+       struct _region r;
+       uint8_t *p;
+
+       p = malloc(sizeof(*p));
+       if (p == NULL)
+               return errno;
+       *p = val;
+       _region_init(&r, p, 1);
+       return _citrus_db_factory_add_by_string(df, key, &r, 1);
+}
+
+int
+_citrus_db_factory_add16_by_string(struct _citrus_db_factory *df,
+                                  const char *key, uint16_t val)
+{
+       struct _region r;
+       uint16_t *p;
+
+       p = malloc(sizeof(*p));
+       if (p == NULL)
+               return errno;
+       *p = htons(val);
+       _region_init(&r, p, 2);
+       return _citrus_db_factory_add_by_string(df, key, &r, 1);
+}
+
+int
+_citrus_db_factory_add32_by_string(struct _citrus_db_factory *df,
+                                  const char *key, uint32_t val)
+{
+       struct _region r;
+       uint32_t *p;
+
+       p = malloc(sizeof(*p));
+       if (p == NULL)
+               return errno;
+       *p = htonl(val);
+       _region_init(&r, p, 4);
+       return _citrus_db_factory_add_by_string(df, key, &r, 1);
+}
+
+int
+_citrus_db_factory_add_string_by_string(struct _citrus_db_factory *df,
+                                       const char *key, const char *data)
+{
+       char *p;
+       struct _region r;
+
+       p = strdup(data);
+       if (p == NULL)
+               return errno;
+       _region_init(&r, p, strlen(p)+1);
+       return _citrus_db_factory_add_by_string(df, key, &r, 1);
+}
+
+size_t
+_citrus_db_factory_calc_size(struct _citrus_db_factory *df)
+{
+       size_t sz;
+
+       sz = ceilto(_CITRUS_DB_HEADER_SIZE);
+       sz += ceilto(_CITRUS_DB_ENTRY_SIZE * df->df_num_entries);
+       sz += ceilto(df->df_total_key_size);
+       sz += df->df_total_data_size;
+
+       return sz;
+}
+
+static __inline void
+put8(struct _region *r, size_t *rofs, uint8_t val)
+{
+       *(uint8_t *)_region_offset(r, *rofs) = val;
+       *rofs += 1;
+}
+
+static __inline void
+put16(struct _region *r, size_t *rofs, uint16_t val)
+{
+       val = htons(val);
+       memcpy(_region_offset(r, *rofs), &val, 2);
+       *rofs += 2;
+}
+
+static __inline void
+put32(struct _region *r, size_t *rofs, uint32_t val)
+{
+       val = htonl(val);
+       memcpy(_region_offset(r, *rofs), &val, 4);
+       *rofs += 4;
+}
+
+static __inline void
+putpad(struct _region *r, size_t *rofs)
+{
+       size_t i;
+       for (i = ceilto(*rofs) - *rofs; i > 0; i--)
+               put8(r, rofs, 0);
+}
+
+static __inline void
+dump_header(struct _region *r, const char *magic, size_t *rofs,
+           size_t num_entries)
+{
+       while (*rofs<_CITRUS_DB_MAGIC_SIZE)
+               put8(r, rofs, *magic++);
+       put32(r, rofs, num_entries);
+       put32(r, rofs, _CITRUS_DB_HEADER_SIZE);
+}
+
+int
+_citrus_db_factory_serialize(struct _citrus_db_factory *df, const char *magic,
+                            struct _region *r)
+{
+       size_t i, ofs, keyofs, dataofs, nextofs;
+       struct _citrus_db_factory_entry *de, **depp, *det;
+
+       ofs = 0;
+       /* check whether more than 0 entries exist */
+       if (df->df_num_entries == 0) {
+               dump_header(r, magic, &ofs, 0);
+               return 0;
+       }
+       /* allocate hash table */
+       depp = malloc(sizeof(*depp) * df->df_num_entries);
+       if (depp == NULL)
+               return -1;
+       for (i = 0; i < df->df_num_entries; i++)
+               depp[i] = NULL;
+
+       /* step1: store the entries which are not conflicting */
+       STAILQ_FOREACH(de, &df->df_entries, de_entry) {
+               de->de_hashvalue %= df->df_num_entries;
+               de->de_idx = -1;
+               de->de_next = NULL;
+               if (depp[de->de_hashvalue] == NULL) {
+                       depp[de->de_hashvalue] = de;
+                       de->de_idx = (int)de->de_hashvalue;
+               }
+       }
+
+       /* step2: resolve conflicts */
+       i = 0;
+       STAILQ_FOREACH(de, &df->df_entries, de_entry) {
+               if (de->de_idx == -1) {
+                       det = depp[de->de_hashvalue];
+                       while (det->de_next != NULL)
+                               det = det->de_next;
+                       det->de_next = de;
+                       while (depp[i] != NULL)
+                               i++;
+                       depp[i] = de;
+                       de->de_idx = (int)i;
+               }
+       }
+
+       keyofs =
+           _CITRUS_DB_HEADER_SIZE +
+           ceilto(df->df_num_entries*_CITRUS_DB_ENTRY_SIZE);
+       dataofs = keyofs + ceilto(df->df_total_key_size);
+
+       /* dump header */
+       dump_header(r, magic, &ofs, df->df_num_entries);
+
+       /* dump entries */
+       for (i = 0; i < df->df_num_entries; i++) {
+               de = depp[i];
+               nextofs = 0;
+               if (de->de_next) {
+                       nextofs =
+                           _CITRUS_DB_HEADER_SIZE +
+                           de->de_next->de_idx * _CITRUS_DB_ENTRY_SIZE;
+               }
+               put32(r, &ofs, de->de_hashvalue);
+               put32(r, &ofs, nextofs);
+               put32(r, &ofs, keyofs);
+               put32(r, &ofs, _region_size(&de->de_key));
+               put32(r, &ofs, dataofs);
+               put32(r, &ofs, _region_size(&de->de_data));
+               memcpy(_region_offset(r, keyofs),
+                      _region_head(&de->de_key), _region_size(&de->de_key));
+               keyofs += _region_size(&de->de_key);
+               memcpy(_region_offset(r, dataofs),
+                      _region_head(&de->de_data), _region_size(&de->de_data));
+               dataofs += _region_size(&de->de_data);
+               putpad(r, &dataofs);
+       }
+       putpad(r, &ofs);
+       putpad(r, &keyofs);
+       free(depp);
+
+       return 0;
+}
diff --git a/lib/libc/citrus/citrus_db_factory.h b/lib/libc/citrus/citrus_db_factory.h
new file mode 100644 (file)
index 0000000..66a78ec
--- /dev/null
@@ -0,0 +1,60 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_db_factory.h,v 1.1 2003/06/25 09:51:30 tshiozak Exp $       */
+/*     $DragonFly: src/lib/libc/citrus/citrus_db_factory.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#ifndef _CITRUS_DB_FACTORY_H_
+#define _CITRUS_DB_FACTORY_H_
+
+struct _citrus_db_factory;
+typedef uint32_t (*_citrus_db_hash_func_t)(void *, struct _citrus_region *);;
+
+__BEGIN_DECLS
+int    _citrus_db_factory_create(struct _citrus_db_factory **,
+                                 _citrus_db_hash_func_t, void *);
+void   _citrus_db_factory_free(struct _citrus_db_factory *);
+int    _citrus_db_factory_add(struct _citrus_db_factory *,
+                              struct _citrus_region *, int,
+                              struct _citrus_region *, int);
+int    _citrus_db_factory_add_by_string(struct _citrus_db_factory *,
+                                        const char *,
+                                        struct _citrus_region *, int);
+int    _citrus_db_factory_add8_by_string(struct _citrus_db_factory *,
+                                         const char *, uint8_t);
+int    _citrus_db_factory_add16_by_string(struct _citrus_db_factory *,
+                                          const char *, uint16_t);
+int    _citrus_db_factory_add32_by_string(struct _citrus_db_factory *,
+                                         const char *, uint32_t);
+int    _citrus_db_factory_add_string_by_string(struct _citrus_db_factory *,
+                                               const char *, const char *);
+size_t _citrus_db_factory_calc_size(struct _citrus_db_factory *);
+int    _citrus_db_factory_serialize(struct _citrus_db_factory *,
+                                    const char *, struct _citrus_region *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/citrus/citrus_db_file.h b/lib/libc/citrus/citrus_db_file.h
new file mode 100644 (file)
index 0000000..017f241
--- /dev/null
@@ -0,0 +1,86 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_db_file.h,v 1.2 2003/06/30 17:54:13 christos Exp $  */
+/*     $DragonFly: src/lib/libc/citrus/citrus_db_file.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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;
+} __attribute__((__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;
+} __attribute__((__packed__));
+#define _CITRUS_DB_ENTRY_SIZE  24
+
+#endif
diff --git a/lib/libc/citrus/citrus_db_hash.c b/lib/libc/citrus/citrus_db_hash.c
new file mode 100644 (file)
index 0000000..b50236b
--- /dev/null
@@ -0,0 +1,61 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_db_hash.c,v 1.4 2004/01/02 21:49:35 itojun Exp $    */
+/*     $DragonFly: src/lib/libc/citrus/citrus_db_hash.c,v 1.1 2005/03/11 23:33:53 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 <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#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 __unused, 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 --git a/lib/libc/citrus/citrus_db_hash.h b/lib/libc/citrus/citrus_db_hash.h
new file mode 100644 (file)
index 0000000..6f4c6c4
--- /dev/null
@@ -0,0 +1,38 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_db_hash.h,v 1.1 2003/06/25 09:51:31 tshiozak Exp $  */
+/*     $DragonFly: src/lib/libc/citrus/citrus_db_hash.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 --git a/lib/libc/citrus/citrus_esdb.c b/lib/libc/citrus/citrus_esdb.c
new file mode 100644 (file)
index 0000000..76eaf53
--- /dev/null
@@ -0,0 +1,351 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_esdb.c,v 1.4 2004/07/21 14:16:34 tshiozak Exp $     */
+/*     $DragonFly: src/lib/libc/citrus/citrus_esdb.c,v 1.1 2005/03/11 23:33:53 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 <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 "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 version, 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, &version, NULL);
+       if (ret)
+               goto err1;
+       switch (version) {
+       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);
+       if (esdb->db_encname == NULL) {
+               ret = errno;
+               goto err1;
+       }
+
+       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);
+               if (esdb->db_variable == NULL) {
+                       ret = errno;
+                       goto err2;
+               }
+       } 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));
+       if (esdb->db_charsets == NULL) {
+               ret = errno;
+               goto err3;
+       }
+       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);
+               if (esdb->db_charsets[i].ec_csname == NULL) {
+                       ret = errno;
+                       goto err4;
+               }
+       }
+
+       _db_close(db);
+       return 0;
+
+err4:
+       for (; i > 0; i--)
+               free(esdb->db_charsets[i - 1].ec_csname);
+       free(esdb->db_charsets);
+err3:
+       free(esdb->db_variable);
+err2:
+       free(esdb->db_encname);
+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 *db, const char *esname)
+{
+       int ret;
+       const char *realname, *encfile;
+       char buf1[PATH_MAX], buf2[PATH_MAX], path[PATH_MAX];
+       struct _region fr;
+
+       _DIAGASSERT(esname != NULL);
+
+       snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, ESDB_ALIAS);
+       realname = _lookup_alias(path, esname, buf1, sizeof(buf1),
+                                _LOOKUP_CASE_IGNORE);
+
+       snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, ESDB_DIR);
+       encfile = _lookup_simple(path, realname, buf2, sizeof(buf2),
+                                _LOOKUP_CASE_IGNORE);
+       if (encfile==NULL)
+               return ENOENT;
+
+       /* open file */
+       snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, encfile);
+       ret = _map_file(&fr, path);
+       if (ret)
+               return ret;
+
+       ret = conv_esdb(db, &fr);
+
+       _unmap_file(&fr);
+
+       return ret;
+}
+
+/*
+ * _citrus_esdb_close:
+ *     free an ESDB.
+ */
+void
+_citrus_esdb_close(struct _citrus_esdb *db)
+{
+       int i;
+
+       _DIAGASSERT(db != NULL);
+       _DIAGASSERT(db->db_num_charsets == 0 || db->db_charsets != NULL);
+
+       for (i = 0; i < db->db_num_charsets; i++)
+               free(db->db_charsets[i].ec_csname);
+       db->db_num_charsets = 0;
+       free(db->db_charsets); db->db_charsets = NULL;
+       free(db->db_encname); db->db_encname = NULL;
+       db->db_len_variable = 0;
+       free(db->db_variable); db->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]);
+       free(list);
+}
+
+/*
+ * _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[PATH_MAX];
+
+       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 *));
+       num = 0;
+       if (list == NULL) {
+               ret = errno;
+               goto quit3;
+       }
+
+       /* get alias entries */
+       while ((ret = _lookup_seq_next(cla, &key, NULL)) == 0) {
+               snprintf(buf, sizeof(buf), "%.*s",
+                        (int)_region_size(&key),
+                        (const char *)_region_head(&key));
+               _bcs_convert_to_lower(buf);
+               list[num] = strdup(buf);
+               if (list[num] == NULL) {
+                       ret = errno;
+                       goto quit3;
+               }
+               num++;
+       }
+       if (ret != ENOENT)
+               goto quit3;
+       /* get dir entries */
+       while ((ret = _lookup_seq_next(cld, &key, NULL)) == 0) {
+               /* check duplicated entry */
+               snprintf(buf, sizeof(buf), "%.*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);
+                       if (list[num] == NULL) {
+                               ret = errno;
+                               goto quit3;
+                       }
+                       num++;
+               }
+       }
+       if (ret != ENOENT)
+               goto quit3;
+
+       ret = 0;
+       q = realloc(list, num * sizeof(char *));
+       if (!q) {
+               ret = ENOMEM;
+               goto quit3;
+       }
+       list = q;
+       *rlist = list;
+       *rnum = num;
+quit3:
+       if (ret)
+               _citrus_esdb_free_list(list, num);
+       _lookup_seq_close(cld);
+quit1:
+       _lookup_seq_close(cla);
+quit0:
+       return ret;
+}
diff --git a/lib/libc/citrus/citrus_esdb.h b/lib/libc/citrus/citrus_esdb.h
new file mode 100644 (file)
index 0000000..bf28038
--- /dev/null
@@ -0,0 +1,57 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_esdb.h,v 1.1 2003/06/25 09:51:32 tshiozak Exp $     */
+/*     $DragonFly: src/lib/libc/citrus/citrus_esdb.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 --git a/lib/libc/citrus/citrus_esdb_file.h b/lib/libc/citrus/citrus_esdb_file.h
new file mode 100644 (file)
index 0000000..e1593c5
--- /dev/null
@@ -0,0 +1,46 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_esdb_file.h,v 1.1 2003/06/25 09:51:32 tshiozak Exp $        */
+/*     $DragonFly: src/lib/libc/citrus/citrus_esdb_file.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 --git a/lib/libc/citrus/citrus_hash.c b/lib/libc/citrus/citrus_hash.c
new file mode 100644 (file)
index 0000000..933ce2d
--- /dev/null
@@ -0,0 +1,51 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_hash.c,v 1.1 2003/06/25 09:51:32 tshiozak Exp $     */
+/*     $DragonFly: src/lib/libc/citrus/citrus_hash.c,v 1.1 2005/03/11 23:33:53 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 <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#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;
+
+       /* LINTED: discard const */
+       _region_init(&r, (char *)key, strlen(key));
+
+       return (int)(_db_hash_std(NULL, &r) % (uint32_t)hashsize);
+}
diff --git a/lib/libc/citrus/citrus_hash.h b/lib/libc/citrus/citrus_hash.h
new file mode 100644 (file)
index 0000000..8a131f0
--- /dev/null
@@ -0,0 +1,60 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_hash.h,v 1.3 2004/01/02 21:49:35 itojun Exp $       */
+/*     $DragonFly: src/lib/libc/citrus/citrus_hash.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 --git a/lib/libc/citrus/citrus_iconv.c b/lib/libc/citrus/citrus_iconv.c
new file mode 100644 (file)
index 0000000..48b27ce
--- /dev/null
@@ -0,0 +1,391 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_iconv.c,v 1.6 2004/12/30 05:03:48 christos Exp $    */
+/*     $DragonFly: src/lib/libc/citrus/citrus_iconv.c,v 1.1 2005/03/11 23:33:53 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 "namespace.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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+#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
+#define CI_ENV_MAX_REUSE       "ICONV_MAX_REUSE"
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static int isinit = 0;
+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)
+{
+       if (__isthreaded)
+               _pthread_mutex_lock(&lock);
+
+       if (!isinit) {
+               _CITRUS_HASH_INIT(&shared_pool, CI_HASH_SIZE);
+               TAILQ_INIT(&shared_unused);
+               shared_max_reuse = -1;
+               if (!issetugid() && getenv(CI_ENV_MAX_REUSE))
+                       shared_max_reuse = atoi(getenv(CI_ENV_MAX_REUSE));
+               if (shared_max_reuse < 0)
+                       shared_max_reuse = CI_INITIAL_MAX_REUSE;
+               isinit = 1;
+       }
+
+       if (__isthreaded)
+               _pthread_mutex_unlock(&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_MAX];
+
+       /* 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);
+       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);
+                       }
+                       _citrus_unload_module(ci->ci_module);
+               }
+               free(ci);
+       }
+}
+
+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[LINE_MAX];
+       const char *module, *variable;
+       size_t len_convname;
+
+       /* search converter entry */
+       ret = lookup_iconv_entry(basedir, convname, linebuf, sizeof(linebuf),
+                                &module, &variable);
+       if (ret) {
+               if (ret == ENOENT)
+                       /* fallback */
+                       ret = lookup_iconv_entry(basedir, "*",
+                                                linebuf, PATH_MAX,
+                                                &module, &variable);
+               if (ret)
+                       return ret;
+       }
+
+       /* initialize iconv handle */
+       len_convname = strlen(convname);
+       ci = malloc(sizeof(*ci)+len_convname+1);
+       if (!ci) {
+               ret = errno;
+               goto err;
+       }
+       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) {
+               ret = EOPNOTSUPP;
+               goto err;
+       }
+       ci->ci_ops = malloc(sizeof(*ci->ci_ops));
+       if (!ci->ci_ops) {
+               ret = errno;
+               goto err;
+       }
+       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)
+               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;
+
+       *rci = ci;
+
+       return 0;
+err:
+       close_shared(ci);
+       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[PATH_MAX];
+
+       snprintf(convname, sizeof(convname), "%s/%s", src, dst);
+
+       if (__isthreaded)
+               _pthread_mutex_lock(&lock);
+
+       /* 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) {
+                       TAILQ_REMOVE(&shared_unused, ci, ci_tailq_entry);
+                       shared_num_unused--;
+               }
+               ci->ci_used_count++;
+               *rci = ci;
+               goto quit;
+       }
+
+       /* create new entry */
+       ret = open_shared(&ci, basedir, convname, src, dst);
+       if (ret)
+               goto quit;
+
+       _CITRUS_HASH_INSERT(&shared_pool, ci, ci_hash_entry, hashval);
+       ci->ci_used_count = 1;
+       *rci = ci;
+
+quit:
+       if (__isthreaded)
+               _pthread_mutex_unlock(&lock);
+
+       return ret;
+}
+
+static void
+release_shared(struct _citrus_iconv_shared * __restrict ci)
+{
+       if (__isthreaded)
+               _pthread_mutex_lock(&lock);
+
+       ci->ci_used_count--;
+       if (ci->ci_used_count == 0) {
+               /* 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);
+               }
+       }
+
+       if (__isthreaded)
+               _pthread_mutex_unlock(&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;
+       struct _citrus_iconv *cv;
+       char realsrc[PATH_MAX], realdst[PATH_MAX];
+       char buf[PATH_MAX], path[PATH_MAX];
+
+       init_cache();
+
+       /* resolve codeset name aliases */
+       snprintf(path, sizeof(path), "%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);
+
+       /* sanity check */
+       if (strchr(realsrc, '/') != NULL || strchr(realdst, '/'))
+               return EINVAL;
+
+       /* get shared record */
+       ret = get_shared(&ci, basedir, realsrc, realdst);
+       if (ret)
+               return ret;
+
+       /* create/init context */
+       cv = malloc(sizeof(*cv));
+       if (cv == NULL) {
+               ret = errno;
+               release_shared(ci);
+               return ret;
+       }
+       cv->cv_shared = ci;
+       ret = (*ci->ci_ops->io_init_context)(cv);
+       if (ret) {
+               release_shared(ci);
+               free(cv);
+               return ret;
+       }
+       *rcv = cv;
+
+       return 0;
+}
+
+/*
+ * _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);
+       }
+}
diff --git a/lib/libc/citrus/citrus_iconv.h b/lib/libc/citrus/citrus_iconv.h
new file mode 100644 (file)
index 0000000..0d2739a
--- /dev/null
@@ -0,0 +1,69 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_iconv.h,v 1.3 2003/07/10 08:50:43 tshiozak Exp $    */
+/*     $DragonFly: src/lib/libc/citrus/citrus_iconv.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 && (out || !outbytes));
+
+       return (*cv->cv_shared->ci_ops->io_convert)(cv, in, inbytes, out,
+                                                   outbytes, flags, nresults);
+}
+
+#endif
diff --git a/lib/libc/citrus/citrus_iconv_local.h b/lib/libc/citrus/citrus_iconv_local.h
new file mode 100644 (file)
index 0000000..9c834c9
--- /dev/null
@@ -0,0 +1,108 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_iconv_local.h,v 1.2 2003/07/01 09:42:16 tshiozak Exp $      */
+/*     $DragonFly: src/lib/libc/citrus/citrus_iconv_local.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 --git a/lib/libc/citrus/citrus_lookup.c b/lib/libc/citrus/citrus_lookup.c
new file mode 100644 (file)
index 0000000..6ca9970
--- /dev/null
@@ -0,0 +1,353 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_lookup.c,v 1.3 2004/07/21 14:16:34 tshiozak Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_lookup.c,v 1.1 2005/03/11 23:33:53 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 <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>
+
+#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;
+       free(cl->cl_key);
+       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_MAX];
+
+       snprintf(path, sizeof(path), "%s.db", name);
+       ret = _map_file(&r, 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 && (q-p != cl->cl_keylen ||
+                          memcmp(p, cl->cl_key, (size_t)(q-p)) != 0))
+               goto retry;
+
+       /* found a entry */
+       if (key)
+               /* LINTED: discard const */
+               _region_init(key, (char *)p, q-p);
+       p = _bcs_skip_ws_len(q, &len);
+       if (data)
+               /* LINTED: discard const */
+               _region_init(data, len ? (char *)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;
+       free(cl->cl_key);
+       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)
+               /* LINTED: discard const */
+               _region_init(data, (char *)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));
+       if (cl == NULL)
+               return errno;
+
+       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);
+
+       return ret;
+}
+
+void
+_citrus_lookup_seq_rewind(struct _citrus_lookup *cl)
+{
+       cl->cl_rewind = 1;
+       free(cl->cl_key);
+       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)
+{
+       free(cl->cl_key);
+       (*cl->cl_close)(cl);
+}
+
+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 --git a/lib/libc/citrus/citrus_lookup.h b/lib/libc/citrus/citrus_lookup.h
new file mode 100644 (file)
index 0000000..16562e8
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_lookup.h,v 1.2 2004/07/21 14:16:34 tshiozak Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_lookup.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 --git a/lib/libc/citrus/citrus_lookup_factory.c b/lib/libc/citrus/citrus_lookup_factory.c
new file mode 100644 (file)
index 0000000..8b9b460
--- /dev/null
@@ -0,0 +1,120 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_lookup_factory.c,v 1.4 2003/10/27 00:12:42 lukem Exp $      */
+/*     $DragonFly: src/lib/libc/citrus/citrus_lookup_factory.c,v 1.1 2005/03/11 23:33:53 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/endian.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_bcs.h"
+#include "citrus_db_factory.h"
+#include "citrus_db_hash.h"
+#include "citrus_lookup_factory.h"
+#include "citrus_lookup_file.h"
+
+#define T_COMM '#'
+static int
+convert_line(struct _citrus_db_factory *df, const char *line, size_t len)
+{
+       const char *p;
+       char key[LINE_MAX], data[LINE_MAX];
+
+       /* cut off trailing comment */
+       p = memchr(line, T_COMM, len);
+       if (p)
+               len = p - line;
+
+       /* key */
+       line = _bcs_skip_ws_len(line, &len);
+       if (len == 0)
+               return 0;
+       p = _bcs_skip_nonws_len(line, &len);
+       if (p==line)
+               return 0;
+       snprintf(key, sizeof(key), "%.*s", (int)(p-line), line);
+       _bcs_convert_to_lower(key);
+
+       /* data */
+       line = _bcs_skip_ws_len(p, &len);
+       _bcs_trunc_rws_len(line, &len);
+       snprintf(data, sizeof(data), "%.*s", (int)len, line);
+
+       return _db_factory_addstr_by_s(df, key, data);
+}
+
+static int
+dump_db(struct _citrus_db_factory *df, struct _region *r)
+{
+       size_t size;
+       void *ptr;
+
+       size = _db_factory_calc_size(df);
+       ptr = malloc(size);
+       if (ptr == NULL)
+               return errno;
+       _region_init(r, ptr, size);
+
+       return _db_factory_serialize(df, _CITRUS_LOOKUP_MAGIC, r);
+}
+
+int
+_citrus_lookup_factory_convert(FILE *out, FILE *in)
+{
+       struct _citrus_db_factory *df;
+       struct _region r;
+       char *line;
+       size_t size;
+       int ret;
+
+       ret = _db_factory_create(&df, &_db_hash_std, NULL);
+       if (ret)
+               return ret;
+
+       while ((line = fgetln(in, &size)) != NULL)
+               if ((ret = convert_line(df, line, size))) {
+                       _db_factory_free(df);
+                       return ret;
+               }
+
+       ret = dump_db(df, &r);
+       _db_factory_free(df);
+       if (ret)
+               return ret;
+
+       if (fwrite(_region_head(&r), _region_size(&r), 1, out) != 1)
+               return errno;
+
+       return 0;
+}
diff --git a/lib/libc/citrus/citrus_lookup_factory.h b/lib/libc/citrus/citrus_lookup_factory.h
new file mode 100644 (file)
index 0000000..fa20d4d
--- /dev/null
@@ -0,0 +1,37 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_lookup_factory.h,v 1.1 2003/06/25 09:51:35 tshiozak Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_lookup_factory.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#ifndef _CITRUS_LOOKUP_FACTORY_H_
+#define _CITRUS_LOOKUP_FACTORY_H_
+
+__BEGIN_DECLS
+int    _citrus_lookup_factory_convert(FILE *, FILE *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/citrus/citrus_lookup_file.h b/lib/libc/citrus/citrus_lookup_file.h
new file mode 100644 (file)
index 0000000..728822c
--- /dev/null
@@ -0,0 +1,35 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_lookup_factory.h,v 1.1 2003/06/25 09:51:35 tshiozak Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_lookup_file.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#ifndef _CITRUS_LOOKUP_FILE_H_
+#define _CITRUS_LOOKUP_FILE_H_
+
+#define _CITRUS_LOOKUP_MAGIC   "LOOKUP\0\0"
+
+#endif
diff --git a/lib/libc/citrus/citrus_mapper.c b/lib/libc/citrus/citrus_mapper.c
new file mode 100644 (file)
index 0000000..0392ca6
--- /dev/null
@@ -0,0 +1,412 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_mapper.c,v 1.6 2004/12/30 05:05:01 christos Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_mapper.c,v 1.1 2005/03/11 23:33:53 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 "namespace.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+#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
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+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 stat st;
+       int ret;
+       char path[PATH_MAX];
+       struct _citrus_mapper_area *ma;
+
+       if (__isthreaded)
+               _pthread_mutex_lock(&lock);
+
+       if (*rma != NULL) {
+               ret = 0;
+               goto quit;
+       }
+
+       snprintf(path, PATH_MAX, "%s/%s", area, _CITRUS_MAPPER_DIR);
+
+       ret = stat(path, &st);
+       if (ret)
+               goto quit;
+
+       ma = malloc(sizeof(*ma));
+       if (ma == NULL) {
+               ret = errno;
+               goto quit;
+       }
+       ma->ma_dir = strdup(area);
+       if (ma->ma_dir == NULL) {
+               ret = errno;
+               free(ma->ma_dir);
+               goto quit;
+       }
+       _CITRUS_HASH_INIT(&ma->ma_cache, CM_HASH_SIZE);
+
+       *rma = ma;
+       ret = 0;
+quit:
+       if (__isthreaded)
+               _pthread_mutex_unlock(&lock);
+
+       return ret;
+}
+
+
+/*
+ * 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_MAX];
+
+       /* create mapper.dir path */
+       snprintf(path, PATH_MAX, "%s/%s", dir, _CITRUS_MAPPER_DIR);
+
+       /* open read stream */
+       ret = _map_file(&r, 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);
+       strlcpy(p, cp, (size_t)(cq-cp+1));
+       p += cq-cp+1;
+
+       /* get variable */
+       *variable = p;
+       cp = _bcs_skip_ws_len(cq, &len);
+       strlcpy(p, cp, len+1);
+
+       ret = 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);
+               }
+               _citrus_unload_module(cm->cm_module);
+       }
+       free(cm->cm_traits);
+       free(cm);
+}
+
+/*
+ * 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));
+       if (!cm)
+               return errno;
+
+       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) {
+               ret = EOPNOTSUPP;
+               goto err;
+       }
+       cm->cm_ops = malloc(sizeof(*cm->cm_ops));
+       if (!cm->cm_ops) {
+               ret = errno;
+               goto err;
+       }
+       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)
+               goto err;
+
+       /* allocate traits structure */
+       cm->cm_traits = malloc(sizeof(*cm->cm_traits));
+       if (cm->cm_traits == NULL) {
+               ret = errno;
+               goto err;
+       }
+       /* 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[PATH_MAX];
+       const char *module, *variable;
+       struct _citrus_mapper *cm;
+       int hashval;
+
+       if (__isthreaded)
+               _pthread_mutex_lock(&lock);
+
+       /* 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 quit;
+       }
+
+       /* search mapper entry */
+       ret = lookup_mapper_entry(ma->ma_dir, mapname, linebuf, PATH_MAX,
+                                 &module, &variable);
+       if (ret)
+               goto quit;
+
+       /* open mapper */
+       ret = mapper_open(ma, &cm, module, variable);
+       if (ret)
+               goto quit;
+       cm->cm_key = strdup(mapname);
+       if (cm->cm_key == NULL) {
+               ret = errno;
+               if (__isthreaded)
+                       _pthread_mutex_unlock(&lock);
+               _mapper_close(cm);
+               return ret;
+       }
+
+       /* insert to the cache */
+       cm->cm_refcount = 1;
+       _CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval);
+
+       *rcm = cm;
+       ret = 0;
+quit:
+       if (__isthreaded)
+               _pthread_mutex_unlock(&lock);
+       return ret;
+}
+
+/*
+ * _citrus_mapper_close:
+ *     close the specified mapper.
+ */
+void
+_citrus_mapper_close(struct _citrus_mapper *cm)
+{
+       if (cm) {
+               if (__isthreaded)
+                       _pthread_mutex_lock(&lock);
+               if (cm->cm_refcount == REFCOUNT_PERSISTENT)
+                       goto quit;
+               if (cm->cm_refcount > 0) {
+                       if (--cm->cm_refcount > 0)
+                               goto quit;
+                       _CITRUS_HASH_REMOVE(cm, cm_entry);
+                       free(cm->cm_key);
+               }
+               if (__isthreaded)
+                       _pthread_mutex_unlock(&lock);
+               mapper_close(cm);
+               return;
+quit:
+               if (__isthreaded)
+                       _pthread_mutex_unlock(&lock);
+       }
+}
+
+/*
+ * _citrus_mapper_set_persistent:
+ *     set persistent count.
+ */
+void
+_citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)
+{
+       if (__isthreaded)
+               _pthread_mutex_lock(&lock);
+       cm->cm_refcount = REFCOUNT_PERSISTENT;
+       if (__isthreaded)
+               _pthread_mutex_unlock(&lock);
+}
diff --git a/lib/libc/citrus/citrus_mapper.h b/lib/libc/citrus/citrus_mapper.h
new file mode 100644 (file)
index 0000000..c466b56
--- /dev/null
@@ -0,0 +1,143 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_mapper.h,v 1.3 2003/07/12 15:39:19 tshiozak Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_mapper.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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 --git a/lib/libc/citrus/citrus_mapper_local.h b/lib/libc/citrus/citrus_mapper_local.h
new file mode 100644 (file)
index 0000000..ddef553
--- /dev/null
@@ -0,0 +1,106 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_mapper_local.h,v 1.1 2003/06/25 09:51:36 tshiozak Exp $     */
+/*     $DragonFly: src/lib/libc/citrus/citrus_mapper_local.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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, u_int32_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 --git a/lib/libc/citrus/citrus_memstream.c b/lib/libc/citrus/citrus_memstream.c
new file mode 100644 (file)
index 0000000..df8ff72
--- /dev/null
@@ -0,0 +1,149 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_memstream.c,v 1.2 2004/01/02 21:49:35 itojun Exp $  */
+/*     $DragonFly: src/lib/libc/citrus/citrus_memstream.c,v 1.1 2005/03/11 23:33:53 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/types.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 (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 --git a/lib/libc/citrus/citrus_memstream.h b/lib/libc/citrus/citrus_memstream.h
new file mode 100644 (file)
index 0000000..ac4c9e7
--- /dev/null
@@ -0,0 +1,176 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_memstream.h,v 1.2 2004/12/30 05:01:19 christos Exp $        */
+/*     $DragonFly: src/lib/libc/citrus/citrus_memstream.h,v 1.1 2005/03/11 23:33:53 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.
+ *
+ */
+
+#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_rewind(struct _citrus_memory_stream *ms)
+{
+       ms->ms_pos = 0;
+}
+
+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 += ms->ms_pos;
+               if (pos>=sz)
+                       return -1;
+               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 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;
+}
+
+#endif
diff --git a/lib/libc/citrus/citrus_mmap.c b/lib/libc/citrus/citrus_mmap.c
new file mode 100644 (file)
index 0000000..67fc738
--- /dev/null
@@ -0,0 +1,96 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_mmap.c,v 1.3 2005/01/19 00:52:37 mycroft Exp $      */
+/*     $DragonFly: src/lib/libc/citrus/citrus_mmap.c,v 1.1 2005/03/11 23:33:53 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/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#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)
+{
+       int fd, ret = 0;
+       struct stat st;
+       void *head;
+
+       _DIAGASSERT(r != NULL);
+
+       _region_init(r, NULL, 0);
+
+       if ((fd = open(path, O_RDONLY)) == -1)
+               return errno;
+       if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+               ret = errno;
+               goto error;
+       }
+
+       if (fstat(fd, &st)  == -1) {
+               ret = errno;
+               goto error;
+       }
+       if (!S_ISREG(st.st_mode)) {
+               ret = EOPNOTSUPP;
+               goto error;
+       }
+
+       head = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_PRIVATE,
+           fd, (off_t)0);
+       if (head == MAP_FAILED) {
+               ret = errno;
+               goto error;
+       }
+       _region_init(r, head, (size_t)st.st_size);
+
+error:
+       (void)close(fd);
+       return ret;
+}
+
+void
+_citrus_unmap_file(struct _citrus_region *r)
+{
+       _DIAGASSERT(r != NULL);
+
+       if (_region_head(r) != NULL) {
+               (void)munmap(_region_head(r), _region_size(r));
+               _region_init(r, NULL, 0);
+       }
+}
diff --git a/lib/libc/citrus/citrus_mmap.h b/lib/libc/citrus/citrus_mmap.h
new file mode 100644 (file)
index 0000000..071d34d
--- /dev/null
@@ -0,0 +1,40 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_mmap.h,v 1.1 2003/06/25 09:51:38 tshiozak Exp $     */
+/*     $DragonFly: src/lib/libc/citrus/citrus_mmap.h,v 1.1 2005/03/11 23:33:53 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.
+ *
+ */
+
+#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 --git a/lib/libc/citrus/citrus_module.c b/lib/libc/citrus/citrus_module.c
new file mode 100644 (file)
index 0000000..499fa7d
--- /dev/null
@@ -0,0 +1,358 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_module.c,v 1.4 2004/12/21 09:00:01 yamt Exp $       */
+/*     $DragonFly: src/lib/libc/citrus/citrus_module.c,v 1.1 2005/03/11 23:33:53 joerg 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.
+ */
+
+/*-
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 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.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <locale.h>
+#include <stddef.h>
+#include <paths.h>
+#include "citrus_module.h"
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <dlfcn.h>
+
+#ifdef _I18N_DYNAMIC
+
+static int _getdewey(int [], char *);
+static int _cmpndewey(int [], int, int [], int);
+static const char *_findshlib(char *, int *, int *);
+
+static char *_pathI18nModule = NULL;
+
+/* from libexec/ld.aout_so/shlib.c */
+#undef major
+#undef minor
+#define MAXDEWEY       3       /*ELF*/
+
+static int
+_getdewey(int dewey[], char *cp)
+{
+       int     i, n;
+
+       _DIAGASSERT(dewey != NULL);
+       _DIAGASSERT(cp != NULL);
+
+       for (n = 0, i = 0; i < MAXDEWEY; i++) {
+               if (*cp == '\0')
+                       break;
+
+               if (*cp == '.') cp++;
+               if (*cp < '0' || '9' < *cp)
+                       return 0;
+
+               dewey[n++] = (int)strtol(cp, &cp, 10);
+       }
+
+       return n;
+}
+
+/*
+ * Compare two dewey arrays.
+ * Return -1 if `d1' represents a smaller value than `d2'.
+ * Return  1 if `d1' represents a greater value than `d2'.
+ * Return  0 if equal.
+ */
+static int
+_cmpndewey(int d1[], int n1, int d2[], int n2)
+{
+       register int    i;
+
+       _DIAGASSERT(d1 != NULL);
+       _DIAGASSERT(d2 != NULL);
+
+       for (i = 0; i < n1 && i < n2; i++) {
+               if (d1[i] < d2[i])
+                       return -1;
+               if (d1[i] > d2[i])
+                       return 1;
+       }
+
+       if (n1 == n2)
+               return 0;
+
+       if (i == n1)
+               return -1;
+
+       if (i == n2)
+               return 1;
+
+       /* XXX cannot happen */
+       return 0;
+}
+
+static const char *
+_findshlib(char *name, int *majorp, int *minorp)
+{
+       int             dewey[MAXDEWEY];
+       int             ndewey;
+       int             tmp[MAXDEWEY];
+       int             i;
+       int             len;
+       char            *lname;
+       static char     path[PATH_MAX];
+       int             major, minor;
+       const char      *search_dirs[1];
+       const int       n_search_dirs = 1;
+
+       _DIAGASSERT(name != NULL);
+       _DIAGASSERT(majorp != NULL);
+       _DIAGASSERT(minorp != NULL);
+
+       major = *majorp;
+       minor = *minorp;
+       path[0] = '\0';
+       search_dirs[0] = _pathI18nModule;
+       len = strlen(name);
+       lname = name;
+
+       ndewey = 0;
+
+       for (i = 0; i < n_search_dirs; i++) {
+               DIR             *dd = opendir(search_dirs[i]);
+               struct dirent   *dp;
+               int             found_dot_a = 0;
+               int             found_dot_so = 0;
+
+               if (dd == NULL)
+                       continue;
+
+               while ((dp = readdir(dd)) != NULL) {
+                       int     n;
+
+                       if (dp->d_namlen < len + 4)
+                               continue;
+                       if (strncmp(dp->d_name, lname, (size_t)len) != 0)
+                               continue;
+                       if (strncmp(dp->d_name+len, ".so.", 4) != 0)
+                               continue;
+
+                       if ((n = _getdewey(tmp, dp->d_name+len+4)) == 0)
+                               continue;
+
+                       if (major != -1 && found_dot_a)
+                               found_dot_a = 0;
+
+                       /* XXX should verify the library is a.out/ELF? */
+
+                       if (major == -1 && minor == -1) {
+                               goto compare_version;
+                       } else if (major != -1 && minor == -1) {
+                               if (tmp[0] == major)
+                                       goto compare_version;
+                       } else if (major != -1 && minor != -1) {
+                               if (tmp[0] == major) {
+                                       if (n == 1 || tmp[1] >= minor)
+                                               goto compare_version;
+                               }
+                       }
+
+                       /* else, this file does not qualify */
+                       continue;
+
+               compare_version:
+                       if (_cmpndewey(tmp, n, dewey, ndewey) <= 0)
+                               continue;
+
+                       /* We have a better version */
+                       found_dot_so = 1;
+                       snprintf(path, sizeof(path), "%s/%s", search_dirs[i],
+                           dp->d_name);
+                       found_dot_a = 0;
+                       bcopy(tmp, dewey, sizeof(dewey));
+                       ndewey = n;
+                       *majorp = dewey[0];
+                       *minorp = dewey[1];
+               }
+               closedir(dd);
+
+               if (found_dot_a || found_dot_so)
+                       /*
+                        * There's a lib in this dir; take it.
+                        */
+                       return path[0] ? path : NULL;
+       }
+
+       return path[0] ? path : NULL;
+}
+
+void *
+_citrus_find_getops(_citrus_module_t handle, const char *modname,
+                   const char *ifname)
+{
+       char name[PATH_MAX];
+       void *p;
+
+       _DIAGASSERT(handle != NULL);
+       _DIAGASSERT(modname != NULL);
+       _DIAGASSERT(ifname != NULL);
+
+       snprintf(name, sizeof(name), "_citrus_%s_%s_getops", modname, ifname);
+       p = dlsym((void *)handle, name);
+       return p;
+}
+
+int
+_citrus_load_module(_citrus_module_t *rhandle, const char *encname)
+{
+       const char *p;
+       char path[PATH_MAX];
+       int maj, min;
+       void *handle;
+
+       _DIAGASSERT(rhandle != NULL);
+
+       if (_pathI18nModule == NULL) {
+               p = getenv("PATH_I18NMODULE");
+               if (p != NULL && !issetugid()) {
+                       _pathI18nModule = strdup(p);
+                       if (_pathI18nModule == NULL)
+                               return ENOMEM;
+               } else
+                       _pathI18nModule = _PATH_I18NMODULE;
+       }
+
+       (void)snprintf(path, sizeof(path), "lib%s", encname);
+       maj = I18NMODULE_MAJOR;
+       min = -1;
+       p = _findshlib(path, &maj, &min);
+       if (!p)
+               return (EINVAL);
+       handle = dlopen(p, RTLD_LAZY);
+       if (!handle)
+               return (EINVAL);
+
+       *rhandle = (_citrus_module_t)handle;
+
+       return (0);
+}
+
+void
+_citrus_unload_module(_citrus_module_t handle)
+{
+       if (handle)
+               dlclose((void *)handle);
+}
+#else
+/* !_I18N_DYNAMIC */
+
+void *
+/*ARGSUSED*/
+_citrus_find_getops(_citrus_module_t handle, const char *modname,
+                   const char *ifname)
+{
+       return (NULL);
+}
+
+int
+/*ARGSUSED*/
+_citrus_load_module(_citrus_module_t *rhandle, char const *modname)
+{
+       return (EINVAL);
+}
+
+void
+/*ARGSUSED*/
+_citrus_unload_module(_citrus_module_t handle)
+{
+}
+#endif
diff --git a/lib/libc/citrus/citrus_module.h b/lib/libc/citrus/citrus_module.h
new file mode 100644 (file)
index 0000000..84b8493
--- /dev/null
@@ -0,0 +1,44 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_module.h,v 1.1 2002/03/17 22:14:20 tshiozak Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_module.h,v 1.1 2005/03/11 23:33:53 joerg 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 --git a/lib/libc/citrus/citrus_namespace.h b/lib/libc/citrus/citrus_namespace.h
new file mode 100644 (file)
index 0000000..92a12d1
--- /dev/null
@@ -0,0 +1,224 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_namespace.h,v 1.4 2004/07/21 14:16:34 tshiozak Exp $        */
+/*     $DragonFly: src/lib/libc/citrus/citrus_namespace.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#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
+#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_seek                _citrus_memory_stream_seek
+#define _memstream_rewind      _citrus_memory_stream_rewind
+#define _memstream_remainder   _citrus_memory_stream_remainder
+#define _memstream_getc                _citrus_memory_stream_getc
+#define _memstream_peek                _citrus_memory_stream_peek
+#define _memstream_getregion   _citrus_memory_stream_getregion
+#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
+#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_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
+#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 --git a/lib/libc/citrus/citrus_none.c b/lib/libc/citrus/citrus_none.c
new file mode 100644 (file)
index 0000000..d3fc6a7
--- /dev/null
@@ -0,0 +1,476 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_none.c,v 1.12 2004/01/18 03:57:30 yamt Exp $        */
+/*     $DragonFly: src/lib/libc/citrus/citrus_none.c,v 1.1 2005/03/11 23:33:53 joerg 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 <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <locale.h>
+#include <wchar.h>
+#include <sys/types.h>
+
+#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)
+{
+       return (_citrus_NONE_ctype_mbsrtowcs(cl, wcs, (const char **)&s, 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)*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)
+{
+       return (_citrus_NONE_ctype_wcsrtombs(cl, s, (const wchar_t **)&pwcs, 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);
+}
diff --git a/lib/libc/citrus/citrus_none.h b/lib/libc/citrus/citrus_none.h
new file mode 100644 (file)
index 0000000..e111a39
--- /dev/null
@@ -0,0 +1,37 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_none.h,v 1.3 2003/06/25 09:51:38 tshiozak Exp $     */
+/*     $DragonFly: src/lib/libc/citrus/citrus_none.h,v 1.1 2005/03/11 23:33:53 joerg 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 --git a/lib/libc/citrus/citrus_pivot_factory.c b/lib/libc/citrus/citrus_pivot_factory.c
new file mode 100644 (file)
index 0000000..963abbe
--- /dev/null
@@ -0,0 +1,222 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_pivot_factory.c,v 1.4 2004/01/02 21:49:35 itojun Exp $      */
+/*     $DragonFly: src/lib/libc/citrus/citrus_pivot_factory.c,v 1.1 2005/03/11 23:33:53 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/endian.h>
+#include <sys/queue.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_bcs.h"
+#include "citrus_db_factory.h"
+#include "citrus_db_hash.h"
+#include "citrus_pivot_file.h"
+#include "citrus_pivot_factory.h"
+
+struct src_entry {
+       char *se_name;
+       struct _citrus_db_factory *se_df;
+       STAILQ_ENTRY(src_entry) se_entry;
+};
+STAILQ_HEAD(src_head, src_entry);
+
+static int
+find_src(struct src_head *sh, struct src_entry **rse, const char *name)
+{
+       int ret;
+       struct src_entry *se;
+
+       STAILQ_FOREACH(se, sh, se_entry) {
+               if (_bcs_strcasecmp(se->se_name, name) == 0) {
+                       *rse = se;
+                       return 0;
+               }
+       }
+       se = malloc(sizeof(*se));
+       if (se == NULL)
+               return errno;
+       se->se_name = strdup(name);
+       if (se->se_name == NULL) {
+               ret = errno;
+               free(se);
+               return ret;
+       }
+       ret = _db_factory_create(&se->se_df, &_db_hash_std, NULL);
+       if (ret) {
+               free(se->se_name);
+               free(se);
+               return ret;
+       }
+       STAILQ_INSERT_TAIL(sh, se, se_entry);
+       *rse = se;
+
+       return 0;
+}
+
+static void
+free_src(struct src_head *sh)
+{
+       struct src_entry *se;
+
+       while ((se = STAILQ_FIRST(sh)) != NULL) {
+               STAILQ_REMOVE_HEAD(sh, se_entry);
+               _db_factory_free(se->se_df);
+               free(se->se_name);
+               free(se);
+       }
+}
+
+
+#define T_COMM '#'
+static int
+convert_line(struct src_head *sh, const char *line, size_t len)
+{
+       int ret;
+       struct src_entry *se;
+       const char *p;
+       char key1[LINE_MAX], key2[LINE_MAX], data[LINE_MAX];
+       uint32_t val;
+
+       /* cut off trailing comment */
+       p = memchr(line, T_COMM, len);
+       if (p)
+               len = p - line;
+
+       /* key1 */
+       line = _bcs_skip_ws_len(line, &len);
+       if (len == 0)
+               return 0;
+       p = _bcs_skip_nonws_len(line, &len);
+       if (p==line)
+               return 0;
+       snprintf(key1, sizeof(key1), "%.*s", (int)(p-line), line);
+
+       /* key2 */
+       line = _bcs_skip_ws_len(p, &len);
+       if (len == 0)
+               return 0;
+       p = _bcs_skip_nonws_len(line, &len);
+       if (p==line)
+               return 0;
+       snprintf(key2, sizeof(key2), "%.*s", (int)(p-line), line);
+
+       /* data */
+       line = _bcs_skip_ws_len(p, &len);
+       _bcs_trunc_rws_len(line, &len);
+       snprintf(data, sizeof(data), "%.*s", (int)len, line);
+       /* LINTED: discard const */
+       val = strtoul(data, __DECONST(char **, &p), 0);
+       if (*p != '\0')
+               return EFTYPE;
+
+       /* insert to DB */
+       ret = find_src(sh, &se, key1);
+       if (ret)
+               return ret;
+
+       return _db_factory_add32_by_s(se->se_df, key2, val);
+}
+
+static int
+dump_db(struct src_head *sh, struct _region *r)
+{
+       int ret;
+       struct _db_factory *df;
+       struct src_entry *se;
+       size_t size;
+       void *ptr;
+       struct _region subr;
+
+       ret = _db_factory_create(&df, &_db_hash_std, NULL);
+       if (ret)
+               return ret;
+
+       STAILQ_FOREACH(se, sh, se_entry) {
+               size = _db_factory_calc_size(se->se_df);
+               ptr = malloc(size);
+               if (ptr == NULL)
+                       goto quit;
+               _region_init(&subr, ptr, size);
+               ret = _db_factory_serialize(se->se_df, _CITRUS_PIVOT_SUB_MAGIC,
+                                           &subr);
+               if (ret)
+                       goto quit;
+               ret = _db_factory_add_by_s(df, se->se_name, &subr, 1);
+               if (ret)
+                       goto quit;
+       }
+
+       size = _db_factory_calc_size(df);
+       ptr = malloc(size);
+       if (ptr == NULL)
+               goto quit;
+       _region_init(r, ptr, size);
+
+       ret = _db_factory_serialize(df, _CITRUS_PIVOT_MAGIC, r);
+       ptr = NULL;
+
+quit:
+       free(ptr);
+       _db_factory_free(df);
+       return ret;
+}
+
+int
+_citrus_pivot_factory_convert(FILE *out, FILE *in)
+{
+       struct src_head sh;
+       struct _region r;
+       char *line;
+       size_t size;
+       int ret;
+
+       STAILQ_INIT(&sh);
+
+       while ((line = fgetln(in, &size)) != NULL)
+               if ((ret = convert_line(&sh, line, size))) {
+                       free_src(&sh);
+                       return ret;
+               }
+
+       ret = dump_db(&sh, &r);
+       free_src(&sh);
+       if (ret)
+               return ret;
+
+       if (fwrite(_region_head(&r), _region_size(&r), 1, out) != 1)
+               return errno;
+
+       return 0;
+}
diff --git a/lib/libc/citrus/citrus_pivot_factory.h b/lib/libc/citrus/citrus_pivot_factory.h
new file mode 100644 (file)
index 0000000..913a038
--- /dev/null
@@ -0,0 +1,37 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_pivot_factory.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $    */
+/*     $DragonFly: src/lib/libc/citrus/citrus_pivot_factory.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#ifndef _CITRUS_PIVOT_FACTORY_H_
+#define _CITRUS_PIVOT_FACTORY_H_
+
+__BEGIN_DECLS
+int    _citrus_pivot_factory_convert(FILE *, FILE *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/citrus/citrus_pivot_file.h b/lib/libc/citrus/citrus_pivot_file.h
new file mode 100644 (file)
index 0000000..2a1fabb
--- /dev/null
@@ -0,0 +1,36 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_pivot_file.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $       */
+/*     $DragonFly: src/lib/libc/citrus/citrus_pivot_file.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#ifndef _CITRUS_PIVOT_FILE_H_
+#define _CITRUS_PIVOT_FILE_H_
+
+#define _CITRUS_PIVOT_MAGIC    "CSPIVOT\0"
+#define _CITRUS_PIVOT_SUB_MAGIC        "CSPIVSUB"
+
+#endif
diff --git a/lib/libc/citrus/citrus_region.h b/lib/libc/citrus/citrus_region.h
new file mode 100644 (file)
index 0000000..d4cd3a0
--- /dev/null
@@ -0,0 +1,94 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_region.h,v 1.5 2004/12/30 05:00:42 christos Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_region.h,v 1.1 2005/03/11 23:33:53 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.
+ *
+ */
+
+#ifndef _CITRUS_REGION_H_
+#define _CITRUS_REGION_H_
+
+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), 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), 4);
+       return val;
+}
+
+#endif
diff --git a/lib/libc/citrus/citrus_stdenc.c b/lib/libc/citrus/citrus_stdenc.c
new file mode 100644 (file)
index 0000000..701851f
--- /dev/null
@@ -0,0 +1,179 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_stdenc.c,v 1.2 2003/07/10 08:50:44 tshiozak Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_stdenc.c,v 1.1 2005/03/11 23:33:53 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/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 */
+};
+
+#ifdef _I18N_DYNAMIC
+
+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));
+       if (ce==NULL) {
+               ret = errno;
+               goto bad;
+       }
+       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));
+       if (ce->ce_ops == NULL) {
+               ret = errno;
+               goto bad;
+       }
+
+       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 */
+
+       /* 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)
+               goto bad;
+
+       /* allocate traits */
+       ce->ce_traits = malloc(sizeof(*ce->ce_traits));
+       if (ce->ce_traits == NULL) {
+               ret = errno;
+               goto bad;
+       }
+       /* 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);
+               }
+               free(ce->ce_traits);
+               _citrus_unload_module(ce->ce_module);
+       }
+       free(ce);
+}
+
+#else
+/* !_I18N_DYNAMIC */
+
+int
+/*ARGSUSED*/
+_citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce,
+                   char const * __restrict encname,
+                   const void * __restrict variable, size_t lenvar)
+{
+       if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) {
+               *rce = &_citrus_stdenc_default;
+               return (0);
+       }
+       return (EINVAL);
+}
+
+void
+/*ARGSUSED*/
+_citrus_stdenc_close(struct _citrus_stdenc *ce)
+{
+}
+
+#endif
diff --git a/lib/libc/citrus/citrus_stdenc.h b/lib/libc/citrus/citrus_stdenc.h
new file mode 100644 (file)
index 0000000..a0a046f
--- /dev/null
@@ -0,0 +1,119 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_stdenc.h,v 1.3 2003/07/10 08:50:44 tshiozak Exp $   */
+/*     $DragonFly: src/lib/libc/citrus/citrus_stdenc.h,v 1.1 2005/03/11 23:33:53 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.
+ *
+ */
+
+#ifndef _CITRUS_STDENC_H_
+#define _CITRUS_STDENC_H_
+
+struct _citrus_stdenc;
+struct _citrus_stdenc_ops;
+struct _citrus_stdenc_traits;
+
+#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;
+}
+
+#endif
diff --git a/lib/libc/citrus/citrus_stdenc_local.h b/lib/libc/citrus/citrus_stdenc_local.h
new file mode 100644 (file)
index 0000000..968a5ab
--- /dev/null
@@ -0,0 +1,146 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_stdenc_local.h,v 1.2 2003/06/26 12:09:57 tshiozak Exp $     */
+/*     $DragonFly: src/lib/libc/citrus/citrus_stdenc_local.h,v 1.1 2005/03/11 23:33:53 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.
+ *
+ */
+
+#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)
+
+#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 \
+}
+
+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);
+
+/*
+ * ABI version change log
+ *   0x00000001
+ *     initial version
+ */
+#define _CITRUS_STDENC_ABI_VERSION     0x00000001
+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;
+};
+
+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 --git a/lib/libc/citrus/citrus_stdenc_template.h b/lib/libc/citrus/citrus_stdenc_template.h
new file mode 100644 (file)
index 0000000..e65afbb
--- /dev/null
@@ -0,0 +1,187 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_stdenc_template.h,v 1.2 2003/06/26 12:09:57 tshiozak Exp $  */
+/*     $DragonFly: src/lib/libc/citrus/citrus_stdenc_template.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+/*
+ * 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 = calloc(1, sizeof(_ENCODING_INFO));
+               if (ei == NULL) {
+                       return errno;
+               }
+       }
+
+       ret = _FUNCNAME(encoding_module_init)(ei, var, lenvar);
+       if (ret) {
+               free((void *)ei);
+               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);
+       }
+}
+
+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
+}
diff --git a/lib/libc/citrus/citrus_types.h b/lib/libc/citrus/citrus_types.h
new file mode 100644 (file)
index 0000000..87c517b
--- /dev/null
@@ -0,0 +1,38 @@
+/*     $NetBSD: src/lib/libc/citrus/citrus_types.h,v 1.3 2003/10/27 00:12:42 lukem Exp $       */
+/*     $DragonFly: src/lib/libc/citrus/citrus_types.h,v 1.1 2005/03/11 23:33:53 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.
+ */
+
+#ifndef _CITRUS_TYPES_H_
+#define _CITRUS_TYPES_H_
+
+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 --git a/lib/libc/citrus/modules/citrus_big5.c b/lib/libc/citrus/modules/citrus_big5.c
new file mode 100644 (file)
index 0000000..85569a2
--- /dev/null
@@ -0,0 +1,395 @@
+/*     $NetBSD: src/lib/libc/citrus/modules/citrus_big5.c,v 1.8 2003/08/07 16:42:38 agc Exp $  */
+/*     $DragonFly: src/lib/libc/citrus/modules/citrus_big5.c,v 1.1 2005/03/11 23:33:53 joerg 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/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_ctype.h"
+#include "citrus_stdenc.h"
+#include "citrus_big5.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+       char ch[2];
+       int chlen;
+} _BIG5State;
+
+typedef struct {
+       int dummy;
+} _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(u_int c)
+{
+       c &= 0xff;
+       return ((c >= 0xa1 && c <= 0xfe) ? 2 : 1);
+}
+
+static __inline int
+_citrus_BIG5_check2(u_int c)
+{
+       c &= 0xff;
+       if ((c >= 0x40 && c <= 0x7f) || (c >= 0xa1 && c <= 0xfe))
+               return 1;
+       else
+               return 0;
+}
+
+static int
+/*ARGSUSED*/
+_citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei,
+                                 const void * __restrict var, size_t lenvar)
+{
+       _DIAGASSERT(ei != NULL);
+
+       memset((void *)ei, 0, sizeof(*ei));
+
+       return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_BIG5_encoding_module_uninit(_BIG5EncodingInfo *ei)
+{
+}
+
+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(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(psenc->ch[1] & 0xff))
+                       goto ilseq;
+               wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
+               break;
+       default:
+               /* illegal state */
+               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,
+         &nb