summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/Makefile3
-rw-r--r--lib/libc/iconv/Makefile.inc18
-rw-r--r--lib/libc/iconv/Symbol.map101
-rw-r--r--lib/libc/iconv/__iconv_get_list.395
-rw-r--r--lib/libc/iconv/_strtol.h167
-rw-r--r--lib/libc/iconv/_strtoul.h126
-rw-r--r--lib/libc/iconv/citrus_aliasname_local.h49
-rw-r--r--lib/libc/iconv/citrus_bcs.c168
-rw-r--r--lib/libc/iconv/citrus_bcs.h102
-rw-r--r--lib/libc/iconv/citrus_bcs_strtol.c57
-rw-r--r--lib/libc/iconv/citrus_bcs_strtoul.c57
-rw-r--r--lib/libc/iconv/citrus_csmapper.c383
-rw-r--r--lib/libc/iconv/citrus_csmapper.h48
-rw-r--r--lib/libc/iconv/citrus_db.c331
-rw-r--r--lib/libc/iconv/citrus_db.h70
-rw-r--r--lib/libc/iconv/citrus_db_factory.c348
-rw-r--r--lib/libc/iconv/citrus_db_factory.h57
-rw-r--r--lib/libc/iconv/citrus_db_file.h85
-rw-r--r--lib/libc/iconv/citrus_db_hash.c64
-rw-r--r--lib/libc/iconv/citrus_db_hash.h37
-rw-r--r--lib/libc/iconv/citrus_esdb.c374
-rw-r--r--lib/libc/iconv/citrus_esdb.h58
-rw-r--r--lib/libc/iconv/citrus_esdb_file.h45
-rw-r--r--lib/libc/iconv/citrus_fix_grouping.h53
-rw-r--r--lib/libc/iconv/citrus_hash.c51
-rw-r--r--lib/libc/iconv/citrus_hash.h59
-rw-r--r--lib/libc/iconv/citrus_iconv.c335
-rw-r--r--lib/libc/iconv/citrus_iconv.h64
-rw-r--r--lib/libc/iconv/citrus_iconv_local.h107
-rw-r--r--lib/libc/iconv/citrus_lock.h35
-rw-r--r--lib/libc/iconv/citrus_lookup.c362
-rw-r--r--lib/libc/iconv/citrus_lookup.h64
-rw-r--r--lib/libc/iconv/citrus_lookup_factory.c121
-rw-r--r--lib/libc/iconv/citrus_lookup_factory.h37
-rw-r--r--lib/libc/iconv/citrus_lookup_file.h35
-rw-r--r--lib/libc/iconv/citrus_mapper.c397
-rw-r--r--lib/libc/iconv/citrus_mapper.h131
-rw-r--r--lib/libc/iconv/citrus_mapper_local.h96
-rw-r--r--lib/libc/iconv/citrus_memstream.c148
-rw-r--r--lib/libc/iconv/citrus_memstream.h226
-rw-r--r--lib/libc/iconv/citrus_mmap.c97
-rw-r--r--lib/libc/iconv/citrus_mmap.h40
-rw-r--r--lib/libc/iconv/citrus_module.c314
-rw-r--r--lib/libc/iconv/citrus_module.h54
-rw-r--r--lib/libc/iconv/citrus_namespace.h241
-rw-r--r--lib/libc/iconv/citrus_none.c238
-rw-r--r--lib/libc/iconv/citrus_none.h36
-rw-r--r--lib/libc/iconv/citrus_pivot_factory.c225
-rw-r--r--lib/libc/iconv/citrus_pivot_factory.h37
-rw-r--r--lib/libc/iconv/citrus_pivot_file.h36
-rw-r--r--lib/libc/iconv/citrus_prop.c444
-rw-r--r--lib/libc/iconv/citrus_prop.h92
-rw-r--r--lib/libc/iconv/citrus_region.h113
-rw-r--r--lib/libc/iconv/citrus_stdenc.c145
-rw-r--r--lib/libc/iconv/citrus_stdenc.h124
-rw-r--r--lib/libc/iconv/citrus_stdenc_local.h161
-rw-r--r--lib/libc/iconv/citrus_stdenc_template.h211
-rw-r--r--lib/libc/iconv/citrus_types.h40
-rw-r--r--lib/libc/iconv/iconv.3305
-rw-r--r--lib/libc/iconv/iconv.c332
-rw-r--r--lib/libc/iconv/iconv_canonicalize.374
-rw-r--r--lib/libc/iconv/iconvctl.3162
-rw-r--r--lib/libc/iconv/iconvlist.393
63 files changed, 8778 insertions, 0 deletions
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index 4eb57de..77c7ce0 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -57,6 +57,9 @@ NOASM=
.include "${.CURDIR}/gdtoa/Makefile.inc"
.include "${.CURDIR}/gen/Makefile.inc"
.include "${.CURDIR}/gmon/Makefile.inc"
+.if ${MK_ICONV} != "no"
+.include "${.CURDIR}/iconv/Makefile.inc"
+.endif
.include "${.CURDIR}/inet/Makefile.inc"
.include "${.CURDIR}/isc/Makefile.inc"
.include "${.CURDIR}/locale/Makefile.inc"
diff --git a/lib/libc/iconv/Makefile.inc b/lib/libc/iconv/Makefile.inc
new file mode 100644
index 0000000..8c43a20
--- /dev/null
+++ b/lib/libc/iconv/Makefile.inc
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+# iconv sources
+.PATH: ${.CURDIR}/iconv
+
+MAN+= iconv.3 iconvctl.3 iconv_canonicalize.3 iconvlist.3 __iconv_get_list.3
+MLINKS+= iconv.3 iconv_open.3 \
+ iconv.3 iconv_open_into.3 \
+ iconv.3 iconv_close.3 \
+ iconv.3 __iconv.3 \
+ __iconv_get_list.3 __iconv_free_list.3
+SRCS+= citrus_bcs.c citrus_bcs_strtol.c citrus_bcs_strtoul.c \
+ citrus_csmapper.c citrus_db.c citrus_db_factory.c citrus_db_hash.c \
+ citrus_esdb.c citrus_hash.c citrus_iconv.c citrus_lookup.c \
+ citrus_lookup_factory.c citrus_mapper.c citrus_memstream.c \
+ citrus_mmap.c citrus_module.c citrus_none.c citrus_pivot_factory.c \
+ citrus_prop.c citrus_stdenc.c iconv.c
+SYM_MAPS+= ${.CURDIR}/iconv/Symbol.map
diff --git a/lib/libc/iconv/Symbol.map b/lib/libc/iconv/Symbol.map
new file mode 100644
index 0000000..515cddc
--- /dev/null
+++ b/lib/libc/iconv/Symbol.map
@@ -0,0 +1,101 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.2 {
+ __iconv;
+ __iconv_free_list;
+ __iconv_get_list;
+ _citrus_bcs_convert_to_lower;
+ _citrus_bcs_convert_to_upper;
+ _citrus_bcs_isalnum;
+ _citrus_bcs_isalpha;
+ _citrus_bcs_isblank;
+ _citrus_bcs_isdigit;
+ _citrus_bcs_iseol;
+ _citrus_bcs_islower;
+ _citrus_bcs_isspace;
+ _citrus_bcs_isupper;
+ _citrus_bcs_isxdigit;
+ _citrus_bcs_skip_nonws;
+ _citrus_bcs_skip_nonws_len;
+ _citrus_bcs_skip_ws;
+ _citrus_bcs_skip_ws_len;
+ _citrus_bcs_strcasecmp;
+ _citrus_bcs_strncasecmp;
+ _citrus_bcs_strtol;
+ _citrus_bcs_strtoul;
+ _citrus_bcs_tolower;
+ _citrus_bcs_toupper;
+ _citrus_bcs_trunc_ws_len;
+ _citrus_csmapper_open;
+ _citrus_csmapper_close;
+ _citrus_db_factory_add_by_string;
+ _citrus_db_factory_add_string_by_string;
+ _citrus_db_factory_add32_by_string;
+ _citrus_db_factory_calc_size;
+ _citrus_db_factory_create;
+ _citrus_db_factory_serialize;
+ _citrus_db_hash_std;
+ _citrus_db_close;
+ _citrus_db_get_entry;
+ _citrus_db_get_number_of_entries;
+ _citrus_db_lookup;
+ _citrus_db_lookup_by_string;
+ _citrus_db_lookup8_by_string;
+ _citrus_db_lookup16_by_string;
+ _citrus_db_lookup_string_by_string;
+ _citrus_db_open;
+ _citrus_esdb_close;
+ _citrus_esdb_open;
+ _citrus_lookup_factory_convert;
+ _citrus_map_file;
+ _citrus_mapper_close;
+ _citrus_mapper_convert;
+ _citrus_mapper_create_area;
+ _citrus_mapper_get_dst_max;
+ _citrus_mapper_get_src_max;
+ _citrus_mapper_get_state_size;
+ _citrus_mapper_init_state;
+ _citrus_mapper_open;
+ _citrus_mapper_open_direct;
+ _citrus_mapper_set_persistent;
+ _citrus_memory_stream_bind;
+ _citrus_memory_stream_chr;
+ _citrus_memory_stream_getc;
+ _citrus_memory_stream_getln;
+ _citrus_memory_stream_getln_region;
+ _citrus_memory_stream_getregion;
+ _citrus_memory_stream_iseof;
+ _citrus_memory_stream_matchline;
+ _citrus_memory_stream_peek;
+ _citrus_memory_stream_remainder;
+ _citrus_memory_stream_rewind;
+ _citrus_memory_stream_seek;
+ _citrus_memory_stream_skip_ws;
+ _citrus_memory_stream_tell;
+ _citrus_memory_stream_ungetc;
+ _citrus_pivot_factory_convert;
+ _citrus_prop_object_init;
+ _citrus_prop_object_uninit;
+ _citrus_prop_parse_variable;
+ _citrus_prop_read_bool;
+ _citrus_prop_read_character;
+ _citrus_prop_read_character_common;
+ _citrus_prop_read_element;
+ _citrus_prop_read_num;
+ _citrus_prop_read_str;
+ _citrus_prop_read_symbol;
+ _citrus_stdenc_close;
+ _citrus_stdenc_open;
+ _citrus_unmap_file;
+ _libiconv_version;
+ iconv_canonicalize;
+ libiconv;
+ libiconv_close;
+ libiconv_open;
+ libiconv_open_into;
+ libiconv_set_relocation_prefix;
+ libiconvctl;
+ libiconvlist;
+};
diff --git a/lib/libc/iconv/__iconv_get_list.3 b/lib/libc/iconv/__iconv_get_list.3
new file mode 100644
index 0000000..7c8d015
--- /dev/null
+++ b/lib/libc/iconv/__iconv_get_list.3
@@ -0,0 +1,95 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" 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.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 20, 2009
+.Dt __ICONV_GET_LIST 3
+.Os
+.Sh NAME
+.Nm __iconv_get_list
+.Nm __iconv_free_list
+.Nd retrieving a list of character encodings supported by
+.Xr iconv 3
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft int
+.Fn __iconv_get_list "char ***names" "size_t count" "bool paired"
+.Ft void
+.Fn __iconv_free_list "char **names" "size_t count"
+.Sh DESCRIPTION
+The
+.Fn __iconv_get_list
+function obtains a list of character encodings that are supported by the
+.Xr iconv 3
+call.
+The list of the encoding names will be stored in
+.Fa names
+and the number of the entries is stored in
+.Fa count .
+If the
+.Fa paired
+variable is true, the list will be arranged into
+canonical/alias name pairs.
+.Pp
+The
+.Fn __iconv_free_list
+function is to free the allocated memory during the call of
+.Fn __iconv_get_list .
+.Sh RETURN VALUES
+Upon successful completion
+.Fn __iconv_get_list
+returns 0 and set the
+.Fa names
+and
+.Fa count
+arguments.
+Otherwise, \-1 is returned and errno is set to indicate the error.
+.Sh SEE ALSO
+.Xr iconv 3 ,
+.Xr iconvlist 3
+.Sh STANDARDS
+The
+.Nm __iconv_get_list
+and
+.Nm __iconv_free_list
+functions are non-standard interfaces, which appeared in
+the implementation of the Citrus Project.
+The iconv implementation of the Citrus Project was adopted in
+.Fx 9 .
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq gabor@FreeBSD.org .
diff --git a/lib/libc/iconv/_strtol.h b/lib/libc/iconv/_strtol.h
new file mode 100644
index 0000000..d2d9d84
--- /dev/null
+++ b/lib/libc/iconv/_strtol.h
@@ -0,0 +1,167 @@
+/* $FreeBSD$ */
+/* $NetBSD: _strtol.h,v 1.2 2009/05/20 22:03:29 christos Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. 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.
+ * 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.
+ *
+ * Original version ID:
+ * NetBSD: src/lib/libc/locale/_wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp
+ */
+
+/*
+ * function template for strtol, strtoll and strtoimax.
+ *
+ * parameters:
+ * _FUNCNAME : function name
+ * __INT : return type
+ * __INT_MIN : lower limit of the return type
+ * __INT_MAX : upper limit of the return type
+ */
+
+__INT
+_FUNCNAME(const char *nptr, char **endptr, int base)
+{
+ const char *s;
+ __INT acc, cutoff;
+ unsigned char c;
+ int any, cutlim, i, neg;
+
+ /* check base value */
+ if (base && (base < 2 || base > 36)) {
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ errno = EINVAL;
+ if (endptr != NULL)
+ /* LINTED interface specification */
+ *endptr = __DECONST(void *, nptr);
+ return (0);
+#else
+ panic("%s: invalid base %d", __func__, base);
+#endif
+ }
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = (c == '0' ? 8 : 10);
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = (neg ? __INT_MIN : __INT_MAX);
+ cutlim = (int)(cutoff % base);
+ cutoff /= base;
+ if (neg) {
+ if (cutlim > 0) {
+ cutlim -= base;
+ cutoff += 1;
+ }
+ cutlim = -cutlim;
+ }
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ i = c - '0';
+ else if (isalpha(c))
+ i = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
+ else
+ break;
+ if (i >= base)
+ break;
+ if (any < 0)
+ continue;
+ if (neg) {
+ if (acc < cutoff || (acc == cutoff && i > cutlim)) {
+ acc = __INT_MIN;
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ any = -1;
+ errno = ERANGE;
+#else
+ any = 0;
+ break;
+#endif
+ } else {
+ any = 1;
+ acc *= base;
+ acc -= i;
+ }
+ } else {
+ if (acc > cutoff || (acc == cutoff && i > cutlim)) {
+ acc = __INT_MAX;
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ any = -1;
+ errno = ERANGE;
+#else
+ any = 0;
+ break;
+#endif
+ } else {
+ any = 1;
+ acc *= base;
+ acc += i;
+ }
+ }
+ }
+ if (endptr != NULL)
+ /* LINTED interface specification */
+ *endptr = __DECONST(void *, any ? s - 1 : nptr);
+ return(acc);
+}
diff --git a/lib/libc/iconv/_strtoul.h b/lib/libc/iconv/_strtoul.h
new file mode 100644
index 0000000..64e0d46
--- /dev/null
+++ b/lib/libc/iconv/_strtoul.h
@@ -0,0 +1,126 @@
+/* $FreeBSD$ */
+/* $NetBSD: _strtoul.h,v 1.1 2008/08/20 12:42:26 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. 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.
+ * 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.
+ *
+ * Original version ID:
+ * NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp
+ */
+
+/*
+ * function template for strtoul, strtoull and strtoumax.
+ *
+ * parameters:
+ * _FUNCNAME : function name
+ * __UINT : return type
+ * __UINT_MAX : upper limit of the return type
+ */
+
+__UINT
+_FUNCNAME(const char *nptr, char **endptr, int base)
+{
+ const char *s;
+ __UINT acc, cutoff;
+ unsigned char c;
+ int any, cutlim, i, neg;
+
+ /* check base value */
+ if (base && (base < 2 || base > 36)) {
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ errno = EINVAL;
+ return (0);
+#else
+ panic("%s: invalid base %d", __func__, base);
+#endif
+ }
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = (c == '0' ? 8 : 10);
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ cutoff = __UINT_MAX / (__UINT)base;
+ cutlim = (int)(__UINT_MAX % (__UINT)base);
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ i = c - '0';
+ else if (isalpha(c))
+ i = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
+ else
+ break;
+ if (i >= base)
+ break;
+ if (any < 0)
+ continue;
+ if (acc > cutoff || (acc == cutoff && i > cutlim)) {
+ acc = __UINT_MAX;
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ any = -1;
+ errno = ERANGE;
+#else
+ any = 0;
+ break;
+#endif
+ } else {
+ any = 1;
+ acc *= (__UINT)base;
+ acc += i;
+ }
+ }
+ if (neg && any > 0)
+ acc = -acc;
+ if (endptr != NULL)
+ /* LINTED interface specification */
+ *endptr = __DECONST(void *, any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/lib/libc/iconv/citrus_aliasname_local.h b/lib/libc/iconv/citrus_aliasname_local.h
new file mode 100644
index 0000000..687362b
--- /dev/null
+++ b/lib/libc/iconv/citrus_aliasname_local.h
@@ -0,0 +1,49 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_aliasname_local.h,v 1.2 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ALIASNAME_LOCAL_H_
+#define _CITRUS_ALIASNAME_LOCAL_H_
+
+static __inline const char *
+__unaliasname(const char *dbname, const char *alias,
+ void *buf, size_t bufsize)
+{
+
+ return (_lookup_simple(dbname, alias,
+ buf, bufsize, _LOOKUP_CASE_SENSITIVE));
+}
+
+static __inline int
+__isforcemapping(const char *name)
+{
+
+ return (_bcs_strcasecmp("/force", name));
+}
+
+#endif /*_CITRUS_ALIASNAME_LOCAL_H_*/
diff --git a/lib/libc/iconv/citrus_bcs.c b/lib/libc/iconv/citrus_bcs.c
new file mode 100644
index 0000000..e86fb37
--- /dev/null
+++ b/lib/libc/iconv/citrus_bcs.c
@@ -0,0 +1,168 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_bcs.c,v 1.5 2005/05/14 17:55:42 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+/*
+ * case insensitive comparison between two C strings.
+ */
+int
+_citrus_bcs_strcasecmp(const char * __restrict str1,
+ const char * __restrict str2)
+{
+ int c1, c2;
+
+ c1 = c2 = 1;
+
+ while (c1 && c2 && c1 == c2) {
+ c1 = _bcs_toupper(*str1++);
+ c2 = _bcs_toupper(*str2++);
+ }
+
+ return ((c1 == c2) ? 0 : ((c1 > c2) ? 1 : -1));
+}
+
+/*
+ * case insensitive comparison between two C strings with limitation of length.
+ */
+int
+_citrus_bcs_strncasecmp(const char * __restrict str1,
+ const char * __restrict str2, size_t sz)
+{
+ int c1, c2;
+
+ c1 = c2 = 1;
+
+ while (c1 && c2 && c1 == c2 && sz != 0) {
+ c1 = _bcs_toupper(*str1++);
+ c2 = _bcs_toupper(*str2++);
+ sz--;
+ }
+
+ return ((c1 == c2) ? 0 : ((c1 > c2) ? 1 : -1));
+}
+
+/*
+ * skip white space characters.
+ */
+const char *
+_citrus_bcs_skip_ws(const char *p)
+{
+
+ while (*p && _bcs_isspace(*p))
+ p++;
+
+ return (p);
+}
+
+/*
+ * skip non white space characters.
+ */
+const char *
+_citrus_bcs_skip_nonws(const char *p)
+{
+
+ while (*p && !_bcs_isspace(*p))
+ p++;
+
+ return (p);
+}
+
+/*
+ * skip white space characters with limitation of length.
+ */
+const char *
+_citrus_bcs_skip_ws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+ while (*p && *len > 0 && _bcs_isspace(*p)) {
+ p++;
+ (*len)--;
+ }
+
+ return (p);
+}
+
+/*
+ * skip non white space characters with limitation of length.
+ */
+const char *
+_citrus_bcs_skip_nonws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+ while (*p && *len > 0 && !_bcs_isspace(*p)) {
+ p++;
+ (*len)--;
+ }
+
+ return (p);
+}
+
+/*
+ * truncate trailing white space characters.
+ */
+void
+_citrus_bcs_trunc_rws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+ while (*len > 0 && _bcs_isspace(p[*len - 1]))
+ (*len)--;
+}
+
+/*
+ * destructive transliterate to lowercase.
+ */
+void
+_citrus_bcs_convert_to_lower(char *s)
+{
+
+ while (*s) {
+ *s = _bcs_tolower(*s);
+ s++;
+ }
+}
+
+/*
+ * destructive transliterate to uppercase.
+ */
+void
+_citrus_bcs_convert_to_upper(char *s)
+{
+
+ while (*s) {
+ *s = _bcs_toupper(*s);
+ s++;
+ }
+}
diff --git a/lib/libc/iconv/citrus_bcs.h b/lib/libc/iconv/citrus_bcs.h
new file mode 100644
index 0000000..3b1f537
--- /dev/null
+++ b/lib/libc/iconv/citrus_bcs.h
@@ -0,0 +1,102 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_bcs.h,v 1.6 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#ifndef _CITRUS_BCS_H_
+#define _CITRUS_BCS_H_
+
+/*
+ * predicate/conversion for basic character set.
+ *
+ * `Basic character set' is a term defined in the ISO C standard.
+ * Citrus bcs is, if anything, close to `portable character set'
+ * defined in the POSIX.
+ */
+
+#define _CITRUS_BCS_PRED(_name_, _cond_) \
+static __inline int _citrus_bcs_##_name_(uint8_t c) { return (_cond_); }
+
+/*
+ * predicates.
+ * Unlike predicates defined in ctype.h, these do not accept EOF.
+ */
+_CITRUS_BCS_PRED(isblank, c == ' ' || c == '\t')
+_CITRUS_BCS_PRED(iseol, c == '\n' || c == '\r')
+_CITRUS_BCS_PRED(isspace, _citrus_bcs_isblank(c) || _citrus_bcs_iseol(c) ||
+ c == '\f' || c == '\v')
+_CITRUS_BCS_PRED(isdigit, c >= '0' && c <= '9')
+_CITRUS_BCS_PRED(isupper, c >= 'A' && c <= 'Z')
+_CITRUS_BCS_PRED(islower, c >= 'a' && c <= 'z')
+_CITRUS_BCS_PRED(isalpha, _citrus_bcs_isupper(c) || _citrus_bcs_islower(c))
+_CITRUS_BCS_PRED(isalnum, _citrus_bcs_isdigit(c) || _citrus_bcs_isalpha(c))
+_CITRUS_BCS_PRED(isxdigit, _citrus_bcs_isdigit(c) ||
+ (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
+
+/*
+ * transliterate between uppercase and lowercase.
+ * Unlike transliterator defined in ctype.h, these do not accept EOF.
+ */
+static __inline uint8_t
+_citrus_bcs_toupper(uint8_t c)
+{
+
+ return (_citrus_bcs_islower(c) ? (c - 'a' + 'A') : c);
+}
+
+static __inline uint8_t
+_citrus_bcs_tolower(uint8_t c)
+{
+
+ return (_citrus_bcs_isupper(c) ? (c - 'A' + 'a') : c);
+}
+
+__BEGIN_DECLS
+int _citrus_bcs_strcasecmp(const char * __restrict,
+ const char * __restrict);
+int _citrus_bcs_strncasecmp(const char * __restrict,
+ const char * __restrict, size_t);
+const char *_citrus_bcs_skip_ws(const char * __restrict);
+const char *_citrus_bcs_skip_nonws(const char * __restrict);
+const char *_citrus_bcs_skip_ws_len(const char * __restrict,
+ size_t * __restrict);
+const char *_citrus_bcs_skip_nonws_len(const char * __restrict,
+ size_t * __restrict);
+void _citrus_bcs_trunc_rws_len(const char * __restrict,
+ size_t * __restrict);
+void _citrus_bcs_convert_to_lower(char *);
+void _citrus_bcs_convert_to_upper(char *);
+
+long int _citrus_bcs_strtol(const char * __restrict,
+ char ** __restrict, int);
+unsigned long _citrus_bcs_strtoul(const char * __restrict,
+ char ** __restrict, int);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_bcs_strtol.c b/lib/libc/iconv/citrus_bcs_strtol.c
new file mode 100644
index 0000000..4073622
--- /dev/null
+++ b/lib/libc/iconv/citrus_bcs_strtol.c
@@ -0,0 +1,57 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_bcs_strtol.c,v 1.2 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c) 2005 The DragonFly Project. All rights reserved.
+ * Copyright (c) 2003, 2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+#define _FUNCNAME _bcs_strtol
+#define __INT long int
+
+#undef isspace
+#define isspace(c) _bcs_isspace(c)
+
+#undef isdigit
+#define isdigit(c) _bcs_isdigit(c)
+
+#undef isalpha
+#define isalpha(c) _bcs_isalpha(c)
+
+#undef isupper
+#define isupper(c) _bcs_isupper(c)
+
+#include "_strtol.h"
diff --git a/lib/libc/iconv/citrus_bcs_strtoul.c b/lib/libc/iconv/citrus_bcs_strtoul.c
new file mode 100644
index 0000000..d9fa97c
--- /dev/null
+++ b/lib/libc/iconv/citrus_bcs_strtoul.c
@@ -0,0 +1,57 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_bcs_strtoul.c,v 1.3 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c) 2005 The DragonFly Project. All rights reserved.
+ * Copyright (c) 2003, 2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+#define _FUNCNAME _bcs_strtoul
+#define __UINT unsigned long int
+
+#undef isspace
+#define isspace(c) _bcs_isspace(c)
+
+#undef isdigit
+#define isdigit(c) _bcs_isdigit(c)
+
+#undef isalpha
+#define isalpha(c) _bcs_isalpha(c)
+
+#undef isupper
+#define isupper(c) _bcs_isupper(c)
+
+#include "_strtoul.h"
diff --git a/lib/libc/iconv/citrus_csmapper.c b/lib/libc/iconv/citrus_csmapper.c
new file mode 100644
index 0000000..5e0a01a
--- /dev/null
+++ b/lib/libc/iconv/citrus_csmapper.c
@@ -0,0 +1,383 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_csmapper.c,v 1.10 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/endian.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_lock.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 struct _citrus_mapper_area *maparea = NULL;
+
+#define CS_ALIAS _PATH_CSMAPPER "/charset.alias"
+#define CS_PIVOT _PATH_CSMAPPER "/charset.pivot"
+
+
+/* ---------------------------------------------------------------------- */
+
+static int
+get32(struct _region *r, uint32_t *rval)
+{
+
+ if (_region_size(r) != 4)
+ return (EFTYPE);
+
+ memcpy(rval, _region_head(r), (size_t)4);
+ *rval = be32toh(*rval);
+
+ return (0);
+}
+
+static int
+open_subdb(struct _citrus_db **subdb, struct _citrus_db *db, const char *src)
+{
+ struct _region r;
+ int ret;
+
+ 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)
+{
+ struct _citrus_db *db1, *db2, *db3;
+ struct _region fr, r1, r2;
+ char buf[LINE_MAX];
+ uint32_t val32;
+ unsigned long norm;
+ int i, num, ret;
+
+ 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;
+ if (_db_lookup_by_s(db3, dst, &r2, NULL) != 0)
+ 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)
+{
+ struct zone z1, z2;
+ char buf[20];
+ 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 = _bcs_strtoul(buf, NULL, 0);
+
+ return (0);
+}
+
+static int
+find_dst(struct parse_arg *pasrc, const char *dst)
+{
+ struct _lookup *cl;
+ struct parse_arg padst;
+ struct _region data;
+ int ret;
+
+ 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)
+{
+ struct _lookup *cl;
+ struct _region data;
+ struct parse_arg pa;
+ char pivot_min[PATH_MAX];
+ unsigned long norm_min;
+ int ret;
+
+ 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;
+
+ WLOCK;
+ 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:
+ UNLOCK;
+ 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)
+{
+ const char *realsrc, *realdst;
+ char buf1[PATH_MAX], buf2[PATH_MAX], key[PATH_MAX], pivot[PATH_MAX];
+ unsigned long norm;
+ int ret;
+
+ norm = 0;
+
+ 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/iconv/citrus_csmapper.h b/lib/libc/iconv/citrus_csmapper.h
new file mode 100644
index 0000000..dd178da
--- /dev/null
+++ b/lib/libc/iconv/citrus_csmapper.h
@@ -0,0 +1,48 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_csmapper.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_CSMAPPER_H_
+#define _CITRUS_CSMAPPER_H
+
+#define _citrus_csmapper _citrus_mapper
+#define _citrus_csmapper_close _citrus_mapper_close
+#define _citrus_csmapper_convert _citrus_mapper_convert
+#define _citrus_csmapper_init_state _citrus_mapper_init_state
+#define _citrus_csmapper_get_state_size _citrus_mapper_get_state_size
+#define _citrus_csmapper_get_src_max _citrus_mapper_get_src_max
+#define _citrus_csmapper_get_dst_max _citrus_mapper_get_dst_max
+
+#define _CITRUS_CSMAPPER_F_PREVENT_PIVOT 0x00000001
+__BEGIN_DECLS
+int _citrus_csmapper_open(struct _citrus_csmapper *__restrict *__restrict,
+ const char *__restrict, const char *__restrict, uint32_t,
+ unsigned long *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_db.c b/lib/libc/iconv/citrus_db.c
new file mode 100644
index 0000000..2de848b
--- /dev/null
+++ b/lib/libc/iconv/citrus_db.c
@@ -0,0 +1,331 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db.c,v 1.5 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/endian.h>
+#include <sys/types.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_factory.h"
+#include "citrus_db_file.h"
+
+struct _citrus_db {
+ struct _region db_region;
+ _citrus_db_hash_func_t db_hashfunc;
+ void *db_hashfunc_closure;
+};
+
+int
+_citrus_db_open(struct _citrus_db **rdb, struct _region *r, const char *magic,
+ _citrus_db_hash_func_t hashfunc, void *hashfunc_closure)
+{
+ struct _citrus_db *db;
+ struct _citrus_db_header_x *dhx;
+ struct _memstream ms;
+
+ _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)
+{
+ struct _citrus_db_entry_x *dex;
+ struct _citrus_db_header_x *dhx;
+ struct _citrus_region r;
+ struct _memstream ms;
+ uint32_t hashval, num_entries;
+ size_t offset;
+
+ _memstream_bind(&ms, &db->db_region);
+
+ dhx = _memstream_getregion(&ms, NULL, sizeof(*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(key)%num_entries;
+ offset = be32toh(dhx->dhx_entry_offset) +
+ hashval * _CITRUS_DB_ENTRY_SIZE;
+ if (dl)
+ dl->dl_hashval = hashval;
+ }
+ do {
+ /* seek to the next entry */
+ if (_citrus_memory_stream_seek(&ms, offset, SEEK_SET))
+ return (EFTYPE);
+ /* get the entry record */
+ dex = _memstream_getregion(&ms, NULL, _CITRUS_DB_ENTRY_SIZE);
+ if (dex == NULL)
+ return (EFTYPE);
+
+ /* jump to next entry having the same hash value. */
+ offset = be32toh(dex->dex_next_offset);
+
+ /* save the current position */
+ if (dl) {
+ dl->dl_offset = offset;
+ if (offset == 0)
+ dl->dl_offset = _region_size(&db->db_region);
+ }
+
+ /* compare hash value. */
+ if (be32toh(dex->dex_hash_value) != hashval)
+ /* not found */
+ break;
+ /* compare key length */
+ if (be32toh(dex->dex_key_size) == _region_size(key)) {
+ /* seek to the head of the key. */
+ if (_memstream_seek(&ms, be32toh(dex->dex_key_offset),
+ SEEK_SET))
+ return (EFTYPE);
+ /* get the region of the key */
+ if (_memstream_getregion(&ms, &r,
+ _region_size(key)) == NULL)
+ return (EFTYPE);
+ /* compare key byte stream */
+ if (memcmp(_region_head(&r), _region_head(key),
+ _region_size(key)) == 0) {
+ /* match */
+ if (_memstream_seek(
+ &ms, be32toh(dex->dex_data_offset),
+ SEEK_SET))
+ return (EFTYPE);
+ if (_memstream_getregion(
+ &ms, data,
+ be32toh(dex->dex_data_size)) == NULL)
+ return (EFTYPE);
+ return (0);
+ }
+ }
+ } while (offset != 0);
+
+ return (ENOENT);
+}
+
+int
+_citrus_db_lookup_by_string(struct _citrus_db *db, const char *key,
+ struct _citrus_region *data, struct _citrus_db_locator *dl)
+{
+ struct _region r;
+
+ _region_init(&r, __DECONST(void *, 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)
+{
+ struct _region r;
+ int ret;
+
+ 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)
+{
+ struct _region r;
+ int ret;
+ 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)
+{
+ struct _region r;
+ uint32_t val;
+ int ret;
+
+ 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)
+{
+ struct _region r;
+ int ret;
+
+ 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 _citrus_db_header_x *dhx;
+ struct _memstream ms;
+
+ _memstream_bind(&ms, &db->db_region);
+
+ dhx = _memstream_getregion(&ms, NULL, sizeof(*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)
+{
+ struct _citrus_db_entry_x *dex;
+ struct _citrus_db_header_x *dhx;
+ struct _memstream ms;
+ uint32_t num_entries;
+ size_t offset;
+
+ _memstream_bind(&ms, &db->db_region);
+
+ dhx = _memstream_getregion(&ms, NULL, sizeof(*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/iconv/citrus_db.h b/lib/libc/iconv/citrus_db.h
new file mode 100644
index 0000000..27e16f3
--- /dev/null
+++ b/lib/libc/iconv/citrus_db.h
@@ -0,0 +1,70 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_H_
+#define _CITRUS_DB_H_
+
+#include "citrus_db_factory.h"
+
+struct _citrus_db;
+struct _citrus_db_locator {
+ uint32_t dl_hashval;
+ size_t dl_offset;
+};
+
+__BEGIN_DECLS
+int _citrus_db_open(struct _citrus_db **, struct _citrus_region *,
+ const char *, _citrus_db_hash_func_t, void *);
+void _citrus_db_close(struct _citrus_db *);
+int _citrus_db_lookup(struct _citrus_db *, struct _citrus_region *,
+ struct _citrus_region *, struct _citrus_db_locator *);
+int _citrus_db_lookup_by_string(struct _citrus_db *, const char *,
+ struct _citrus_region *, struct _citrus_db_locator *);
+int _citrus_db_lookup8_by_string(struct _citrus_db *, const char *,
+ uint8_t *, struct _citrus_db_locator *);
+int _citrus_db_lookup16_by_string(struct _citrus_db *, const char *,
+ uint16_t *, struct _citrus_db_locator *);
+int _citrus_db_lookup32_by_string(struct _citrus_db *, const char *,
+ uint32_t *, struct _citrus_db_locator *);
+int _citrus_db_lookup_string_by_string(struct _citrus_db *, const char *,
+ const char **, struct _citrus_db_locator *);
+int _citrus_db_get_number_of_entries(struct _citrus_db *);
+int _citrus_db_get_entry(struct _citrus_db *, int,
+ struct _citrus_region *, struct _citrus_region *);
+__END_DECLS
+
+static __inline void
+_citrus_db_locator_init(struct _citrus_db_locator *dl)
+{
+
+ dl->dl_hashval = 0;
+ dl->dl_offset = 0;
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_db_factory.c b/lib/libc/iconv/citrus_db_factory.c
new file mode 100644
index 0000000..9a3edf2
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_factory.c
@@ -0,0 +1,348 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_factory.c,v 1.9 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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)(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(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)
+{
+ struct _citrus_db_factory_entry *de, **depp, *det;
+ size_t dataofs, i, keyofs, nextofs, ofs;
+
+ 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/iconv/citrus_db_factory.h b/lib/libc/iconv/citrus_db_factory.h
new file mode 100644
index 0000000..b98b19c
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_factory.h
@@ -0,0 +1,57 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_factory.h,v 1.3 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_FACTORY_H_
+#define _CITRUS_DB_FACTORY_H_
+
+struct _citrus_db_factory;
+typedef uint32_t (*_citrus_db_hash_func_t)(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/iconv/citrus_db_file.h b/lib/libc/iconv/citrus_db_file.h
new file mode 100644
index 0000000..aed07e8
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_file.h
@@ -0,0 +1,85 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_file.h,v 1.4 2008/02/10 05:58:22 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_FILE_H_
+#define _CITRUS_DB_FILE_H_
+
+/*
+ * db format:
+ * +---
+ * | header
+ * | - magic
+ * | - num entries
+ * +---
+ * | entry directory
+ * | +------------
+ * | | entry0
+ * | | - hash value
+ * | | - next entry
+ * | | - key offset
+ * | | - key len
+ * | | - data offset
+ * | | - data size
+ * | |---
+ * | | entry1
+ * | | ..
+ * | | entryN
+ * | +---
+ * +---
+ * | key table
+ * | - key0
+ * | ...
+ * | - keyN
+ * +---
+ * | data table
+ * | - data0
+ * | ...
+ * | - dataN
+ * +---
+ */
+
+#define _CITRUS_DB_MAGIC_SIZE 8
+#define _CITRUS_DB_HEADER_SIZE 16
+struct _citrus_db_header_x {
+ char dhx_magic[_CITRUS_DB_MAGIC_SIZE];
+ uint32_t dhx_num_entries;
+ uint32_t dhx_entry_offset;
+} __packed;
+
+struct _citrus_db_entry_x {
+ uint32_t dex_hash_value;
+ uint32_t dex_next_offset;
+ uint32_t dex_key_offset;
+ uint32_t dex_key_size;
+ uint32_t dex_data_offset;
+ uint32_t dex_data_size;
+} __packed;
+#define _CITRUS_DB_ENTRY_SIZE 24
+
+#endif
diff --git a/lib/libc/iconv/citrus_db_hash.c b/lib/libc/iconv/citrus_db_hash.c
new file mode 100644
index 0000000..2c599ff
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_hash.c
@@ -0,0 +1,64 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_hash.c,v 1.5 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_db_hash.h"
+
+uint32_t
+_citrus_db_hash_std(struct _region *r)
+{
+ const uint8_t *p;
+ uint32_t hash, tmp;
+ size_t i;
+
+ hash = 0;
+ p = _region_head(r);
+
+ 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/iconv/citrus_db_hash.h b/lib/libc/iconv/citrus_db_hash.h
new file mode 100644
index 0000000..549af26
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_hash.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_hash.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_HASH_H_
+#define _CITRUS_DB_HASH_H_
+
+__BEGIN_DECLS
+uint32_t _citrus_db_hash_std(struct _citrus_region *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_esdb.c b/lib/libc/iconv/citrus_esdb.c
new file mode 100644
index 0000000..578cbc1
--- /dev/null
+++ b/lib/libc/iconv/citrus_esdb.c
@@ -0,0 +1,374 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_esdb.c,v 1.5 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.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)
+{
+ struct _citrus_db *db;
+ const char *str;
+ char buf[100];
+ uint32_t csid, i, num_charsets, tmp, version;
+ int ret;
+
+ /* 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)
+{
+ struct _region fr;
+ const char *realname, *encfile;
+ char buf1[PATH_MAX], buf2[PATH_MAX], path[PATH_MAX];
+ int ret;
+
+ 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)
+{
+
+ for (int 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)
+{
+
+ for (size_t 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, bool sorted)
+{
+ struct _citrus_lookup *cla, *cld;
+ struct _region key, data;
+ char **list, **q;
+ char buf[PATH_MAX];
+ size_t num;
+ int ret;
+
+ 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, &data)) == 0) {
+ if (sorted)
+ snprintf(buf, sizeof(buf), "%.*s/%.*s",
+ (int)_region_size(&data),
+ (const char *)_region_head(&data),
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
+ else
+ snprintf(buf, sizeof(buf), "%.*s/%.*s",
+ (int)_region_size(&data),
+ (const char *)_region_head(&data),
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
+ _bcs_convert_to_upper(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, &data)) == 0) {
+ if (!sorted)
+ snprintf(buf, sizeof(buf), "%.*s",
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
+ else {
+ /* check duplicated entry */
+ char *p;
+ char buf1[PATH_MAX];
+
+ snprintf(buf1, sizeof(buf1), "%.*s",
+ (int)_region_size(&data),
+ (const char *)_region_head(&data));
+ if ((p = strchr(buf1, '/')) != NULL)
+ memcpy(buf1, p + 1, strlen(p) - 1);
+ if ((p = strstr(buf1, ".esdb")) != NULL)
+ *p = '\0';
+ snprintf(buf, sizeof(buf), "%s/%.*s", buf1,
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
+ }
+ _bcs_convert_to_upper(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;
+ /* XXX: why reallocing the list space posteriorly?
+ shouldn't be done earlier? */
+ 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/iconv/citrus_esdb.h b/lib/libc/iconv/citrus_esdb.h
new file mode 100644
index 0000000..f82a398
--- /dev/null
+++ b/lib/libc/iconv/citrus_esdb.h
@@ -0,0 +1,58 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_esdb.h,v 1.1 2003/06/25 09:51:32 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ESDB_H_
+#define _CITRUS_ESDB_H_
+
+#include "citrus_types.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 *, bool);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_esdb_file.h b/lib/libc/iconv/citrus_esdb_file.h
new file mode 100644
index 0000000..98609d1
--- /dev/null
+++ b/lib/libc/iconv/citrus_esdb_file.h
@@ -0,0 +1,45 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_esdb_file.h,v 1.1 2003/06/25 09:51:32 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ESDB_FILE_H_
+#define _CITRUS_ESDB_FILE_H_
+
+#define _CITRUS_ESDB_MAGIC "ESDB\0\0\0\0"
+
+#define _CITRUS_ESDB_SYM_VERSION "version"
+#define _CITRUS_ESDB_SYM_ENCODING "encoding"
+#define _CITRUS_ESDB_SYM_VARIABLE "variable"
+#define _CITRUS_ESDB_SYM_NUM_CHARSETS "num_charsets"
+#define _CITRUS_ESDB_SYM_INVALID "invalid"
+#define _CITRUS_ESDB_SYM_CSNAME_PREFIX "csname_"
+#define _CITRUS_ESDB_SYM_CSID_PREFIX "csid_"
+
+#define _CITRUS_ESDB_VERSION 0x00000001
+
+#endif
diff --git a/lib/libc/iconv/citrus_fix_grouping.h b/lib/libc/iconv/citrus_fix_grouping.h
new file mode 100644
index 0000000..fbb1788
--- /dev/null
+++ b/lib/libc/iconv/citrus_fix_grouping.h
@@ -0,0 +1,53 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_fix_grouping.h,v 1.2 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_FIX_GROUPING_H_
+#define _CITRUS_FIX_GROUPING_H_
+
+#define _CITRUS_LC_GROUPING_VALUE_MIN 0
+#define _CITRUS_LC_GROUPING_VALUE_MAX 126
+#define _CITRUS_LC_GROUPING_VALUE_NO_FUTHER 127
+
+#if CHAR_MAX != _CITRUS_LC_GROUPING_VALUE_NO_FUTHER
+static __inline void
+_citrus_fixup_char_max_md(char *grouping)
+{
+ char *p;
+
+ for (p = grouping; *p != '\0'; ++p)
+ if (*p == _CITRUS_LC_GROUPING_VALUE_NO_FUTHER)
+ *p = (char)CHAR_MAX;
+}
+#define _CITRUS_FIXUP_CHAR_MAX_MD(grouping) \
+ _citrus_fixup_char_max_md(__DECONST(void *, grouping))
+#else
+#define _CITRUS_FIXUP_CHAR_MAX_MD(grouping) /* nothing to do */
+#endif
+
+#endif /*_CITRUS_FIX_GROUPING_H_*/
diff --git a/lib/libc/iconv/citrus_hash.c b/lib/libc/iconv/citrus_hash.c
new file mode 100644
index 0000000..4db1bda
--- /dev/null
+++ b/lib/libc/iconv/citrus_hash.c
@@ -0,0 +1,51 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_hash.c,v 1.3 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.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;
+
+ _region_init(&r, __DECONST(void *, key), strlen(key));
+
+ return ((int)(_db_hash_std(&r) % (uint32_t)hashsize));
+}
diff --git a/lib/libc/iconv/citrus_hash.h b/lib/libc/iconv/citrus_hash.h
new file mode 100644
index 0000000..c3e7311
--- /dev/null
+++ b/lib/libc/iconv/citrus_hash.h
@@ -0,0 +1,59 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_hash.h,v 1.3 2004/01/02 21:49:35 itojun Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_HASH_H_
+#define _CITRUS_HASH_H_
+
+#define _CITRUS_HASH_ENTRY(type) LIST_ENTRY(type)
+#define _CITRUS_HASH_HEAD(headname, type, hashsize) \
+struct headname { \
+ LIST_HEAD(, type) chh_table[hashsize]; \
+}
+#define _CITRUS_HASH_INIT(head, hashsize) \
+do { \
+ int _ch_loop; \
+ \
+ for (_ch_loop = 0; _ch_loop < hashsize; _ch_loop++) \
+ LIST_INIT(&(head)->chh_table[_ch_loop]); \
+} while (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 (0)
+
+__BEGIN_DECLS
+int _citrus_string_hash_func(const char *, int);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_iconv.c b/lib/libc/iconv/citrus_iconv.c
new file mode 100644
index 0000000..941ee02
--- /dev/null
+++ b/lib/libc/iconv/citrus_iconv.c
@@ -0,0 +1,335 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv.c,v 1.7 2008/07/25 14:05:25 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <iconv.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_esdb.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_module.h"
+#include "citrus_lock.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 bool isinit = false;
+static int shared_max_reuse, shared_num_unused;
+static _CITRUS_HASH_HEAD(, _citrus_iconv_shared, CI_HASH_SIZE) shared_pool;
+static TAILQ_HEAD(, _citrus_iconv_shared) shared_unused;
+
+static __inline void
+init_cache(void)
+{
+
+ WLOCK;
+ 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 = true;
+ }
+ UNLOCK;
+}
+
+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 convname, const char * __restrict src,
+ const char * __restrict dst)
+{
+ struct _citrus_iconv_shared *ci;
+ _citrus_iconv_getops_t getops;
+ const char *module;
+ size_t len_convname;
+ int ret;
+
+ module = (strcmp(src, dst) != 0) ? "iconv_std" : "iconv_none";
+
+ /* 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);
+ if (ret)
+ 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, src, dst);
+ 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 *src, const char *dst)
+{
+ struct _citrus_iconv_shared * ci;
+ char convname[PATH_MAX];
+ int hashval, ret = 0;
+
+ snprintf(convname, sizeof(convname), "%s/%s", src, dst);
+
+ WLOCK;
+
+ /* 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, 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:
+ UNLOCK;
+
+ return (ret);
+}
+
+static void
+release_shared(struct _citrus_iconv_shared * __restrict ci)
+{
+
+ WLOCK;
+ 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);
+ TAILQ_REMOVE(&shared_unused, ci, ci_tailq_entry);
+ _CITRUS_HASH_REMOVE(ci, ci_hash_entry);
+ shared_num_unused--;
+ close_shared(ci);
+ }
+ }
+
+ UNLOCK;
+}
+
+/*
+ * _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 src, const char * __restrict dst)
+{
+ struct _citrus_iconv *cv;
+ struct _citrus_iconv_shared *ci = NULL;
+ char realdst[PATH_MAX], realsrc[PATH_MAX];
+ char buf[PATH_MAX], path[PATH_MAX];
+ int ret;
+
+ init_cache();
+
+ /* GNU behaviour, using locale encoding if "" or "char" is specified */
+ if ((strcmp(src, "") == 0) || (strcmp(src, "char") == 0))
+ src = nl_langinfo(CODESET);
+ if ((strcmp(dst, "") == 0) || (strcmp(dst, "char") == 0))
+ dst = nl_langinfo(CODESET);
+
+ /* resolve codeset name aliases */
+ strlcpy(realsrc, _lookup_alias(path, src, buf, (size_t)PATH_MAX,
+ _LOOKUP_CASE_IGNORE), (size_t)PATH_MAX);
+ strlcpy(realdst, _lookup_alias(path, dst, buf, (size_t)PATH_MAX,
+ _LOOKUP_CASE_IGNORE), (size_t)PATH_MAX);
+
+ /* sanity check */
+ if (strchr(realsrc, '/') != NULL || strchr(realdst, '/'))
+ return (EINVAL);
+
+ /* get shared record */
+ ret = get_shared(&ci, realsrc, realdst);
+ if (ret)
+ return (ret);
+
+ /* create/init context */
+ if (*rcv == NULL) {
+ cv = malloc(sizeof(*cv));
+ if (cv == NULL) {
+ ret = errno;
+ release_shared(ci);
+ return (ret);
+ }
+ *rcv = cv;
+ }
+ (*rcv)->cv_shared = ci;
+ ret = (*ci->ci_ops->io_init_context)(*rcv);
+ if (ret) {
+ release_shared(ci);
+ free(*rcv);
+ return (ret);
+ }
+ 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);
+ }
+}
+
+const char
+*_citrus_iconv_canonicalize(const char *name)
+{
+ char *buf;
+
+ if ((buf = malloc((size_t)PATH_MAX)) == NULL)
+ return (NULL);
+ memset((void *)buf, 0, (size_t)PATH_MAX);
+ _citrus_esdb_alias(name, buf, (size_t)PATH_MAX);
+ return (buf);
+}
diff --git a/lib/libc/iconv/citrus_iconv.h b/lib/libc/iconv/citrus_iconv.h
new file mode 100644
index 0000000..99604e9
--- /dev/null
+++ b/lib/libc/iconv/citrus_iconv.h
@@ -0,0 +1,64 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv.h,v 1.5 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_H_
+#define _CITRUS_ICONV_H_
+
+struct _citrus_iconv_shared;
+struct _citrus_iconv_ops;
+struct _citrus_iconv;
+
+__BEGIN_DECLS
+int _citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict,
+ const char * __restrict, const char * __restrict);
+void _citrus_iconv_close(struct _citrus_iconv *);
+const char *_citrus_iconv_canonicalize(const char *);
+__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,
+ char * __restrict * __restrict in, size_t * __restrict inbytes,
+ char * __restrict * __restrict out, size_t * __restrict outbytes,
+ uint32_t flags, size_t * __restrict nresults)
+{
+
+ return (*cv->cv_shared->ci_ops->io_convert)(cv, in, inbytes, out,
+ outbytes, flags, nresults);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_iconv_local.h b/lib/libc/iconv/citrus_iconv_local.h
new file mode 100644
index 0000000..db20363
--- /dev/null
+++ b/lib/libc/iconv/citrus_iconv_local.h
@@ -0,0 +1,107 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv_local.h,v 1.3 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_LOCAL_H_
+#define _CITRUS_ICONV_LOCAL_H_
+
+#include <iconv.h>
+
+#define _CITRUS_ICONV_GETOPS_FUNC_BASE(_n_) \
+ int _n_(struct _citrus_iconv_ops *)
+#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); \
+static void _citrus_##_m_##_iconv_uninit_shared \
+ (struct _citrus_iconv_shared *); \
+static int _citrus_##_m_##_iconv_convert \
+ (struct _citrus_iconv * __restrict, \
+ 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_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);
+typedef void (*_citrus_iconv_uninit_shared_t)
+ (struct _citrus_iconv_shared *);
+typedef int (*_citrus_iconv_convert_t)
+ (struct _citrus_iconv * __restrict,
+ 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 {
+ _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;
+};
+
+struct _citrus_iconv_shared {
+ struct _citrus_iconv_ops *ci_ops;
+ void *ci_closure;
+ _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;
+ bool ci_discard_ilseq;
+ struct iconv_hooks *ci_hooks;
+};
+
+struct _citrus_iconv {
+ struct _citrus_iconv_shared *cv_shared;
+ void *cv_closure;
+};
+
+#endif
diff --git a/lib/libc/iconv/citrus_lock.h b/lib/libc/iconv/citrus_lock.h
new file mode 100644
index 0000000..ad9443a
--- /dev/null
+++ b/lib/libc/iconv/citrus_lock.h
@@ -0,0 +1,35 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (C) 2010 Gabor Kovesdan <gabor@FreeBSD.org>
+ * 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 <pthread.h>
+
+static pthread_rwlock_t lock;
+
+#define WLOCK if (__isthreaded) \
+ pthread_rwlock_wrlock(&lock);
+#define UNLOCK if (__isthreaded) \
+ pthread_rwlock_unlock(&lock);
diff --git a/lib/libc/iconv/citrus_lookup.c b/lib/libc/iconv/citrus_lookup.c
new file mode 100644
index 0000000..09b1298
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup.c
@@ -0,0 +1,362 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup.c,v 1.6 2009/02/03 04:58:38 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.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)
+{
+ struct _region r;
+ char path[PATH_MAX];
+ int ret;
+
+ 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 && ((size_t)(q - p) != cl->cl_keylen ||
+ memcmp(p, cl->cl_key, (size_t)(q - p)) != 0))
+ goto retry;
+
+ /* found a entry */
+ if (key)
+ _region_init(key, __DECONST(void *, p), (size_t)(q - p));
+ p = _bcs_skip_ws_len(q, &len);
+ if (data)
+ _region_init(data, len ? __DECONST(void *, 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)
+ _region_init(data, __DECONST(void *, 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);
+ free(cl);
+}
+
+char *
+_citrus_lookup_simple(const char *name, const char *key,
+ char *linebuf, size_t linebufsize, int ignore_case)
+{
+ struct _citrus_lookup *cl;
+ struct _region data;
+ int ret;
+
+ 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/iconv/citrus_lookup.h b/lib/libc/iconv/citrus_lookup.h
new file mode 100644
index 0000000..e7a7150
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup.h
@@ -0,0 +1,64 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup.h,v 1.2 2004/07/21 14:16:34 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_LOOKUP_H_
+#define _CITRUS_LOOKUP_H_
+
+#define _CITRUS_LOOKUP_CASE_SENSITIVE 0
+#define _CITRUS_LOOKUP_CASE_IGNORE 1
+
+struct _citrus_lookup;
+__BEGIN_DECLS
+char *_citrus_lookup_simple(const char *, const char *, char *,
+ size_t, int);
+int _citrus_lookup_seq_open(struct _citrus_lookup **,
+ const char *, int);
+void _citrus_lookup_seq_rewind(struct _citrus_lookup *);
+int _citrus_lookup_seq_next(struct _citrus_lookup *,
+ struct _region *, struct _region *);
+int _citrus_lookup_seq_lookup(struct _citrus_lookup *,
+ const char *, struct _region *);
+int _citrus_lookup_get_number_of_entries(struct _citrus_lookup *);
+void _citrus_lookup_seq_close(struct _citrus_lookup *);
+__END_DECLS
+
+static __inline const char *
+_citrus_lookup_alias(const char *path, const char *key, char *buf, size_t n,
+ int ignore_case)
+{
+ const char *ret;
+
+ ret = _citrus_lookup_simple(path, key, buf, n, ignore_case);
+ if (ret == NULL)
+ ret = key;
+
+ return (ret);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_lookup_factory.c b/lib/libc/iconv/citrus_lookup_factory.c
new file mode 100644
index 0000000..ec5a5d6
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup_factory.c
@@ -0,0 +1,121 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup_factory.c,v 1.4 2003/10/27 00:12:42 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.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_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 data[LINE_MAX], key[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)
+{
+ void *ptr;
+ size_t size;
+
+ 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/iconv/citrus_lookup_factory.h b/lib/libc/iconv/citrus_lookup_factory.h
new file mode 100644
index 0000000..9016de5
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup_factory.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup_factory.h,v 1.1 2003/06/25 09:51:35 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_LOOKUP_FACTORY_H_
+#define _CITRUS_LOOKUP_FACTORY_H_
+
+__BEGIN_DECLS
+int _citrus_lookup_factory_convert(FILE *, FILE *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_lookup_file.h b/lib/libc/iconv/citrus_lookup_file.h
new file mode 100644
index 0000000..43944b3
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup_file.h
@@ -0,0 +1,35 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup_file.h,v 1.1 2003/06/25 09:51:36 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_LOOKUP_FILE_H_
+#define _CITRUS_LOOKUP_FILE_H_
+
+#define _CITRUS_LOOKUP_MAGIC "LOOKUP\0\0"
+
+#endif
diff --git a/lib/libc/iconv/citrus_mapper.c b/lib/libc/iconv/citrus_mapper.c
new file mode 100644
index 0000000..a788a9d9
--- /dev/null
+++ b/lib/libc/iconv/citrus_mapper.c
@@ -0,0 +1,397 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper.c,v 1.7 2008/07/25 14:05:25 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/queue.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_types.h"
+#include "citrus_region.h"
+#include "citrus_lock.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
+
+struct _citrus_mapper_area {
+ _CITRUS_HASH_HEAD(, _citrus_mapper, CM_HASH_SIZE) ma_cache;
+ char *ma_dir;
+};
+
+/*
+ * _citrus_mapper_create_area:
+ * create mapper area
+ */
+
+int
+_citrus_mapper_create_area(
+ struct _citrus_mapper_area *__restrict *__restrict rma,
+ const char *__restrict area)
+{
+ struct _citrus_mapper_area *ma;
+ struct stat st;
+ char path[PATH_MAX];
+ int ret;
+
+ WLOCK;
+
+ if (*rma != NULL) {
+ ret = 0;
+ goto quit;
+ }
+
+ snprintf(path, (size_t)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:
+ UNLOCK;
+
+ 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;
+ const char *cp, *cq;
+ char *p;
+ char path[PATH_MAX];
+ size_t len;
+ int ret;
+
+ /* create mapper.dir path */
+ snprintf(path, (size_t)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)
+{
+ struct _citrus_mapper *cm;
+ _citrus_mapper_getops_t getops;
+ int ret;
+
+ /* 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);
+ 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)
+{
+ struct _citrus_mapper *cm;
+ char linebuf[PATH_MAX];
+ const char *module, *variable;
+ int hashval, ret;
+
+ variable = NULL;
+
+ WLOCK;
+
+ /* 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,
+ (size_t)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;
+ _mapper_close(cm);
+ goto quit;
+ }
+
+ /* insert to the cache */
+ cm->cm_refcount = 1;
+ _CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval);
+
+ *rcm = cm;
+ ret = 0;
+quit:
+ UNLOCK;
+
+ return (ret);
+}
+
+/*
+ * _citrus_mapper_close:
+ * close the specified mapper.
+ */
+void
+_citrus_mapper_close(struct _citrus_mapper *cm)
+{
+
+ if (cm) {
+ WLOCK;
+ 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);
+ }
+ mapper_close(cm);
+quit:
+ UNLOCK;
+ }
+}
+
+/*
+ * _citrus_mapper_set_persistent:
+ * set persistent count.
+ */
+void
+_citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)
+{
+
+ WLOCK;
+ cm->cm_refcount = REFCOUNT_PERSISTENT;
+ UNLOCK;
+}
diff --git a/lib/libc/iconv/citrus_mapper.h b/lib/libc/iconv/citrus_mapper.h
new file mode 100644
index 0000000..429b2a1
--- /dev/null
+++ b/lib/libc/iconv/citrus_mapper.h
@@ -0,0 +1,131 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper.h,v 1.3 2003/07/12 15:39:19 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_H_
+#define _CITRUS_MAPPER_H_
+
+struct _citrus_mapper_area;
+struct _citrus_mapper;
+struct _citrus_mapper_ops;
+struct _citrus_mapper_traits;
+
+__BEGIN_DECLS
+int _citrus_mapper_create_area(
+ struct _citrus_mapper_area *__restrict *__restrict,
+ const char *__restrict);
+int _citrus_mapper_open(struct _citrus_mapper_area *__restrict,
+ struct _citrus_mapper *__restrict *__restrict,
+ const char *__restrict);
+int _citrus_mapper_open_direct(
+ struct _citrus_mapper_area *__restrict,
+ struct _citrus_mapper *__restrict *__restrict,
+ const char *__restrict, const char *__restrict);
+void _citrus_mapper_close(struct _citrus_mapper *);
+void _citrus_mapper_set_persistent(struct _citrus_mapper * __restrict);
+__END_DECLS
+
+#include "citrus_mapper_local.h"
+
+/* return values of _citrus_mapper_convert */
+#define _CITRUS_MAPPER_CONVERT_SUCCESS (0)
+#define _CITRUS_MAPPER_CONVERT_NONIDENTICAL (1)
+#define _CITRUS_MAPPER_CONVERT_SRC_MORE (2)
+#define _CITRUS_MAPPER_CONVERT_DST_MORE (3)
+#define _CITRUS_MAPPER_CONVERT_ILSEQ (4)
+#define _CITRUS_MAPPER_CONVERT_FATAL (5)
+
+/*
+ * _citrus_mapper_convert:
+ * convert an index.
+ * - if the converter supports M:1 converter, the function may return
+ * _CITRUS_MAPPER_CONVERT_SRC_MORE and the storage pointed by dst
+ * may be unchanged in this case, although the internal status of
+ * the mapper is affected.
+ * - if the converter supports 1:N converter, the function may return
+ * _CITRUS_MAPPER_CONVERT_DST_MORE. In this case, the contiguous
+ * call of this function ignores src and changes the storage pointed
+ * by dst.
+ * - if the converter supports M:N converter, the function may behave
+ * the combination of the above.
+ *
+ */
+static __inline int
+_citrus_mapper_convert(struct _citrus_mapper * __restrict cm,
+ _citrus_index_t * __restrict dst, _citrus_index_t src,
+ void * __restrict ps)
+{
+
+ 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)
+{
+
+ (*cm->cm_ops->mo_init_state)();
+}
+
+/*
+ * _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)
+{
+
+ 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)
+{
+
+ 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)
+{
+
+ return (cm->cm_traits->mt_dst_max);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_mapper_local.h b/lib/libc/iconv/citrus_mapper_local.h
new file mode 100644
index 0000000..887a35d
--- /dev/null
+++ b/lib/libc/iconv/citrus_mapper_local.h
@@ -0,0 +1,96 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_local.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_LOCAL_H_
+#define _CITRUS_MAPPER_LOCAL_H_
+
+#define _CITRUS_MAPPER_GETOPS_FUNC_BASE(_n_) \
+int _n_(struct _citrus_mapper_ops *)
+#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 \
+ (void);
+
+#define _CITRUS_MAPPER_DEF_OPS(_m_) \
+struct _citrus_mapper_ops _citrus_##_m_##_mapper_ops = { \
+ /* 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)(void);
+
+struct _citrus_mapper_ops {
+ _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/iconv/citrus_memstream.c b/lib/libc/iconv/citrus_memstream.c
new file mode 100644
index 0000000..d7ad4fd
--- /dev/null
+++ b/lib/libc/iconv/citrus_memstream.c
@@ -0,0 +1,148 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_memstream.c,v 1.4 2009/02/03 05:02:12 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#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)
+{
+ const uint8_t *h, *p;
+ size_t ret;
+ int i;
+
+ 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 keylen, len;
+
+ keylen = strlen(key);
+ for(;;) {
+ p = _citrus_memory_stream_getln(ms, &len);
+ if (p == NULL)
+ return (NULL);
+
+ /* ignore comment */
+ q = memchr(p, T_COMM, len);
+ if (q) {
+ len = q - p;
+ }
+ /* ignore trailing white space and newline */
+ _bcs_trunc_rws_len(p, &len);
+ if (len == 0)
+ continue; /* ignore null line */
+
+ /* skip white spaces at the head of the line */
+ p = _bcs_skip_ws_len(p, &len);
+ q = _bcs_skip_nonws_len(p, &len);
+
+ if ((size_t)(q - p) == keylen) {
+ if (iscasesensitive) {
+ if (memcmp(key, p, keylen) == 0)
+ break; /* match */
+ } else {
+ if (_bcs_strncasecmp(key, p, keylen) == 0)
+ break; /* match */
+ }
+ }
+ }
+
+ p = _bcs_skip_ws_len(q, &len);
+ *rlen = len;
+
+ return (p);
+}
+
+void *
+_citrus_memory_stream_chr(struct _citrus_memory_stream *ms,
+ struct _citrus_region *r, char ch)
+{
+ void *chr, *head;
+ 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/iconv/citrus_memstream.h b/lib/libc/iconv/citrus_memstream.h
new file mode 100644
index 0000000..cd5ef13
--- /dev/null
+++ b/lib/libc/iconv/citrus_memstream.h
@@ -0,0 +1,226 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_memstream.h,v 1.3 2005/05/14 17:55:42 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_MEMSTREAM_H_
+#define _CITRUS_MEMSTREAM_H_
+
+struct _citrus_memory_stream {
+ struct _citrus_region ms_region;
+ size_t ms_pos;
+};
+
+__BEGIN_DECLS
+const char *_citrus_memory_stream_getln(
+ struct _citrus_memory_stream * __restrict,
+ size_t * __restrict);
+const char *_citrus_memory_stream_matchline(
+ struct _citrus_memory_stream * __restrict,
+ const char * __restrict, size_t * __restrict, int);
+void *_citrus_memory_stream_chr(struct _citrus_memory_stream *,
+ struct _citrus_region *, char);
+void _citrus_memory_stream_skip_ws(struct _citrus_memory_stream *);
+__END_DECLS
+
+static __inline int
+_citrus_memory_stream_iseof(struct _citrus_memory_stream *ms)
+{
+
+ return (ms->ms_pos >= _citrus_region_size(&ms->ms_region));
+}
+
+static __inline void
+_citrus_memory_stream_bind(struct _citrus_memory_stream * __restrict ms,
+ const struct _citrus_region * __restrict r)
+{
+
+ ms->ms_region = *r;
+ ms->ms_pos = 0;
+}
+
+static __inline void
+_citrus_memory_stream_bind_ptr(struct _citrus_memory_stream * __restrict ms,
+ void *ptr, size_t sz)
+{
+ struct _citrus_region r;
+
+ _citrus_region_init(&r, ptr, sz);
+ _citrus_memory_stream_bind(ms, &r);
+}
+
+static __inline void
+_citrus_memory_stream_rewind(struct _citrus_memory_stream *ms)
+{
+
+ ms->ms_pos = 0;
+}
+
+static __inline size_t
+_citrus_memory_stream_tell(struct _citrus_memory_stream *ms)
+{
+
+ return (ms->ms_pos);
+}
+
+static __inline size_t
+_citrus_memory_stream_remainder(struct _citrus_memory_stream *ms)
+{
+ size_t sz;
+
+ sz = _citrus_region_size(&ms->ms_region);
+ if (ms->ms_pos>sz)
+ return (0);
+ return (sz-ms->ms_pos);
+}
+
+static __inline int
+_citrus_memory_stream_seek(struct _citrus_memory_stream *ms, size_t pos, int w)
+{
+ size_t sz;
+
+ sz = _citrus_region_size(&ms->ms_region);
+
+ switch (w) {
+ case SEEK_SET:
+ if (pos >= sz)
+ return (-1);
+ ms->ms_pos = pos;
+ break;
+ case SEEK_CUR:
+ pos += (ssize_t)ms->ms_pos;
+ if (pos >= sz)
+ return (-1);
+ ms->ms_pos = pos;
+ break;
+ case SEEK_END:
+ if (sz < pos)
+ return (-1);
+ ms->ms_pos = sz - pos;
+ break;
+ }
+ return (0);
+}
+
+static __inline int
+_citrus_memory_stream_getc(struct _citrus_memory_stream *ms)
+{
+
+ if (_citrus_memory_stream_iseof(ms))
+ return (EOF);
+ return (_citrus_region_peek8(&ms->ms_region, ms->ms_pos++));
+}
+
+static __inline void
+_citrus_memory_stream_ungetc(struct _citrus_memory_stream *ms, int ch)
+{
+
+ if (ch != EOF && ms->ms_pos > 0)
+ ms->ms_pos--;
+}
+
+static __inline int
+_citrus_memory_stream_peek(struct _citrus_memory_stream *ms)
+{
+
+ if (_citrus_memory_stream_iseof(ms))
+ return (EOF);
+ return (_citrus_region_peek8(&ms->ms_region, ms->ms_pos));
+}
+
+static __inline void *
+_citrus_memory_stream_getregion(struct _citrus_memory_stream *ms,
+ struct _citrus_region *r, size_t sz)
+{
+ void *ret;
+
+ if (ms->ms_pos + sz > _citrus_region_size(&ms->ms_region))
+ return (NULL);
+
+ ret = _citrus_region_offset(&ms->ms_region, ms->ms_pos);
+ ms->ms_pos += sz;
+ if (r)
+ _citrus_region_init(r, ret, sz);
+
+ return (ret);
+}
+
+static __inline int
+_citrus_memory_stream_get8(struct _citrus_memory_stream *ms, uint8_t *rval)
+{
+
+ if (ms->ms_pos + 1 > _citrus_region_size(&ms->ms_region))
+ return (-1);
+
+ *rval = _citrus_region_peek8(&ms->ms_region, ms->ms_pos);
+ ms->ms_pos += 2;
+
+ return (0);
+}
+
+static __inline int
+_citrus_memory_stream_get16(struct _citrus_memory_stream *ms, uint16_t *rval)
+{
+
+ if (ms->ms_pos + 2 > _citrus_region_size(&ms->ms_region))
+ return (-1);
+
+ *rval = _citrus_region_peek16(&ms->ms_region, ms->ms_pos);
+ ms->ms_pos += 2;
+
+ return (0);
+}
+
+static __inline int
+_citrus_memory_stream_get32(struct _citrus_memory_stream *ms, uint32_t *rval)
+{
+
+ if (ms->ms_pos + 4 > _citrus_region_size(&ms->ms_region))
+ return (-1);
+
+ *rval = _citrus_region_peek32(&ms->ms_region, ms->ms_pos);
+ ms->ms_pos += 4;
+
+ return (0);
+}
+
+static __inline int
+_citrus_memory_stream_getln_region(struct _citrus_memory_stream *ms,
+ struct _citrus_region *r)
+{
+ const char *ptr;
+ size_t sz;
+
+ ptr = _citrus_memory_stream_getln(ms, &sz);
+ if (ptr)
+ _citrus_region_init(r, __DECONST(void *, ptr), sz);
+
+ return (ptr == NULL);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_mmap.c b/lib/libc/iconv/citrus_mmap.c
new file mode 100644
index 0000000..dd5d059
--- /dev/null
+++ b/lib/libc/iconv/citrus_mmap.c
@@ -0,0 +1,97 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mmap.c,v 1.3 2005/01/19 00:52:37 mycroft Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+#include <sys/types.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)
+{
+ struct stat st;
+ void *head;
+ int fd, ret;
+
+ ret = 0;
+
+ _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)
+{
+
+ if (_region_head(r) != NULL) {
+ (void)munmap(_region_head(r), _region_size(r));
+ _region_init(r, NULL, 0);
+ }
+}
diff --git a/lib/libc/iconv/citrus_mmap.h b/lib/libc/iconv/citrus_mmap.h
new file mode 100644
index 0000000..590e7fb
--- /dev/null
+++ b/lib/libc/iconv/citrus_mmap.h
@@ -0,0 +1,40 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mmap.h,v 1.1 2003/06/25 09:51:38 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_MMAP_H_
+#define _CITRUS_MMAP_H_
+
+__BEGIN_DECLS
+int _citrus_map_file(struct _citrus_region * __restrict,
+ const char * __restrict);
+void _citrus_unmap_file(struct _citrus_region *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_module.c b/lib/libc/iconv/citrus_module.c
new file mode 100644
index 0000000..aa96aba
--- /dev/null
+++ b/lib/libc/iconv/citrus_module.c
@@ -0,0 +1,314 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_module.c,v 1.9 2009/01/11 02:46:24 christos 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.
+ *
+ * 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 <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define I18NMODULE_MAJOR 4
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+
+static int _getdewey(int[], char *);
+static int _cmpndewey(int[], int, int[], int);
+static const char *_findshlib(char *, int *, int *);
+
+static const 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;
+
+ 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)_bcs_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)
+{
+ int i;
+
+ 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);
+
+ /* cannot happen */
+ return (0);
+}
+
+static const char *
+_findshlib(char *name, int *majorp, int *minorp)
+{
+ char *lname;
+ const char *search_dirs[1];
+ static char path[PATH_MAX];
+ int dewey[MAXDEWEY], tmp[MAXDEWEY];
+ int i, len, major, minor, ndewey, n_search_dirs;
+
+ n_search_dirs = 1;
+ 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++) {
+ struct dirent *dp;
+ DIR *dd = opendir(search_dirs[i]);
+ int found_dot_a = 0, found_dot_so = 0;
+
+ if (dd == NULL)
+ break;
+
+ 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;
+
+ 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];
+ void *handle;
+ int maj, min;
+
+ 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) {
+ printf("%s", dlerror());
+ return (EINVAL);
+ }
+
+ *rhandle = (_citrus_module_t)handle;
+
+ return (0);
+}
+
+void
+_citrus_unload_module(_citrus_module_t handle)
+{
+
+ if (handle)
+ dlclose((void *)handle);
+}
diff --git a/lib/libc/iconv/citrus_module.h b/lib/libc/iconv/citrus_module.h
new file mode 100644
index 0000000..b004b87
--- /dev/null
+++ b/lib/libc/iconv/citrus_module.h
@@ -0,0 +1,54 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_module.h,v 1.1 2002/03/17 22:14:20 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_MODULE_H_
+#define _CITRUS_MODULE_H_
+
+#define MATCH(x, act) \
+do { \
+ if (lenvar >= (sizeof(#x)-1) && \
+ _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) { \
+ act; \
+ lenvar -= sizeof(#x)-1; \
+ p += sizeof(#x)-1; \
+ } \
+} while (0)
+
+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/iconv/citrus_namespace.h b/lib/libc/iconv/citrus_namespace.h
new file mode 100644
index 0000000..6e9ffe0
--- /dev/null
+++ b/lib/libc/iconv/citrus_namespace.h
@@ -0,0 +1,241 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_namespace.h,v 1.8 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "citrus_bcs.h"
+
+#ifndef _CITRUS_NAMESPACE_H_
+#define _CITRUS_NAMESPACE_H_
+
+/* citrus_alias */
+#ifndef _CITRUS_ALIAS_NO_NAMESPACE
+#define _alias_lookup _citrus_alias_lookup
+#endif /* _CITRUS_ALIAS_NO_NAMESPACE */
+
+/* citrus_bcs */
+#ifndef _CITRUS_BCS_NO_NAMESPACE
+#define _bcs_isalnum _citrus_bcs_isalnum
+#define _bcs_isalpha _citrus_bcs_isalpha
+#define _bcs_isblank _citrus_bcs_isblank
+#define _bcs_isdigit _citrus_bcs_isdigit
+#define _bcs_islower _citrus_bcs_islower
+#define _bcs_iseol _citrus_bcs_iseol
+#define _bcs_isspace _citrus_bcs_isspace
+#define _bcs_isupper _citrus_bcs_isupper
+#define _bcs_isxdigit _citrus_bcs_isxdigit
+#define _bcs_skip_nonws _citrus_bcs_skip_nonws
+#define _bcs_skip_nonws_len _citrus_bcs_skip_nonws_len
+#define _bcs_skip_ws _citrus_bcs_skip_ws
+#define _bcs_skip_ws_len _citrus_bcs_skip_ws_len
+#define _bcs_strcasecmp _citrus_bcs_strcasecmp
+#define _bcs_strncasecmp _citrus_bcs_strncasecmp
+#define _bcs_tolower _citrus_bcs_tolower
+#define _bcs_toupper _citrus_bcs_toupper
+#define _bcs_trunc_rws_len _citrus_bcs_trunc_rws_len
+#define _bcs_convert_to_lower _citrus_bcs_convert_to_lower
+#define _bcs_convert_to_upper _citrus_bcs_convert_to_upper
+#define _bcs_strtol _citrus_bcs_strtol
+#define _bcs_strtoul _citrus_bcs_strtoul
+#endif /* _CITRUS_BCS_NO_NAMESPACE */
+
+/* citrus_csmapper */
+#ifndef _CITRUS_CSMAPPER_NO_NAMESPACE
+#define _csmapper _citrus_csmapper
+#define _csmapper_open _citrus_csmapper_open
+#define _csmapper_close _citrus_csmapper_close
+#define _csmapper_convert _citrus_csmapper_convert
+#define _csmapper_init_state _citrus_csmapper_init_state
+#define _csmapper_get_state_size _citrus_csmapper_get_state_size
+#define _csmapper_get_src_max _citrus_csmapper_get_src_max
+#define _csmapper_get_dst_max _citrus_csmapper_get_dst_max
+#define _CSMAPPER_F_PREVENT_PIVOT _CITRUS_CSMAPPER_F_PREVENT_PIVOT
+#endif /* _CITRUS_CSMAPPER_NO_NAMESPACE */
+
+/* citrus_db */
+#ifndef _CITRUS_DB_NO_NAMESPACE
+#define _db_open _citrus_db_open
+#define _db_close _citrus_db_close
+#define _db_lookup _citrus_db_lookup
+#define _db_lookup_by_s _citrus_db_lookup_by_string
+#define _db_lookup8_by_s _citrus_db_lookup8_by_string
+#define _db_lookup16_by_s _citrus_db_lookup16_by_string
+#define _db_lookup32_by_s _citrus_db_lookup32_by_string
+#define _db_lookupstr_by_s _citrus_db_lookup_string_by_string
+#define _db_hash_std _citrus_db_hash_std
+#define _db_get_num_entries _citrus_db_get_number_of_entries
+#define _db_get_entry _citrus_db_get_entry
+#define _db_locator _citrus_db_locator
+#define _db_locator_init _citrus_db_locator_init
+#endif /* _CITRUS_DB_NO_NAMESPACE */
+
+/* citrus_db_factory */
+#ifndef _CITRUS_DB_FACTORY_NO_NAMESPACE
+#define _db_factory _citrus_db_factory
+#define _db_factory_create _citrus_db_factory_create
+#define _db_factory_free _citrus_db_factory_free
+#define _db_factory_add _citrus_db_factory_add
+#define _db_factory_add_by_s _citrus_db_factory_add_by_string
+#define _db_factory_add8_by_s _citrus_db_factory_add8_by_string
+#define _db_factory_add16_by_s _citrus_db_factory_add16_by_string
+#define _db_factory_add32_by_s _citrus_db_factory_add32_by_string
+#define _db_factory_addstr_by_s _citrus_db_factory_add_string_by_string
+#define _db_factory_calc_size _citrus_db_factory_calc_size
+#define _db_factory_serialize _citrus_db_factory_serialize
+#endif /* _CITRUS_DB_FACTORY_NO_NAMESPACE */
+
+/* citrus_lookup */
+#ifndef _CITRUS_DB_NO_NAMESPACE
+#define _LOOKUP_CASE_SENSITIVE _CITRUS_LOOKUP_CASE_SENSITIVE
+#define _LOOKUP_CASE_IGNORE _CITRUS_LOOKUP_CASE_IGNORE
+#define _lookup _citrus_lookup
+#define _lookup_simple _citrus_lookup_simple
+#define _lookup_alias _citrus_lookup_alias
+#define _lookup_seq_open _citrus_lookup_seq_open
+#define _lookup_seq_rewind _citrus_lookup_seq_rewind
+#define _lookup_seq_next _citrus_lookup_seq_next
+#define _lookup_seq_lookup _citrus_lookup_seq_lookup
+#define _lookup_get_num_entries _citrus_lookup_get_number_of_entries
+#define _lookup_seq_close _citrus_lookup_seq_close
+#define _lookup_factory_convert _citrus_lookup_factory_convert
+#endif /* _CITRUS_DB_NO_NAMESPACE */
+
+/* citrus_esdb */
+#ifndef _CITRUS_ESDB_NO_NAMESPACE
+#define _esdb _citrus_esdb
+#define _esdb_charset _citrus_esdb_charset
+#define _esdb_open _citrus_esdb_open
+#define _esdb_close _citrus_esdb_close
+#define _esdb_get_list _citrus_esdb_get_list
+#define _esdb_free_list _citrus_esdb_free_list
+#endif /* _CITRUS_ESDB_NO_NAMESPACE */
+
+/* citrus_hash */
+#ifndef _CITRUS_HASH_NO_NAMESPACE
+#define _citrus_string_hash_func _string_hash_func
+#endif /* _CITRUS_HASH_NO_NAMESPACE */
+
+/* citrus_mapper */
+#ifndef _CITRUS_MAPPER_NO_NAMESPACE
+#define _mapper _citrus_mapper
+#define _mapper_ops _citrus_mapper_ops
+#define _mapper_traits _citrus_mapper_traits
+#define _mapper_open _citrus_mapper_open
+#define _mapper_open_direct _citrus_mapper_open_direct
+#define _mapper_close _citrus_mapper_close
+#define _MAPPER_CONVERT_SUCCESS _CITRUS_MAPPER_CONVERT_SUCCESS
+#define _MAPPER_CONVERT_NONIDENTICAL _CITRUS_MAPPER_CONVERT_NONIDENTICAL
+#define _MAPPER_CONVERT_SRC_MORE _CITRUS_MAPPER_CONVERT_SRC_MORE
+#define _MAPPER_CONVERT_DST_MORE _CITRUS_MAPPER_CONVERT_DST_MORE
+#define _MAPPER_CONVERT_ILSEQ _CITRUS_MAPPER_CONVERT_ILSEQ
+#define _MAPPER_CONVERT_FATAL _CITRUS_MAPPER_CONVERT_FATAL
+#define _mapper_convert _citrus_mapper_convert
+#define _mapper_init_state _citrus_mapper_init_state
+#define _mapper_get_state_size _citrus_mapper_get_state_size
+#define _mapper_get_src_max _citrus_mapper_get_src_max
+#define _mapper_get_dst_max _citrus_mapper_get_dst_max
+#define _mapper_set_persistent _citrus_mapper_set_persistent
+#endif /* _CITRUS_MAPPER_NO_NAMESPACE */
+
+/* citrus_memstream */
+#ifndef _CITRUS_MEMSTREAM_NO_NAMESPACE
+#define _memstream _citrus_memory_stream
+#define _memstream_getln _citrus_memory_stream_getln
+#define _memstream_matchline _citrus_memory_stream_matchline
+#define _memstream_chr _citrus_memory_stream_chr
+#define _memstream_skip_ws _citrus_memory_stream_skip_ws
+#define _memstream_iseof _citrus_memory_stream_iseof
+#define _memstream_bind _citrus_memory_stream_bind
+#define _memstream_bind_ptr _citrus_memory_stream_bind_ptr
+#define _memstream_seek _citrus_memory_stream_seek
+#define _memstream_rewind _citrus_memory_stream_rewind
+#define _memstream_tell _citrus_memory_stream_tell
+#define _memstream_remainder _citrus_memory_stream_remainder
+#define _memstream_getc _citrus_memory_stream_getc
+#define _memstream_ungetc _citrus_memory_stream_ungetc
+#define _memstream_peek _citrus_memory_stream_peek
+#define _memstream_getregion _citrus_memory_stream_getregion
+#define _memstream_getln_region _citrus_memory_stream_getln_region
+#endif /* _CITRUS_MEMSTREAM_NO_NAMESPACE */
+
+/* citrus_mmap */
+#ifndef _CITRUS_MMAP_NO_NAMESPACE
+#define _map_file _citrus_map_file
+#define _unmap_file _citrus_unmap_file
+#endif /* _CITRUS_MMAP_NO_NAMESPACE */
+
+#ifndef _CITRUS_PIVOT_NO_NAMESPACE
+#define _pivot_factory_convert _citrus_pivot_factory_convert
+#endif /* _CITRUS_PIVOT_NO_NAMESPACE */
+
+/* citrus_region.h */
+#ifndef _CITRUS_REGION_NO_NAMESPACE
+#define _region _citrus_region
+#define _region_init _citrus_region_init
+#define _region_head _citrus_region_head
+#define _region_size _citrus_region_size
+#define _region_check _citrus_region_check
+#define _region_offset _citrus_region_offset
+#define _region_peek8 _citrus_region_peek8
+#define _region_peek16 _citrus_region_peek16
+#define _region_peek32 _citrus_region_peek32
+#define _region_get_subregion _citrus_region_get_subregion
+#endif /* _CITRUS_REGION_NO_NAMESPACE */
+
+/* citrus_stdenc.h */
+#ifndef _CITRUS_STDENC_NO_NAMESPACE
+#define _stdenc _citrus_stdenc
+#define _stdenc_ops _citrus_stdenc_ops
+#define _stdenc_traits _citrus_stdenc_traits
+#define _stdenc_state_desc _citrus_stdenc_state_desc
+#define _stdenc_open _citrus_stdenc_open
+#define _stdenc_close _citrus_stdenc_close
+#define _stdenc_init_state _citrus_stdenc_init_state
+#define _stdenc_mbtocs _citrus_stdenc_mbtocs
+#define _stdenc_cstomb _citrus_stdenc_cstomb
+#define _stdenc_mbtowc _citrus_stdenc_mbtowc
+#define _stdenc_wctomb _citrus_stdenc_wctomb
+#define _stdenc_put_state_reset _citrus_stdenc_put_state_reset
+#define _stdenc_get_state_size _citrus_stdenc_get_state_size
+#define _stdenc_get_mb_cur_max _citrus_stdenc_get_mb_cur_max
+#define _stdenc_get_state_desc _citrus_stdenc_get_state_desc
+#define _STDENC_SDID_GENERIC _CITRUS_STDENC_SDID_GENERIC
+#define _STDENC_SDGEN_UNKNOWN _CITRUS_STDENC_SDGEN_UNKNOWN
+#define _STDENC_SDGEN_INITIAL _CITRUS_STDENC_SDGEN_INITIAL
+#define _STDENC_SDGEN_STABLE _CITRUS_STDENC_SDGEN_STABLE
+#define _STDENC_SDGEN_INCOMPLETE_CHAR _CITRUS_STDENC_SDGEN_INCOMPLETE_CHAR
+#define _STDENC_SDGEN_INCOMPLETE_SHIFT _CITRUS_STDENC_SDGEN_INCOMPLETE_SHIFT
+#endif /* _CITRUS_STDENC_NO_NAMESPACE */
+
+/* citrus_types.h */
+#ifndef _CITRUS_TYPES_NO_NAMESPACE
+#define _index_t _citrus_index_t
+#define _csid_t _citrus_csid_t
+#define _wc_t _citrus_wc_t
+#endif /* _CITRUS_TYPES_NO_NAMESPACE */
+
+#endif
diff --git a/lib/libc/iconv/citrus_none.c b/lib/libc/iconv/citrus_none.c
new file mode 100644
index 0000000..1f77ad0
--- /dev/null
+++ b/lib/libc/iconv/citrus_none.c
@@ -0,0 +1,238 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 2002 Citrus Project,
+ * Copyright (c) 2010 Gabor Kovesdan <gabor@FreeBSD.org>,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <iconv.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_none.h"
+#include "citrus_stdenc.h"
+
+_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
+_citrus_NONE_stdenc_init(struct _citrus_stdenc * __restrict ce,
+ const void *var __unused, size_t lenvar __unused,
+ 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
+_citrus_NONE_stdenc_uninit(struct _citrus_stdenc *ce __unused)
+{
+
+}
+
+static int
+_citrus_NONE_stdenc_init_state(struct _citrus_stdenc * __restrict ce __unused,
+ void * __restrict ps __unused)
+{
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce __unused,
+ _csid_t *csid, _index_t *idx, char **s, size_t n,
+ void *ps __unused, size_t *nresult, struct iconv_hooks *hooks)
+{
+
+ if (n < 1) {
+ *nresult = (size_t)-2;
+ return (0);
+ }
+
+ *csid = 0;
+ *idx = (_index_t)(unsigned char)*(*s)++;
+ *nresult = *idx == 0 ? 0 : 1;
+
+ if ((hooks != NULL) && (hooks->uc_hook != NULL))
+ hooks->uc_hook((unsigned int)*idx, hooks->data);
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_cstomb(struct _citrus_stdenc * __restrict ce __unused,
+ char *s, size_t n, _csid_t csid, _index_t idx, void *ps __unused,
+ size_t *nresult, struct iconv_hooks *hooks __unused)
+{
+
+ if (csid == _CITRUS_CSID_INVALID) {
+ *nresult = 0;
+ return (0);
+ }
+ if (csid != 0)
+ return (EILSEQ);
+
+ if ((idx & 0x000000FF) == idx) {
+ if (n < 1) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ *s = (char)idx;
+ *nresult = 1;
+ } else if ((idx & 0x0000FFFF) == idx) {
+ if (n < 2) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ s[0] = (char)idx;
+ /* XXX: might be endian dependent */
+ s[1] = (char)(idx >> 8);
+ *nresult = 2;
+ } else if ((idx & 0x00FFFFFF) == idx) {
+ if (n < 3) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ s[0] = (char)idx;
+ /* XXX: might be endian dependent */
+ s[1] = (char)(idx >> 8);
+ s[2] = (char)(idx >> 16);
+ *nresult = 3;
+ } else {
+ if (n < 3) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ s[0] = (char)idx;
+ /* XXX: might be endian dependent */
+ s[1] = (char)(idx >> 8);
+ s[2] = (char)(idx >> 16);
+ s[3] = (char)(idx >> 24);
+ *nresult = 4;
+ }
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce __unused,
+ _wc_t * __restrict pwc, char ** __restrict s, size_t n,
+ void * __restrict pspriv __unused, size_t * __restrict nresult,
+ struct iconv_hooks *hooks)
+{
+
+ 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;
+
+ if ((hooks != NULL) && (hooks->wc_hook != NULL))
+ hooks->wc_hook(*pwc, hooks->data);
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce __unused,
+ char * __restrict s, size_t n, _wc_t wc,
+ void * __restrict pspriv __unused, size_t * __restrict nresult,
+ struct iconv_hooks *hooks __unused)
+{
+ int ret;
+
+ if ((wc & ~0xFFU) != 0) {
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ }
+ if (n == 0) {
+ *nresult = (size_t)-1;
+ ret = E2BIG;
+ }
+
+ *nresult = 1;
+ if (s != NULL && n > 0)
+ *s = (char)wc;
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce __unused,
+ char * __restrict s __unused, size_t n __unused,
+ void * __restrict pspriv __unused, size_t * __restrict nresult)
+{
+
+ *nresult = 0;
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_get_state_desc(struct _stdenc * __restrict ce __unused,
+ void * __restrict ps __unused, int id,
+ struct _stdenc_state_desc * __restrict d)
+{
+ int ret = 0;
+
+ switch (id) {
+ case _STDENC_SDID_GENERIC:
+ d->u.generic.state = _STDENC_SDGEN_INITIAL;
+ break;
+ default:
+ ret = EOPNOTSUPP;
+ }
+
+ return (ret);
+}
diff --git a/lib/libc/iconv/citrus_none.h b/lib/libc/iconv/citrus_none.h
new file mode 100644
index 0000000..20d2791
--- /dev/null
+++ b/lib/libc/iconv/citrus_none.h
@@ -0,0 +1,36 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_none.h,v 1.3 2003/06/25 09:51:38 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_NONE_H_
+#define _CITRUS_NONE_H_
+
+extern struct _citrus_stdenc_ops _citrus_NONE_stdenc_ops;
+extern struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits;
+
+#endif
diff --git a/lib/libc/iconv/citrus_pivot_factory.c b/lib/libc/iconv/citrus_pivot_factory.c
new file mode 100644
index 0000000..0f279b1
--- /dev/null
+++ b/lib/libc/iconv/citrus_pivot_factory.c
@@ -0,0 +1,225 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_pivot_factory.c,v 1.7 2009/04/12 14:20:19 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#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)
+{
+ struct src_entry *se;
+ const char *p;
+ char key1[LINE_MAX], key2[LINE_MAX], data[LINE_MAX];
+ char *ep;
+ uint32_t val;
+ int ret;
+
+ se = NULL;
+
+ /* 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);
+ val = strtoul(data, &ep, 0);
+ if (*ep != '\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)
+{
+ struct _db_factory *df;
+ struct src_entry *se;
+ struct _region subr;
+ void *ptr;
+ size_t size;
+ int ret;
+
+ 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/iconv/citrus_pivot_factory.h b/lib/libc/iconv/citrus_pivot_factory.h
new file mode 100644
index 0000000..76f0f70
--- /dev/null
+++ b/lib/libc/iconv/citrus_pivot_factory.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_pivot_factory.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_PIVOT_FACTORY_H_
+#define _CITRUS_PIVOT_FACTORY_H_
+
+__BEGIN_DECLS
+int _citrus_pivot_factory_convert(FILE *, FILE *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_pivot_file.h b/lib/libc/iconv/citrus_pivot_file.h
new file mode 100644
index 0000000..454e93a
--- /dev/null
+++ b/lib/libc/iconv/citrus_pivot_file.h
@@ -0,0 +1,36 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_pivot_file.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_PIVOT_FILE_H_
+#define _CITRUS_PIVOT_FILE_H_
+
+#define _CITRUS_PIVOT_MAGIC "CSPIVOT\0"
+#define _CITRUS_PIVOT_SUB_MAGIC "CSPIVSUB"
+
+#endif
diff --git a/lib/libc/iconv/citrus_prop.c b/lib/libc/iconv/citrus_prop.c
new file mode 100644
index 0000000..c2d4829
--- /dev/null
+++ b/lib/libc/iconv/citrus_prop.c
@@ -0,0 +1,444 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_prop.c,v 1.3 2006/11/22 23:47:21 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_prop.h"
+
+typedef struct {
+ _citrus_prop_type_t type;
+ union {
+ const char *str;
+ int chr;
+ bool boolean;
+ uint64_t num;
+ } u;
+} _citrus_prop_object_t;
+
+static __inline void
+_citrus_prop_object_init(_citrus_prop_object_t *obj, _citrus_prop_type_t type)
+{
+
+ obj->type = type;
+ memset(&obj->u, 0, sizeof(obj->u));
+}
+
+static __inline void
+_citrus_prop_object_uninit(_citrus_prop_object_t *obj)
+{
+
+ if (obj->type == _CITRUS_PROP_STR)
+ free(__DECONST(void *, obj->u.str));
+}
+
+static const char *xdigit = "0123456789ABCDEF";
+
+#define _CITRUS_PROP_READ_UINT_COMMON(_func_, _type_, _max_) \
+static int \
+_citrus_prop_read_##_func_##_common(struct _memstream * __restrict ms, \
+ _type_ * __restrict result, int base) \
+{ \
+ _type_ acc, cutoff; \
+ int ch, cutlim, n; \
+ char *p; \
+ \
+ acc = (_type_)0; \
+ cutoff = _max_ / base; \
+ cutlim = _max_ % base; \
+ for (;;) { \
+ ch = _memstream_getc(ms); \
+ p = strchr(xdigit, _bcs_toupper(ch)); \
+ if (p == NULL || (n = (p - xdigit)) >= base) \
+ break; \
+ if (acc > cutoff || (acc == cutoff && n > cutlim)) \
+ break; \
+ acc *= base; \
+ acc += n; \
+ } \
+ _memstream_ungetc(ms, ch); \
+ *result = acc; \
+ return (0); \
+}
+_CITRUS_PROP_READ_UINT_COMMON(chr, int, UCHAR_MAX)
+_CITRUS_PROP_READ_UINT_COMMON(num, uint64_t, UINT64_MAX)
+#undef _CITRUS_PROP_READ_UINT_COMMON
+
+#define _CITRUS_PROP_READ_INT(_func_, _type_) \
+static int \
+_citrus_prop_read_##_func_(struct _memstream * __restrict ms, \
+ _citrus_prop_object_t * __restrict obj) \
+{ \
+ int base, ch, neg; \
+ \
+ _memstream_skip_ws(ms); \
+ ch = _memstream_getc(ms); \
+ neg = 0; \
+ switch (ch) { \
+ case '-': \
+ neg = 1; \
+ case '+': \
+ ch = _memstream_getc(ms); \
+ } \
+ base = 10; \
+ if (ch == '0') { \
+ base -= 2; \
+ ch = _memstream_getc(ms); \
+ if (ch == 'x' || ch == 'X') { \
+ ch = _memstream_getc(ms); \
+ if (_bcs_isxdigit(ch) == 0) { \
+ _memstream_ungetc(ms, ch); \
+ obj->u._func_ = 0; \
+ return (0); \
+ } \
+ base += 8; \
+ } \
+ } else if (_bcs_isdigit(ch) == 0) \
+ return (EINVAL); \
+ _memstream_ungetc(ms, ch); \
+ return (_citrus_prop_read_##_func_##_common \
+ (ms, &obj->u._func_, base)); \
+}
+_CITRUS_PROP_READ_INT(chr, int)
+_CITRUS_PROP_READ_INT(num, uint64_t)
+#undef _CITRUS_PROP_READ_INT
+
+static int
+_citrus_prop_read_character_common(struct _memstream * __restrict ms,
+ int * __restrict result)
+{
+ int base, ch;
+
+ ch = _memstream_getc(ms);
+ if (ch != '\\')
+ *result = ch;
+ else {
+ ch = _memstream_getc(ms);
+ base = 16;
+ switch (ch) {
+ case 'a':
+ *result = '\a';
+ break;
+ case 'b':
+ *result = '\b';
+ break;
+ case 'f':
+ *result = '\f';
+ break;
+ case 'n':
+ *result = '\n';
+ break;
+ case 'r':
+ *result = '\r';
+ break;
+ case 't':
+ *result = '\t';
+ break;
+ case 'v':
+ *result = '\v';
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ _memstream_ungetc(ms, ch);
+ base -= 8;
+ /*FALLTHROUGH*/
+ case 'x':
+ return (_citrus_prop_read_chr_common(ms, result, base));
+ /*NOTREACHED*/
+ default:
+ /* unknown escape */
+ *result = ch;
+ }
+ }
+ return (0);
+}
+
+static int
+_citrus_prop_read_character(struct _memstream * __restrict ms,
+ _citrus_prop_object_t * __restrict obj)
+{
+ int ch, errnum;
+
+ _memstream_skip_ws(ms);
+ ch = _memstream_getc(ms);
+ if (ch != '\'') {
+ _memstream_ungetc(ms, ch);
+ return (_citrus_prop_read_chr(ms, obj));
+ }
+ errnum = _citrus_prop_read_character_common(ms, &ch);
+ if (errnum != 0)
+ return (errnum);
+ obj->u.chr = ch;
+ ch = _memstream_getc(ms);
+ if (ch != '\'')
+ return (EINVAL);
+ return (0);
+}
+
+static int
+_citrus_prop_read_bool(struct _memstream * __restrict ms,
+ _citrus_prop_object_t * __restrict obj)
+{
+
+ _memstream_skip_ws(ms);
+ switch (_bcs_tolower(_memstream_getc(ms))) {
+ case 't':
+ if (_bcs_tolower(_memstream_getc(ms)) == 'r' &&
+ _bcs_tolower(_memstream_getc(ms)) == 'u' &&
+ _bcs_tolower(_memstream_getc(ms)) == 'e') {
+ obj->u.boolean = true;
+ return (0);
+ }
+ break;
+ case 'f':
+ if (_bcs_tolower(_memstream_getc(ms)) == 'a' &&
+ _bcs_tolower(_memstream_getc(ms)) == 'l' &&
+ _bcs_tolower(_memstream_getc(ms)) == 's' &&
+ _bcs_tolower(_memstream_getc(ms)) == 'e') {
+ obj->u.boolean = false;
+ return (0);
+ }
+ }
+ return (EINVAL);
+}
+
+static int
+_citrus_prop_read_str(struct _memstream * __restrict ms,
+ _citrus_prop_object_t * __restrict obj)
+{
+ int ch, errnum, quot;
+ char *s, *t;
+#define _CITRUS_PROP_STR_BUFSIZ 512
+ size_t m, n;
+
+ m = _CITRUS_PROP_STR_BUFSIZ;
+ s = malloc(m);
+ if (s == NULL)
+ return (ENOMEM);
+ n = 0;
+ _memstream_skip_ws(ms);
+ quot = _memstream_getc(ms);
+ switch (quot) {
+ case EOF:
+ goto done;
+ /*NOTREACHED*/
+ case '\\':
+ _memstream_ungetc(ms, quot);
+ quot = EOF;
+ /*FALLTHROUGH*/
+ case '\"': case '\'':
+ break;
+ default:
+ s[n] = quot;
+ ++n, --m;
+ quot = EOF;
+ }
+ for (;;) {
+ if (m < 1) {
+ m = _CITRUS_PROP_STR_BUFSIZ;
+ t = realloc(s, n + m);
+ if (t == NULL) {
+ free(s);
+ return (ENOMEM);
+ }
+ s = t;
+ }
+ ch = _memstream_getc(ms);
+ if (quot == ch || (quot == EOF &&
+ (ch == ';' || _bcs_isspace(ch)))) {
+done:
+ s[n] = '\0';
+ obj->u.str = (const char *)s;
+ return (0);
+ }
+ _memstream_ungetc(ms, ch);
+ errnum = _citrus_prop_read_character_common(ms, &ch);
+ if (errnum != 0)
+ return (errnum);
+ s[n] = ch;
+ ++n, --m;
+ }
+ free(s);
+ return (EINVAL);
+#undef _CITRUS_PROP_STR_BUFSIZ
+}
+
+typedef int (*_citrus_prop_read_type_t)(struct _memstream * __restrict,
+ _citrus_prop_object_t * __restrict);
+
+static const _citrus_prop_read_type_t readers[] = {
+ _citrus_prop_read_bool,
+ _citrus_prop_read_str,
+ _citrus_prop_read_character,
+ _citrus_prop_read_num,
+};
+
+static __inline int
+_citrus_prop_read_symbol(struct _memstream * __restrict ms,
+ char * __restrict s, size_t n)
+{
+ int ch;
+ size_t m;
+
+ for (m = 0; m < n; ++m) {
+ ch = _memstream_getc(ms);
+ if (ch != '_' && _bcs_isalnum(ch) == 0)
+ goto name_found;
+ s[m] = ch;
+ }
+ ch = _memstream_getc(ms);
+ if (ch == '_' || _bcs_isalnum(ch) != 0)
+ return (EINVAL);
+
+name_found:
+ _memstream_ungetc(ms, ch);
+ s[m] = '\0';
+
+ return (0);
+}
+
+static int
+_citrus_prop_parse_element(struct _memstream * __restrict ms,
+ const _citrus_prop_hint_t * __restrict hints, void ** __restrict context)
+{
+ int ch, errnum;
+#define _CITRUS_PROP_HINT_NAME_LEN_MAX 255
+ char name[_CITRUS_PROP_HINT_NAME_LEN_MAX + 1];
+ const _citrus_prop_hint_t *hint;
+ _citrus_prop_object_t ostart, oend;
+
+ errnum = _citrus_prop_read_symbol(ms, name, sizeof(name));
+ if (errnum != 0)
+ return (errnum);
+ for (hint = hints; hint->name != NULL; ++hint)
+ if (_citrus_bcs_strcasecmp(name, hint->name) == 0)
+ goto hint_found;
+ return (EINVAL);
+
+hint_found:
+ _memstream_skip_ws(ms);
+ ch = _memstream_getc(ms);
+ if (ch != '=' && ch != ':')
+ _memstream_ungetc(ms, ch);
+ do {
+ _citrus_prop_object_init(&ostart, hint->type);
+ _citrus_prop_object_init(&oend, hint->type);
+ errnum = (*readers[hint->type])(ms, &ostart);
+ if (errnum != 0)
+ return (errnum);
+ _memstream_skip_ws(ms);
+ ch = _memstream_getc(ms);
+ switch (hint->type) {
+ case _CITRUS_PROP_BOOL:
+ /*FALLTHROUGH*/
+ case _CITRUS_PROP_STR:
+ break;
+ default:
+ if (ch != '-')
+ break;
+ errnum = (*readers[hint->type])(ms, &oend);
+ if (errnum != 0)
+ return (errnum);
+ _memstream_skip_ws(ms);
+ ch = _memstream_getc(ms);
+ }
+#define CALL0(_func_) \
+do { \
+ errnum = (*hint->cb._func_.func)(context, \
+ hint->name, ostart.u._func_); \
+} while (0)
+#define CALL1(_func_) \
+do { \
+ errnum = (*hint->cb._func_.func)(context, \
+ hint->name, ostart.u._func_, oend.u._func_);\
+} while (0)
+ switch (hint->type) {
+ case _CITRUS_PROP_BOOL:
+ CALL0(boolean);
+ break;
+ case _CITRUS_PROP_STR:
+ CALL0(str);
+ break;
+ case _CITRUS_PROP_CHR:
+ CALL1(chr);
+ break;
+ case _CITRUS_PROP_NUM:
+ CALL1(num);
+ break;
+ default:
+ abort();
+ /*NOTREACHED*/
+ }
+#undef CALL0
+#undef CALL1
+ _citrus_prop_object_uninit(&ostart);
+ _citrus_prop_object_uninit(&oend);
+ if (errnum != 0)
+ return (errnum);
+ } while (ch == ',');
+ if (ch != ';')
+ _memstream_ungetc(ms, ch);
+ return (0);
+}
+
+int
+_citrus_prop_parse_variable(const _citrus_prop_hint_t * __restrict hints,
+ void * __restrict context, const void *var, size_t lenvar)
+{
+ struct _memstream ms;
+ int ch, errnum;
+
+ _memstream_bind_ptr(&ms, __DECONST(void *, var), lenvar);
+ for (;;) {
+ _memstream_skip_ws(&ms);
+ ch = _memstream_getc(&ms);
+ if (ch == EOF || ch == '\0')
+ break;
+ _memstream_ungetc(&ms, ch);
+ errnum = _citrus_prop_parse_element(
+ &ms, hints, (void ** __restrict)context);
+ if (errnum != 0)
+ return (errnum);
+ }
+ return (0);
+}
diff --git a/lib/libc/iconv/citrus_prop.h b/lib/libc/iconv/citrus_prop.h
new file mode 100644
index 0000000..db087a4
--- /dev/null
+++ b/lib/libc/iconv/citrus_prop.h
@@ -0,0 +1,92 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_prop.h,v 1.3 2006/11/23 13:59:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_PROP_H_
+#define _CITRUS_PROP_H_
+
+typedef enum {
+ _CITRUS_PROP_BOOL = 0,
+ _CITRUS_PROP_STR = 1,
+ _CITRUS_PROP_CHR = 2,
+ _CITRUS_PROP_NUM = 3,
+} _citrus_prop_type_t;
+
+typedef struct _citrus_prop_hint_t _citrus_prop_hint_t;
+
+#define _CITRUS_PROP_CB0_T(_func_, _type_) \
+typedef int (*_citrus_prop_##_func_##_cb_func_t) \
+ (void ** __restrict, const char *, _type_); \
+typedef struct { \
+ _citrus_prop_##_func_##_cb_func_t func; \
+} _citrus_prop_##_func_##_cb_t;
+_CITRUS_PROP_CB0_T(boolean, int)
+_CITRUS_PROP_CB0_T(str, const char *)
+#undef _CITRUS_PROP_CB0_T
+
+#define _CITRUS_PROP_CB1_T(_func_, _type_) \
+typedef int (*_citrus_prop_##_func_##_cb_func_t) \
+ (void ** __restrict, const char *, _type_, _type_); \
+typedef struct { \
+ _citrus_prop_##_func_##_cb_func_t func; \
+} _citrus_prop_##_func_##_cb_t;
+_CITRUS_PROP_CB1_T(chr, int)
+_CITRUS_PROP_CB1_T(num, uint64_t)
+#undef _CITRUS_PROP_CB1_T
+
+struct _citrus_prop_hint_t {
+ const char *name;
+ _citrus_prop_type_t type;
+#define _CITRUS_PROP_CB_T_OPS(_name_) \
+ _citrus_prop_##_name_##_cb_t _name_
+ union {
+ _CITRUS_PROP_CB_T_OPS(boolean);
+ _CITRUS_PROP_CB_T_OPS(str);
+ _CITRUS_PROP_CB_T_OPS(chr);
+ _CITRUS_PROP_CB_T_OPS(num);
+ } cb;
+};
+
+#define _CITRUS_PROP_HINT_BOOL(name, cb) \
+ { name, _CITRUS_PROP_BOOL, { .boolean = { cb } } }
+#define _CITRUS_PROP_HINT_STR(name, cb) \
+ { name, _CITRUS_PROP_STR, { .str = { cb } } }
+#define _CITRUS_PROP_HINT_CHR(name, cb) \
+ { name, _CITRUS_PROP_CHR, { .chr = { cb } } }
+#define _CITRUS_PROP_HINT_NUM(name, cb) \
+ { name, _CITRUS_PROP_NUM, { .num = { cb } } }
+#define _CITRUS_PROP_HINT_END \
+ { NULL, _CITRUS_PROP_NUM, { .num = { 0 } } }
+
+__BEGIN_DECLS
+int _citrus_prop_parse_variable(const _citrus_prop_hint_t * __restrict,
+ void * __restrict, const void *, size_t);
+__END_DECLS
+
+#endif /* !_CITRUS_PROP_H_ */
diff --git a/lib/libc/iconv/citrus_region.h b/lib/libc/iconv/citrus_region.h
new file mode 100644
index 0000000..8cecb40
--- /dev/null
+++ b/lib/libc/iconv/citrus_region.h
@@ -0,0 +1,113 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_region.h,v 1.7 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_REGION_H_
+#define _CITRUS_REGION_H_
+
+#include <sys/types.h>
+
+struct _citrus_region {
+ void *r_head;
+ size_t r_size;
+};
+
+static __inline void
+_citrus_region_init(struct _citrus_region *r, void *h, size_t sz)
+{
+
+ r->r_head = h;
+ r->r_size = sz;
+}
+
+static __inline void *
+_citrus_region_head(const struct _citrus_region *r)
+{
+
+ return (r->r_head);
+}
+
+static __inline size_t
+_citrus_region_size(const struct _citrus_region *r)
+{
+
+ return (r->r_size);
+}
+
+static __inline int
+_citrus_region_check(const struct _citrus_region *r, size_t ofs, size_t sz)
+{
+
+ return (r->r_size >= ofs + sz ? 0 : -1);
+}
+
+static __inline void *
+_citrus_region_offset(const struct _citrus_region *r, size_t pos)
+{
+
+ return ((void *)((uint8_t *)r->r_head + pos));
+}
+
+static __inline uint8_t
+_citrus_region_peek8(const struct _citrus_region *r, size_t pos)
+{
+
+ return (*(uint8_t *)_citrus_region_offset(r, pos));
+}
+
+static __inline uint16_t
+_citrus_region_peek16(const struct _citrus_region *r, size_t pos)
+{
+ uint16_t val;
+
+ memcpy(&val, _citrus_region_offset(r, pos), (size_t)2);
+ return (val);
+}
+
+static __inline uint32_t
+_citrus_region_peek32(const struct _citrus_region *r, size_t pos)
+{
+ uint32_t val;
+
+ memcpy(&val, _citrus_region_offset(r, pos), (size_t)4);
+ return (val);
+}
+
+static __inline int
+_citrus_region_get_subregion(struct _citrus_region *subr,
+ const struct _citrus_region *r, size_t ofs, size_t sz)
+{
+
+ if (_citrus_region_check(r, ofs, sz))
+ return (-1);
+ _citrus_region_init(subr, _citrus_region_offset(r, ofs), sz);
+ return (0);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_stdenc.c b/lib/libc/iconv/citrus_stdenc.c
new file mode 100644
index 0000000..b6562f8
--- /dev/null
+++ b/lib/libc/iconv/citrus_stdenc.c
@@ -0,0 +1,145 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_stdenc.c,v 1.3 2005/10/29 18:02:04 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#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_none.h"
+#include "citrus_stdenc.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 */
+};
+
+int
+_citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce,
+ char const * __restrict encname, const void * __restrict variable,
+ size_t lenvar)
+{
+ struct _citrus_stdenc *ce;
+ _citrus_module_t handle;
+ _citrus_stdenc_getops_t getops;
+ int ret;
+
+ 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));
+ if (ret)
+ goto bad;
+
+ /* validation check */
+ if (ce->ce_ops->eo_init == NULL ||
+ ce->ce_ops->eo_uninit == NULL ||
+ ce->ce_ops->eo_init_state == NULL ||
+ ce->ce_ops->eo_mbtocs == NULL ||
+ ce->ce_ops->eo_cstomb == NULL ||
+ ce->ce_ops->eo_mbtowc == NULL ||
+ ce->ce_ops->eo_wctomb == NULL ||
+ ce->ce_ops->eo_get_state_desc == NULL)
+ 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)
+{
+
+ 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);
+}
diff --git a/lib/libc/iconv/citrus_stdenc.h b/lib/libc/iconv/citrus_stdenc.h
new file mode 100644
index 0000000..50f4dff
--- /dev/null
+++ b/lib/libc/iconv/citrus_stdenc.h
@@ -0,0 +1,124 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_stdenc.h,v 1.4 2005/10/29 18:02:04 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_STDENC_H_
+#define _CITRUS_STDENC_H_
+
+struct _citrus_stdenc;
+struct _citrus_stdenc_ops;
+struct _citrus_stdenc_traits;
+
+#define _CITRUS_STDENC_SDID_GENERIC 0
+struct _citrus_stdenc_state_desc
+{
+ union {
+ struct {
+ int state;
+#define _CITRUS_STDENC_SDGEN_UNKNOWN 0
+#define _CITRUS_STDENC_SDGEN_INITIAL 1
+#define _CITRUS_STDENC_SDGEN_STABLE 2
+#define _CITRUS_STDENC_SDGEN_INCOMPLETE_CHAR 3
+#define _CITRUS_STDENC_SDGEN_INCOMPLETE_SHIFT 4
+ } generic;
+ } u;
+};
+
+#include "citrus_stdenc_local.h"
+
+__BEGIN_DECLS
+int _citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict,
+ char const * __restrict, const void * __restrict, size_t);
+void _citrus_stdenc_close(struct _citrus_stdenc *);
+__END_DECLS
+
+static __inline int
+_citrus_stdenc_init_state(struct _citrus_stdenc * __restrict ce,
+ void * __restrict ps)
+{
+
+ 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,
+ char ** __restrict s, size_t n, void * __restrict ps,
+ size_t * __restrict nresult, struct iconv_hooks *hooks)
+{
+
+ return ((*ce->ce_ops->eo_mbtocs)(ce, csid, idx, s, n, ps, nresult,
+ hooks));
+}
+
+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,
+ struct iconv_hooks *hooks)
+{
+
+ return ((*ce->ce_ops->eo_cstomb)(ce, s, n, csid, idx, ps, nresult,
+ hooks));
+}
+
+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, struct iconv_hooks *hooks)
+{
+
+ return ((*ce->ce_ops->eo_wctomb)(ce, s, n, wc, ps, nresult, hooks));
+}
+
+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)
+{
+
+ 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)
+{
+
+ return (ce->ce_traits->et_state_size);
+}
+
+static __inline int
+_citrus_stdenc_get_state_desc(struct _citrus_stdenc * __restrict ce,
+ void * __restrict ps, int id,
+ struct _citrus_stdenc_state_desc * __restrict d)
+{
+
+ return ((*ce->ce_ops->eo_get_state_desc)(ce, ps, id, d));
+}
+#endif
diff --git a/lib/libc/iconv/citrus_stdenc_local.h b/lib/libc/iconv/citrus_stdenc_local.h
new file mode 100644
index 0000000..c55387a
--- /dev/null
+++ b/lib/libc/iconv/citrus_stdenc_local.h
@@ -0,0 +1,161 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_stdenc_local.h,v 1.4 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_STDENC_LOCAL_H_
+#define _CITRUS_STDENC_LOCAL_H_
+
+#include <iconv.h>
+
+#include "citrus_module.h"
+
+#define _CITRUS_STDENC_GETOPS_FUNC_BASE(n) \
+ int n(struct _citrus_stdenc_ops *, size_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, \
+ char ** __restrict, size_t, \
+ void * __restrict, size_t * __restrict, \
+ struct iconv_hooks *); \
+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, struct iconv_hooks *); \
+static int _citrus_##_e_##_stdenc_mbtowc \
+ (struct _citrus_stdenc * __restrict, \
+ _citrus_wc_t * __restrict, \
+ char ** __restrict, size_t, \
+ void * __restrict, size_t * __restrict, \
+ struct iconv_hooks *); \
+static int _citrus_##_e_##_stdenc_wctomb \
+ (struct _citrus_stdenc * __restrict, \
+ char * __restrict, size_t, _citrus_wc_t, \
+ void * __restrict, size_t * __restrict, \
+ struct iconv_hooks *); \
+static int _citrus_##_e_##_stdenc_put_state_reset \
+ (struct _citrus_stdenc * __restrict, \
+ char * __restrict, size_t, void * __restrict, \
+ size_t * __restrict); \
+static int _citrus_##_e_##_stdenc_get_state_desc \
+ (struct _citrus_stdenc * __restrict, \
+ void * __restrict, int, \
+ struct _citrus_stdenc_state_desc * __restrict)
+
+#define _CITRUS_STDENC_DEF_OPS(_e_) \
+struct _citrus_stdenc_ops _citrus_##_e_##_stdenc_ops = { \
+ /* eo_init */ &_citrus_##_e_##_stdenc_init, \
+ /* eo_uninit */ &_citrus_##_e_##_stdenc_uninit, \
+ /* eo_init_state */ &_citrus_##_e_##_stdenc_init_state, \
+ /* eo_mbtocs */ &_citrus_##_e_##_stdenc_mbtocs, \
+ /* eo_cstomb */ &_citrus_##_e_##_stdenc_cstomb, \
+ /* eo_mbtowc */ &_citrus_##_e_##_stdenc_mbtowc, \
+ /* eo_wctomb */ &_citrus_##_e_##_stdenc_wctomb, \
+ /* eo_put_state_reset */&_citrus_##_e_##_stdenc_put_state_reset,\
+ /* eo_get_state_desc */ &_citrus_##_e_##_stdenc_get_state_desc \
+}
+
+typedef int (*_citrus_stdenc_init_t)
+ (struct _citrus_stdenc * __reatrict, const void * __restrict , size_t,
+ struct _citrus_stdenc_traits * __restrict);
+typedef void (*_citrus_stdenc_uninit_t)(struct _citrus_stdenc * __restrict);
+typedef int (*_citrus_stdenc_init_state_t)
+ (struct _citrus_stdenc * __restrict, void * __restrict);
+typedef int (*_citrus_stdenc_mbtocs_t)
+ (struct _citrus_stdenc * __restrict,
+ _citrus_csid_t * __restrict, _citrus_index_t * __restrict,
+ char ** __restrict, size_t,
+ void * __restrict, size_t * __restrict,
+ struct iconv_hooks *);
+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, struct iconv_hooks *);
+typedef int (*_citrus_stdenc_mbtowc_t)
+ (struct _citrus_stdenc * __restrict,
+ _citrus_wc_t * __restrict,
+ char ** __restrict, size_t,
+ void * __restrict, size_t * __restrict,
+ struct iconv_hooks *);
+typedef int (*_citrus_stdenc_wctomb_t)
+ (struct _citrus_stdenc *__restrict, char * __restrict, size_t,
+ _citrus_wc_t, void * __restrict, size_t * __restrict,
+ struct iconv_hooks *);
+typedef int (*_citrus_stdenc_put_state_reset_t)
+ (struct _citrus_stdenc *__restrict, char * __restrict, size_t,
+ void * __restrict, size_t * __restrict);
+typedef int (*_citrus_stdenc_get_state_desc_t)
+ (struct _citrus_stdenc * __restrict, void * __restrict, int,
+ struct _citrus_stdenc_state_desc * __restrict);
+
+struct _citrus_stdenc_ops {
+ _citrus_stdenc_init_t eo_init;
+ _citrus_stdenc_uninit_t eo_uninit;
+ _citrus_stdenc_init_state_t eo_init_state;
+ _citrus_stdenc_mbtocs_t eo_mbtocs;
+ _citrus_stdenc_cstomb_t eo_cstomb;
+ _citrus_stdenc_mbtowc_t eo_mbtowc;
+ _citrus_stdenc_wctomb_t eo_wctomb;
+ _citrus_stdenc_put_state_reset_t eo_put_state_reset;
+ /* version 0x00000002 */
+ _citrus_stdenc_get_state_desc_t eo_get_state_desc;
+};
+
+struct _citrus_stdenc_traits {
+ /* version 0x00000001 */
+ size_t et_state_size;
+ size_t et_mb_cur_max;
+};
+
+struct _citrus_stdenc {
+ /* version 0x00000001 */
+ struct _citrus_stdenc_ops *ce_ops;
+ void *ce_closure;
+ _citrus_module_t ce_module;
+ struct _citrus_stdenc_traits *ce_traits;
+};
+
+#define _CITRUS_DEFAULT_STDENC_NAME "NONE"
+
+#endif
diff --git a/lib/libc/iconv/citrus_stdenc_template.h b/lib/libc/iconv/citrus_stdenc_template.h
new file mode 100644
index 0000000..9a05fa7
--- /dev/null
+++ b/lib/libc/iconv/citrus_stdenc_template.h
@@ -0,0 +1,211 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_stdenc_template.h,v 1.4 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <iconv.h>
+
+/*
+ * 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 __unused)
+{
+
+ 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)
+{
+ _ENCODING_INFO *ei;
+ int ret;
+
+ 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,
+ char ** __restrict s, size_t n, void * __restrict ps,
+ size_t * __restrict nresult, struct iconv_hooks *hooks)
+{
+ wchar_t wc;
+ int ret;
+
+ ret = _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), &wc, s, n,
+ _TO_STATE(ps), nresult);
+
+ if ((ret == 0) && *nresult != (size_t)-2)
+ ret = _FUNCNAME(stdenc_wctocs)(_CE_TO_EI(ce), csid, idx, wc);
+
+ if ((ret == 0) && (hooks != NULL) && (hooks->uc_hook != NULL))
+ hooks->uc_hook((unsigned int)*idx, hooks->data);
+ 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,
+ struct iconv_hooks *hooks __unused)
+{
+ wchar_t wc;
+ int ret;
+
+ wc = ret = 0;
+
+ if (csid != _CITRUS_CSID_INVALID)
+ ret = _FUNCNAME(stdenc_cstowc)(_CE_TO_EI(ce), &wc, csid, idx);
+
+ if (ret == 0)
+ ret = _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc,
+ _TO_STATE(ps), nresult);
+ return (ret);
+}
+
+static int
+_FUNCNAME(stdenc_mbtowc)(struct _citrus_stdenc * __restrict ce,
+ _citrus_wc_t * __restrict wc, char ** __restrict s, size_t n,
+ void * __restrict ps, size_t * __restrict nresult,
+ struct iconv_hooks *hooks)
+{
+ int ret;
+
+ ret = _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), wc, s, n,
+ _TO_STATE(ps), nresult);
+ if ((ret == 0) && (hooks != NULL) && (hooks->wc_hook != NULL))
+ hooks->wc_hook(*wc, hooks->data);
+ return (ret);
+}
+
+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, struct iconv_hooks *hooks __unused)
+{
+ int ret;
+
+ ret = _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc, _TO_STATE(ps),
+ nresult);
+ return (ret);
+}
+
+static int
+_FUNCNAME(stdenc_put_state_reset)(struct _citrus_stdenc * __restrict ce __unused,
+ char * __restrict s __unused, size_t n __unused,
+ void * __restrict ps __unused, size_t * __restrict nresult)
+{
+
+#if _ENCODING_IS_STATE_DEPENDENT
+ return ((_FUNCNAME(put_state_reset)(_CE_TO_EI(ce), s, n, _TO_STATE(ps),
+ nresult)));
+#else
+ *nresult = 0;
+ return (0);
+#endif
+}
+
+static int
+_FUNCNAME(stdenc_get_state_desc)(struct _citrus_stdenc * __restrict ce,
+ void * __restrict ps, int id,
+ struct _citrus_stdenc_state_desc * __restrict d)
+{
+ int ret;
+
+ switch (id) {
+ case _STDENC_SDID_GENERIC:
+ ret = _FUNCNAME(stdenc_get_state_desc_generic)(
+ _CE_TO_EI(ce), _TO_STATE(ps), &d->u.generic.state);
+ break;
+ default:
+ ret = EOPNOTSUPP;
+ }
+
+ return (ret);
+}
diff --git a/lib/libc/iconv/citrus_types.h b/lib/libc/iconv/citrus_types.h
new file mode 100644
index 0000000..5f9c4e3
--- /dev/null
+++ b/lib/libc/iconv/citrus_types.h
@@ -0,0 +1,40 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_types.h,v 1.3 2003/10/27 00:12:42 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#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/iconv/iconv.3 b/lib/libc/iconv/iconv.3
new file mode 100644
index 0000000..9b658e9
--- /dev/null
+++ b/lib/libc/iconv/iconv.3
@@ -0,0 +1,305 @@
+.\" $FreeBSD$
+.\" $NetBSD: iconv.3,v 1.12 2004/08/02 13:38:21 tshiozak Exp $
+.\"
+.\" Copyright (c) 2003 Citrus Project,
+.\" Copyright (c) 2009, 2010 Gabor Kovesdan <gabor@FreeBSD.org>,
+.\" 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.
+.\"
+.Dd Juny 16, 2010
+.Dt ICONV 3
+.Os
+.Sh NAME
+.Nm iconv_open ,
+.Nm iconv_open_into ,
+.Nm iconv_close ,
+.Nm iconv
+.Nd codeset conversion functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft iconv_t
+.Fn iconv_open "const char *dstname" "const char *srcname"
+.Ft int
+.Fn iconv_open_into "const char *dstname" "const char *srcname" "iconv_allocation_t *ptr"
+.Ft int
+.Fn iconv_close "iconv_t cd"
+.Ft size_t
+.Fn iconv "iconv_t cd" "char ** restrict src" "size_t * restrict srcleft" "char ** restrict dst" "size_t * restrict dstleft"
+.Ft size_t
+.Fn __iconv "iconv_t cd" "const char ** restrict src" "size_t * restrict srcleft" "char ** restrict dst" "size_t * restrict dstleft" "uint32_t flags" "size_t invalids"
+.Sh DESCRIPTION
+The
+.Fn iconv_open
+function opens a converter from the codeset
+.Fa srcname
+to the codeset
+.Fa dstname
+and returns its descriptor.
+The arguments
+.Fa srcname
+and
+.Fa dstname
+accept "" and "char", which refer to the current locale encoding.
+.Pp
+The
+.Fn iconv_open_into
+creates a conversion descriptor on a preallocated space.
+The
+.Ft iconv_allocation_t
+is used as a spaceholder type when allocating such space.
+The
+.Fa dstname
+and
+.Fa srcname
+arguments are the same as in the case of
+.Fn iconv_open .
+The
+.Fa ptr
+argument is a pointer of
+.Ft iconv_allocation_t
+to the preallocated space.
+.Pp
+The
+.Fn iconv_close
+function closes the specified converter
+.Fa cd .
+.Pp
+The
+.Fn iconv
+function converts the string in the buffer
+.Fa *src
+of length
+.Fa *srcleft
+bytes and stores the converted string in the buffer
+.Fa *dst
+of size
+.Fa *dstleft
+bytes.
+After calling
+.Fn iconv ,
+the values pointed to by
+.Fa src ,
+.Fa srcleft ,
+.Fa dst ,
+and
+.Fa dstleft
+are updated as follows:
+.Bl -tag -width 01234567
+.It *src
+Pointer to the byte just after the last character fetched.
+.It *srcleft
+Number of remaining bytes in the source buffer.
+.It *dst
+Pointer to the byte just after the last character stored.
+.It *dstleft
+Number of remainder bytes in the destination buffer.
+.El
+.Pp
+If the string pointed to by
+.Fa *src
+contains a byte sequence which is not a valid character in the source
+codeset, the conversion stops just after the last successful conversion.
+If the output buffer is too small to store the converted
+character, the conversion also stops in the same way.
+In these cases, the values pointed to by
+.Fa src ,
+.Fa srcleft ,
+.Fa dst ,
+and
+.Fa dstleft
+are updated to the state just after the last successful conversion.
+.Pp
+If the string pointed to by
+.Fa *src
+contains a character which is valid under the source codeset but
+can not be converted to the destination codeset,
+the character is replaced by an
+.Dq invalid character
+which depends on the destination codeset, e.g.,
+.Sq \&? ,
+and the conversion is continued.
+.Fn iconv
+returns the number of such
+.Dq invalid conversions .
+.Pp
+There are two special cases of
+.Fn iconv :
+.Bl -tag -width 0123
+.It "src == NULL || *src == NULL"
+If the source and/or destination codesets are stateful,
+.Fn iconv
+places these into their initial state.
+.Pp
+If both
+.Fa dst
+and
+.Fa *dst
+are
+.No non- Ns Dv NULL ,
+.Fn iconv
+stores the shift sequence for the destination switching to the initial state
+in the buffer pointed to by
+.Fa *dst .
+The buffer size is specified by the value pointed to by
+.Fa dstleft
+as above.
+.Fn iconv
+will fail if the buffer is too small to store the shift sequence.
+.Pp
+On the other hand,
+.Fa dst
+or
+.Fa *dst
+may be
+.Dv NULL .
+In this case, the shift sequence for the destination switching
+to the initial state is discarded.
+.Pp
+.El
+The
+.Fn __iconv
+function works just like
+.Fn iconv
+but if
+.Fn iconv
+fails, the invalid character count is lost there.
+This is a not bug rather a limitation of
+.St -p1003.1-2008 ,
+so
+.Fn __iconv
+is provided as an alternative but non-standard interface.
+It also has a flags argument, where currently the following
+flags can be passed:
+.Bl -tag -width 0123
+.It __ICONV_F_HIDE_INVALID
+Skip invalid characters, instead of returning with an error.
+.El
+.Sh RETURN VALUES
+Upon successful completion of
+.Fn iconv_open ,
+it returns a conversion descriptor.
+Otherwise,
+.Fn iconv_open
+returns (iconv_t)\-1 and sets errno to indicate the error.
+.Pp
+Upon successful completion of
+.Fn iconv_open_into ,
+it returns 0.
+Otherwise,
+.Fn iconv_open_into
+returns \-1, and sets errno to indicate the error.
+.Pp
+Upon successful completion of
+.Fn iconv_close ,
+it returns 0.
+Otherwise,
+.Fn iconv_close
+returns \-1 and sets errno to indicate the error.
+.Pp
+Upon successful completion of
+.Fn iconv ,
+it returns the number of
+.Dq invalid
+conversions.
+Otherwise,
+.Fn iconv
+returns (size_t)\-1 and sets errno to indicate the error.
+.Sh ERRORS
+The
+.Fn iconv_open
+function may cause an error in the following cases:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Memory is exhausted.
+.It Bq Er EINVAL
+There is no converter specified by
+.Fa srcname
+and
+.Fa dstname .
+.El
+The
+.Fn iconv_open_into
+function may cause an error in the following cases:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+There is no converter specified by
+.Fa srcname
+and
+.Fa dstname .
+.El
+.Pp
+The
+.Fn iconv_close
+function may cause an error in the following case:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The conversion descriptor specified by
+.Fa cd
+is invalid.
+.El
+.Pp
+The
+.Fn iconv
+function may cause an error in the following cases:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The conversion descriptor specified by
+.Fa cd
+is invalid.
+.It Bq Er EILSEQ
+The string pointed to by
+.Fa *src
+contains a byte sequence which does not describe a valid character of
+the source codeset.
+.It Bq Er E2BIG
+The output buffer pointed to by
+.Fa *dst
+is too small to store the result string.
+.It Bq Er EINVAL
+The string pointed to by
+.Fa *src
+terminates with an incomplete character or shift sequence.
+.El
+.Sh SEE ALSO
+.Xr iconv 1 ,
+.Xr mkcsmapper 1 ,
+.Xr mkesdb 1
+.Sh STANDARDS
+The
+.Fn iconv_open ,
+.Fn iconv_close ,
+and
+.Fn iconv
+functions conform to
+.St -p1003.1-2008 .
+.Pp
+The
+.Fn iconv_open_into
+function is a GNU-specific extension and it is not part of any standard,
+thus its use may break portability.
+The
+.Fn __iconv
+function is an own extension and it is not part of any standard,
+thus its use may break portability.
diff --git a/lib/libc/iconv/iconv.c b/lib/libc/iconv/iconv.c
new file mode 100644
index 0000000..2cd38df
--- /dev/null
+++ b/lib/libc/iconv/iconv.c
@@ -0,0 +1,332 @@
+/* $FreeBSD$ */
+/* $NetBSD: iconv.c,v 1.11 2009/03/03 16:22:33 explorer Exp $ */
+
+/*-
+ * Copyright (c) 2003 Citrus Project,
+ * Copyright (c) 2009, 2010 Gabor Kovesdan <gabor@FreeBSD.org>,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <iconv.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_esdb.h"
+#include "citrus_hash.h"
+#include "citrus_iconv.h"
+
+#ifdef __weak_alias
+__weak_alias(libiconv, _iconv)
+__weak_alias(libiconv_open, _iconv_open)
+__weak_alias(libiconv_open_into, _iconv_open_into)
+__weak_alias(libiconv_close, _iconv_close)
+__weak_alias(libiconvlist, _iconvlist)
+__weak_alias(libiconvctl, _iconvctl)
+__weak_alias(libiconv_set_relocation_prefix, _iconv_set_relocation_prefix)
+__weak_alias(iconv_canonicalize, _iconv_canonicalize)
+#endif
+
+#define ISBADF(_h_) (!(_h_) || (_h_) == (iconv_t)-1)
+
+int _libiconv_version = _LIBICONV_VERSION;
+
+iconv_t _iconv_open(const char *out, const char *in,
+ struct _citrus_iconv *prealloc);
+
+iconv_t
+_iconv_open(const char *out, const char *in, struct _citrus_iconv *prealloc)
+{
+ struct _citrus_iconv *handle;
+ char *out_truncated, *p;
+ int ret;
+
+ handle = prealloc;
+
+ /*
+ * Remove anything following a //, as these are options (like
+ * //ignore, //translate, etc) and we just don't handle them.
+ * This is for compatibilty with software that uses thees
+ * blindly.
+ */
+ out_truncated = strdup(out);
+ if (out_truncated == NULL) {
+ errno = ENOMEM;
+ return ((iconv_t)-1);
+ }
+
+ p = out_truncated;
+ while (*p != 0) {
+ if (p[0] == '/' && p[1] == '/') {
+ *p = '\0';
+ break;
+ }
+ p++;
+ }
+
+ ret = _citrus_iconv_open(&handle, in, out_truncated);
+ free(out_truncated);
+ if (ret) {
+ errno = ret == ENOENT ? EINVAL : ret;
+ return ((iconv_t)-1);
+ }
+
+ handle->cv_shared->ci_discard_ilseq = strcasestr(out, "//IGNORE");
+ handle->cv_shared->ci_hooks = NULL;
+
+ return ((iconv_t)(void *)handle);
+}
+
+iconv_t
+libiconv_open(const char *out, const char *in)
+{
+
+ return (_iconv_open(out, in, NULL));
+}
+
+int
+libiconv_open_into(const char *out, const char *in, iconv_allocation_t *ptr)
+{
+ struct _citrus_iconv *handle;
+
+ handle = (struct _citrus_iconv *)ptr;
+ return ((_iconv_open(out, in, handle) == (iconv_t)-1) ? -1 : 0);
+}
+
+int
+libiconv_close(iconv_t handle)
+{
+
+ if (ISBADF(handle)) {
+ errno = EBADF;
+ return (-1);
+ }
+
+ _citrus_iconv_close((struct _citrus_iconv *)(void *)handle);
+
+ return (0);
+}
+
+size_t
+libiconv(iconv_t handle, char **in, size_t *szin, char **out, size_t *szout)
+{
+ size_t ret;
+ int err;
+
+ if (ISBADF(handle)) {
+ errno = EBADF;
+ return ((size_t)-1);
+ }
+
+ err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle,
+ in, szin, out, szout, 0, &ret);
+ if (err) {
+ errno = err;
+ ret = (size_t)-1;
+ }
+
+ return (ret);
+}
+
+size_t
+__iconv(iconv_t handle, char **in, size_t *szin, char **out,
+ size_t *szout, uint32_t flags, size_t *invalids)
+{
+ size_t ret;
+ int err;
+
+ if (ISBADF(handle)) {
+ errno = EBADF;
+ return ((size_t)-1);
+ }
+
+ err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle,
+ in, szin, out, szout, flags, &ret);
+ if (invalids)
+ *invalids = ret;
+ if (err) {
+ errno = err;
+ ret = (size_t)-1;
+ }
+
+ return (ret);
+}
+
+int
+__iconv_get_list(char ***rlist, size_t *rsz, bool sorted)
+{
+ int ret;
+
+ ret = _citrus_esdb_get_list(rlist, rsz, sorted);
+ if (ret) {
+ errno = ret;
+ return (-1);
+ }
+
+ return (0);
+}
+
+void
+__iconv_free_list(char **list, size_t sz)
+{
+
+ _citrus_esdb_free_list(list, sz);
+}
+
+/*
+ * GNU-compatibile non-standard interfaces.
+ */
+static int
+qsort_helper(const void *first, const void *second)
+{
+ const char * const *s1;
+ const char * const *s2;
+
+ s1 = first;
+ s2 = second;
+ return (strcmp(*s1, *s2));
+}
+
+void
+libiconvlist(int (*do_one) (unsigned int, const char * const *,
+ void *), void *data)
+{
+ char **list, **names;
+ const char * const *np;
+ char *curitem, *curkey, *slashpos;
+ size_t sz;
+ unsigned int i, j;
+
+ i = 0;
+
+ if (__iconv_get_list(&list, &sz, true))
+ list = NULL;
+ qsort((void *)list, sz, sizeof(char *), qsort_helper);
+ while (i < sz) {
+ j = 0;
+ slashpos = strchr(list[i], '/');
+ curkey = (char *)malloc(slashpos - list[i] + 2);
+ names = (char **)malloc(sz * sizeof(char *));
+ if ((curkey == NULL) || (names == NULL)) {
+ __iconv_free_list(list, sz);
+ return;
+ }
+ strlcpy(curkey, list[i], slashpos - list[i] + 1);
+ names[j++] = strdup(curkey);
+ for (; (i < sz) && (memcmp(curkey, list[i], strlen(curkey)) == 0); i++) {
+ slashpos = strchr(list[i], '/');
+ curitem = (char *)malloc(strlen(slashpos) + 1);
+ if (curitem == NULL) {
+ __iconv_free_list(list, sz);
+ return;
+ }
+ strlcpy(curitem, &slashpos[1], strlen(slashpos) + 1);
+ if (strcmp(curkey, curitem) == 0) {
+ continue;
+ }
+ names[j++] = strdup(curitem);
+ }
+ np = (const char * const *)names;
+ do_one(j, np, data);
+ free(names);
+ }
+
+ __iconv_free_list(list, sz);
+}
+
+__inline const char
+*iconv_canonicalize(const char *name)
+{
+
+ return (_citrus_iconv_canonicalize(name));
+}
+
+int
+libiconvctl(iconv_t cd, int request, void *argument)
+{
+ struct _citrus_iconv *cv;
+ struct iconv_hooks *hooks;
+ const char *convname;
+ char src[PATH_MAX], *dst;
+ int *i;
+
+ cv = (struct _citrus_iconv *)(void *)cd;
+ hooks = (struct iconv_hooks *)argument;
+ i = (int *)argument;
+
+ if (ISBADF(cd)) {
+ errno = EBADF;
+ return (-1);
+ }
+
+ switch (request) {
+ case ICONV_TRIVIALP:
+ convname = cv->cv_shared->ci_convname;
+ dst = strchr(convname, '/');
+
+ strlcpy(src, convname, dst - convname + 1);
+ dst++;
+ if ((convname == NULL) || (src == NULL) || (dst == NULL))
+ return (-1);
+ *i = strcmp(src, dst) == 0 ? 1 : 0;
+ return (0);
+ case ICONV_GET_TRANSLITERATE:
+ *i = 1;
+ return (0);
+ case ICONV_SET_TRANSLITERATE:
+ return ((*i == 1) ? 0 : -1);
+ case ICONV_GET_DISCARD_ILSEQ:
+ *i = cv->cv_shared->ci_discard_ilseq ? 1 : 0;
+ return (0);
+ case ICONV_SET_DISCARD_ILSEQ:
+ cv->cv_shared->ci_discard_ilseq = *i;
+ return (0);
+ case ICONV_SET_HOOKS:
+ cv->cv_shared->ci_hooks = hooks;
+ return (0);
+ case ICONV_SET_FALLBACKS:
+ errno = EOPNOTSUPP;
+ return (-1);
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+}
+
+void
+libiconv_set_relocation_prefix(const char *orig_prefix __unused,
+ const char *curr_prefix __unused)
+{
+
+}
diff --git a/lib/libc/iconv/iconv_canonicalize.3 b/lib/libc/iconv/iconv_canonicalize.3
new file mode 100644
index 0000000..3c52ae2
--- /dev/null
+++ b/lib/libc/iconv/iconv_canonicalize.3
@@ -0,0 +1,74 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" 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.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 20, 2009
+.Dt ICONV_CANONICALIZE 3
+.Os
+.Sh NAME
+.Nm iconv_canonicalize
+.Nd resolving character encoding names to canonical form
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft const char *
+.Fn iconv_canonicalize "const char *name"
+.Sh DESCRIPTION
+The
+.Fn iconv_canonicalize
+function resolves the character encoding name specified by the
+.Fa name
+argument to its canonical form.
+.Sh RETURN VALUES
+Upon successful completion
+.Fn iconv_canonicalize ,
+returns the canonical name of the given encoding.
+If the specified name is already a canonical name, the same
+value is returned.
+If the specified name is not an existing character encoding
+name, NULL is returned.
+.Sh SEE ALSO
+.Xr iconv 3
+.Sh STANDARDS
+The
+.Nm
+function is a non-standard extension, which appeared in
+the GNU implementation and was adopted in
+.Fx 9
+for compatibility's sake.
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq gabor@FreeBSD.org .
diff --git a/lib/libc/iconv/iconvctl.3 b/lib/libc/iconv/iconvctl.3
new file mode 100644
index 0000000..29007c1
--- /dev/null
+++ b/lib/libc/iconv/iconvctl.3
@@ -0,0 +1,162 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" 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.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 7, 2009
+.Dt ICONVCTL 3
+.Os
+.Sh NAME
+.Nm iconvctl
+.Nd controlling and diagnostical facility for
+.Xr iconv 3
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft int
+.Fn iconvctl "iconv_t cd" "int request" "void *argument"
+.Sh DESCRIPTION
+The
+.Fn iconvctl
+function can retrieve or set specific conversion
+setting from the
+.Fa cd
+conversion descriptor.
+The
+.Fa request
+parameter specifies the operation to accomplish and
+.Fa argument
+is an operation-specific argument.
+.Pp
+The possible operations are the following:
+.Bl -tag -width -indent
+.It ICONV_TRIVIALP
+In this case
+.Fa argument
+is an
+.Ft int *
+variable, which is set to 1 if the encoding is trivial one, i.e.
+the input and output encodings are the same.
+Otherwise, the variable will be 0.
+.It ICONV_GET_TRANSLITERATE
+Determines if transliteration is enabled.
+The answer is stored in
+.Fa argument ,
+which is of
+.Ft int * .
+It will be set to 1 if this feature is enabled or set to 0 otherwise.
+.It ICONV_SET_TRANSLITERATE
+Enables transliteration if
+.Fa argument ,
+which is of
+.Ft int *
+set to 1 or disables it if
+.Fa argument
+is set to 0.
+.It ICONV_GET_DISCARD_ILSEQ
+Determines if illegal sequences are discarded or not.
+The answer is stored in
+.Fa argument ,
+which is of
+.Ft int * .
+It will be set to 1 if this feature is enabled or set to 0 otherwise.
+.It ICONV_SET_DISCARD_ILSEQ
+Sets whether illegal sequences are discarded or not.
+.Fa argument ,
+which is of
+.Ft int *
+set to 1 or disables it if
+.Fa argument
+is set to 0.
+.It ICONV_SET_HOOKS
+Sets callback functions, which will be called back after successful
+conversions.
+The callback functions are stored in a
+.Ft struct iconv_hooks
+variable, which is passed to
+.Nm
+via
+.Fa argument
+by its address.
+.\" XXX: fallbacks are unimplemented and trying to set them will always
+.\" return EOPNOTSUPP but definitions are provided for source-level
+.\" compatibility.
+.\".It ICONV_SET_FALLBACKS
+.\"Sets callback functions, which will be called back after failed
+.\"conversions.
+.\"The callback functions are stored in a
+.\".Ft struct iconv_fallbacks
+.\"variable, which is passed to
+.\".Nm
+.\"via
+.\".Fa argument
+.\"by its address.
+.Sh RETURN VALUES
+Upon successful completion
+.Fn iconvctl ,
+returns 0.
+Otherwise, \-1 is returned and errno is set to
+specify the kind of error.
+.Sh ERRORS
+The
+.Fn iconvctl
+function may cause an error in the following cases:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Unknown or unimplemented operation.
+.It Bq Er EBADF
+The conversion descriptor specified by
+.Fa cd
+is invalid.
+.Sh SEE ALSO
+.Xr iconv 1 ,
+.Xr iconv 3
+.Sh STANDARDS
+The
+.Nm
+facility is a non-standard extension, which appeared in
+the GNU implementation and was adopted in
+.Fx 9
+for compatibility's sake.
+.Sh BUGS
+Transliteration is enabled in this implementation by default, so it
+is impossible by design to turn it off.
+Accordingly, trying to turn it off will always fail and \-1 will be
+returned.
+Getting the transliteration state will always succeed and indicate
+that it is turned on, though.
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq gabor@FreeBSD.org .
diff --git a/lib/libc/iconv/iconvlist.3 b/lib/libc/iconv/iconvlist.3
new file mode 100644
index 0000000..e3fc43c
--- /dev/null
+++ b/lib/libc/iconv/iconvlist.3
@@ -0,0 +1,93 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" 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.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 20, 2009
+.Dt ICONVLIST 3
+.Os
+.Sh NAME
+.Nm iconvlist
+.Nd retrieving a list of character encodings supported by
+.Xr iconv 3
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft void
+.Fo iconvlist "char ***names" "size_t count" "bool paired"
+.Fa "int \*[lp]*do_one\*[rp]\*[lp]unsigned int *count, const char * const *names, void *arg\*[rp]"
+.Fa "void *arg"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn iconvlist
+function obtains a list of character encodings that are supported by the
+.Xr iconv 3
+call.
+The
+.Fn do_one
+callback function will be called, where the
+.Fa count
+argument will be set to the number of the encoding names found, the
+.Fa names
+argument will be the list of the supported encoding names and the
+.Fa arg
+argument will be the \"outer\"
+.Fa arg
+argument of the
+.Fn iconvlist
+function.
+This argument can be used to interchange custom data between the caller of
+.Fn iconvlist
+and the callback function.
+.Pp
+If an error occurs,
+.Fa names
+will be NULL when calling
+.Fn do_one .
+.Sh SEE ALSO
+.Xr iconv 3 ,
+.Xr __iconv_get_list 3 ,
+.Xr __iconv_free_list 3
+.Sh STANDARDS
+The
+.Nm
+function is a non-standard extension, which appeared in
+the GNU implementation and was adopted in
+.Fx 9
+for compatibility's sake.
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq gabor@FreeBSD.org .
OpenPOWER on IntegriCloud