summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile5
-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
-rw-r--r--lib/libiconv/Makefile25
-rw-r--r--lib/libiconv_modules/BIG5/Makefile7
-rw-r--r--lib/libiconv_modules/BIG5/citrus_big5.c457
-rw-r--r--lib/libiconv_modules/BIG5/citrus_big5.h37
-rw-r--r--lib/libiconv_modules/DECHanyu/Makefile6
-rw-r--r--lib/libiconv_modules/DECHanyu/citrus_dechanyu.c392
-rw-r--r--lib/libiconv_modules/DECHanyu/citrus_dechanyu.h37
-rw-r--r--lib/libiconv_modules/EUC/Makefile7
-rw-r--r--lib/libiconv_modules/EUC/citrus_euc.c385
-rw-r--r--lib/libiconv_modules/EUC/citrus_euc.h37
-rw-r--r--lib/libiconv_modules/EUCTW/Makefile7
-rw-r--r--lib/libiconv_modules/EUCTW/citrus_euctw.c377
-rw-r--r--lib/libiconv_modules/EUCTW/citrus_euctw.h37
-rw-r--r--lib/libiconv_modules/GBK2K/Makefile7
-rw-r--r--lib/libiconv_modules/GBK2K/citrus_gbk2k.c417
-rw-r--r--lib/libiconv_modules/GBK2K/citrus_gbk2k.h37
-rw-r--r--lib/libiconv_modules/HZ/Makefile6
-rw-r--r--lib/libiconv_modules/HZ/citrus_hz.c648
-rw-r--r--lib/libiconv_modules/HZ/citrus_hz.h37
-rw-r--r--lib/libiconv_modules/ISO2022/Makefile7
-rw-r--r--lib/libiconv_modules/ISO2022/citrus_iso2022.c1289
-rw-r--r--lib/libiconv_modules/ISO2022/citrus_iso2022.h37
-rw-r--r--lib/libiconv_modules/JOHAB/Makefile7
-rw-r--r--lib/libiconv_modules/JOHAB/citrus_johab.c333
-rw-r--r--lib/libiconv_modules/JOHAB/citrus_johab.h37
-rw-r--r--lib/libiconv_modules/MSKanji/Makefile6
-rw-r--r--lib/libiconv_modules/MSKanji/citrus_mskanji.c473
-rw-r--r--lib/libiconv_modules/MSKanji/citrus_mskanji.h37
-rw-r--r--lib/libiconv_modules/Makefile9
-rw-r--r--lib/libiconv_modules/Makefile.inc14
-rw-r--r--lib/libiconv_modules/UES/Makefile7
-rw-r--r--lib/libiconv_modules/UES/citrus_ues.c412
-rw-r--r--lib/libiconv_modules/UES/citrus_ues.h37
-rw-r--r--lib/libiconv_modules/UTF1632/Makefile7
-rw-r--r--lib/libiconv_modules/UTF1632/citrus_utf1632.c453
-rw-r--r--lib/libiconv_modules/UTF1632/citrus_utf1632.h37
-rw-r--r--lib/libiconv_modules/UTF7/Makefile7
-rw-r--r--lib/libiconv_modules/UTF7/citrus_utf7.c499
-rw-r--r--lib/libiconv_modules/UTF7/citrus_utf7.h37
-rw-r--r--lib/libiconv_modules/UTF8/Makefile6
-rw-r--r--lib/libiconv_modules/UTF8/citrus_utf8.c349
-rw-r--r--lib/libiconv_modules/UTF8/citrus_utf8.h37
-rw-r--r--lib/libiconv_modules/VIQR/Makefile6
-rw-r--r--lib/libiconv_modules/VIQR/citrus_viqr.c494
-rw-r--r--lib/libiconv_modules/VIQR/citrus_viqr.h37
-rw-r--r--lib/libiconv_modules/ZW/Makefile6
-rw-r--r--lib/libiconv_modules/ZW/citrus_zw.c455
-rw-r--r--lib/libiconv_modules/ZW/citrus_zw.h37
-rw-r--r--lib/libiconv_modules/iconv_none/Makefile6
-rw-r--r--lib/libiconv_modules/iconv_none/citrus_iconv_none.c127
-rw-r--r--lib/libiconv_modules/iconv_none/citrus_iconv_none.h37
-rw-r--r--lib/libiconv_modules/iconv_std/Makefile7
-rw-r--r--lib/libiconv_modules/iconv_std/citrus_iconv_std.c583
-rw-r--r--lib/libiconv_modules/iconv_std/citrus_iconv_std.h37
-rw-r--r--lib/libiconv_modules/iconv_std/citrus_iconv_std_local.h82
-rw-r--r--lib/libiconv_modules/mapper_646/Makefile8
-rw-r--r--lib/libiconv_modules/mapper_646/citrus_mapper_646.c249
-rw-r--r--lib/libiconv_modules/mapper_646/citrus_mapper_646.h37
-rw-r--r--lib/libiconv_modules/mapper_none/Makefile6
-rw-r--r--lib/libiconv_modules/mapper_none/citrus_mapper_none.c104
-rw-r--r--lib/libiconv_modules/mapper_none/citrus_mapper_none.h37
-rw-r--r--lib/libiconv_modules/mapper_parallel/Makefile9
-rw-r--r--lib/libiconv_modules/mapper_serial/Makefile7
-rw-r--r--lib/libiconv_modules/mapper_serial/citrus_mapper_serial.c246
-rw-r--r--lib/libiconv_modules/mapper_serial/citrus_mapper_serial.h38
-rw-r--r--lib/libiconv_modules/mapper_std/Makefile7
-rw-r--r--lib/libiconv_modules/mapper_std/citrus_mapper_std.c435
-rw-r--r--lib/libiconv_modules/mapper_std/citrus_mapper_std.h39
-rw-r--r--lib/libiconv_modules/mapper_std/citrus_mapper_std_file.h76
-rw-r--r--lib/libiconv_modules/mapper_std/citrus_mapper_std_local.h71
-rw-r--r--lib/libiconv_modules/mapper_zone/Makefile7
-rw-r--r--lib/libiconv_modules/mapper_zone/citrus_mapper_zone.c385
-rw-r--r--lib/libiconv_modules/mapper_zone/citrus_mapper_zone.h37
137 files changed, 19595 insertions, 0 deletions
diff --git a/lib/Makefile b/lib/Makefile
index e6e3cf0..4fef1bb 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -37,6 +37,7 @@ SUBDIR_ORDERED= ${_csu} \
libcompiler_rt \
libcrypt \
libelf \
+ ${_libiconv_modules} \
libkvm \
msun \
libmd \
@@ -156,6 +157,10 @@ _libgssapi= libgssapi
_librpcsec_gss= librpcsec_gss
.endif
+.if ${MK_ICONV} != "no"
+_libiconv_modules= libiconv_modules
+.endif
+
.if ${MK_IPX} != "no"
_libipx= libipx
.endif
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 .
diff --git a/lib/libiconv/Makefile b/lib/libiconv/Makefile
new file mode 100644
index 0000000..078771e
--- /dev/null
+++ b/lib/libiconv/Makefile
@@ -0,0 +1,25 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../libc/iconv
+
+LIB= iconv
+SHLIB_MAJOR= 4
+MAN= iconv.3 iconvctl.3 iconv_canonicalize.3 iconvlist.3 \
+ __iconv_get_list.3
+MLNKS= 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
+
+WARNS?= 6
+CFLAGS+= --param max-inline-insns-single=128 -I ${.CURDIR}/../../include -I${.CURDIR}/../libc/include
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/BIG5/Makefile b/lib/libiconv_modules/BIG5/Makefile
new file mode 100644
index 0000000..0f755fc
--- /dev/null
+++ b/lib/libiconv_modules/BIG5/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= BIG5
+SRCS+= citrus_big5.c
+CFLAGS+= --param max-inline-insns-single=32
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/BIG5/citrus_big5.c b/lib/libiconv_modules/BIG5/citrus_big5.c
new file mode 100644
index 0000000..b6ece46
--- /dev/null
+++ b/lib/libiconv_modules/BIG5/citrus_big5.c
@@ -0,0 +1,457 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_big5.c,v 1.12 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2002, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_prop.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_big5.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+ int chlen;
+ char ch[2];
+} _BIG5State;
+
+typedef struct _BIG5Exclude {
+ TAILQ_ENTRY(_BIG5Exclude) entry;
+ wint_t end;
+ wint_t start;
+} _BIG5Exclude;
+
+typedef TAILQ_HEAD(_BIG5ExcludeList, _BIG5Exclude) _BIG5ExcludeList;
+
+typedef struct {
+ _BIG5ExcludeList excludes;
+ int cell[0x100];
+} _BIG5EncodingInfo;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_BIG5_##m
+#define _ENCODING_INFO _BIG5EncodingInfo
+#define _ENCODING_STATE _BIG5State
+#define _ENCODING_MB_CUR_MAX(_ei_) 2
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+
+static __inline void
+/*ARGSUSED*/
+_citrus_BIG5_init_state(_BIG5EncodingInfo * __restrict ei __unused,
+ _BIG5State * __restrict s)
+{
+
+ memset(s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_BIG5_pack_state(_BIG5EncodingInfo * __restrict ei __unused,
+ void * __restrict pspriv,
+ const _BIG5State * __restrict s)
+{
+
+ memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_BIG5_unpack_state(_BIG5EncodingInfo * __restrict ei __unused,
+ _BIG5State * __restrict s,
+ const void * __restrict pspriv)
+{
+
+ memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static __inline int
+_citrus_BIG5_check(_BIG5EncodingInfo *ei, unsigned int c)
+{
+
+ return ((ei->cell[c & 0xFF] & 0x1) ? 2 : 1);
+}
+
+static __inline int
+_citrus_BIG5_check2(_BIG5EncodingInfo *ei, unsigned int c)
+{
+
+ return ((ei->cell[c & 0xFF] & 0x2) ? 1 : 0);
+}
+
+static __inline int
+_citrus_BIG5_check_excludes(_BIG5EncodingInfo *ei, wint_t c)
+{
+ _BIG5Exclude *exclude;
+
+ TAILQ_FOREACH(exclude, &ei->excludes, entry) {
+ if (c >= exclude->start && c <= exclude->end)
+ return (EILSEQ);
+ }
+ return (0);
+}
+
+static int
+_citrus_BIG5_fill_rowcol(void ** __restrict ctx, const char * __restrict s,
+ uint64_t start, uint64_t end)
+{
+ _BIG5EncodingInfo *ei;
+ uint64_t n;
+ int i;
+
+ if (start > 0xFF || end > 0xFF)
+ return (EINVAL);
+ ei = (_BIG5EncodingInfo *)ctx;
+ i = strcmp("row", s) ? 1 : 0;
+ i = 1 << i;
+ for (n = start; n <= end; ++n)
+ ei->cell[n & 0xFF] |= i;
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_BIG5_fill_excludes(void ** __restrict ctx,
+ const char * __restrict s __unused, uint64_t start, uint64_t end)
+{
+ _BIG5EncodingInfo *ei;
+ _BIG5Exclude *exclude;
+
+ if (start > 0xFFFF || end > 0xFFFF)
+ return (EINVAL);
+ ei = (_BIG5EncodingInfo *)ctx;
+ exclude = TAILQ_LAST(&ei->excludes, _BIG5ExcludeList);
+ if (exclude != NULL && (wint_t)start <= exclude->end)
+ return (EINVAL);
+ exclude = (void *)malloc(sizeof(*exclude));
+ if (exclude == NULL)
+ return (ENOMEM);
+ exclude->start = (wint_t)start;
+ exclude->end = (wint_t)end;
+ TAILQ_INSERT_TAIL(&ei->excludes, exclude, entry);
+
+ return (0);
+}
+
+static const _citrus_prop_hint_t root_hints[] = {
+ _CITRUS_PROP_HINT_NUM("row", &_citrus_BIG5_fill_rowcol),
+ _CITRUS_PROP_HINT_NUM("col", &_citrus_BIG5_fill_rowcol),
+ _CITRUS_PROP_HINT_NUM("excludes", &_citrus_BIG5_fill_excludes),
+ _CITRUS_PROP_HINT_END
+};
+
+static void
+/*ARGSUSED*/
+_citrus_BIG5_encoding_module_uninit(_BIG5EncodingInfo *ei)
+{
+ _BIG5Exclude *exclude;
+
+ while ((exclude = TAILQ_FIRST(&ei->excludes)) != NULL) {
+ TAILQ_REMOVE(&ei->excludes, exclude, entry);
+ free(exclude);
+ }
+}
+
+static int
+/*ARGSUSED*/
+_citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar)
+{
+ void *ctx = (void *)ei;
+ const char *s;
+ int err;
+
+ memset((void *)ei, 0, sizeof(*ei));
+ TAILQ_INIT(&ei->excludes);
+
+ if (lenvar > 0 && var != NULL) {
+ s = _bcs_skip_ws_len((const char *)var, &lenvar);
+ if (lenvar > 0 && *s != '\0') {
+ err = _citrus_prop_parse_variable(
+ root_hints, (void *)ei, s, lenvar);
+ if (err == 0)
+ return (0);
+
+ _citrus_BIG5_encoding_module_uninit(ei);
+ memset((void *)ei, 0, sizeof(*ei));
+ TAILQ_INIT(&ei->excludes);
+ }
+ }
+
+ /* fallback Big5-1984, for backward compatibility. */
+ _citrus_BIG5_fill_rowcol((void **)&ctx, "row", 0xA1, 0xFE);
+ _citrus_BIG5_fill_rowcol((void **)&ctx, "col", 0x40, 0x7E);
+ _citrus_BIG5_fill_rowcol((void **)&ctx, "col", 0xA1, 0xFE);
+
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_BIG5_mbrtowc_priv(_BIG5EncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc,
+ char ** __restrict s, size_t n,
+ _BIG5State * __restrict psenc,
+ size_t * __restrict nresult)
+{
+ wchar_t wchar;
+ char *s0;
+ int c, chlenbak;
+
+ s0 = *s;
+
+ if (s0 == NULL) {
+ _citrus_BIG5_init_state(ei, psenc);
+ *nresult = 0;
+ return (0);
+ }
+
+ chlenbak = psenc->chlen;
+
+ /* make sure we have the first byte in the buffer */
+ switch (psenc->chlen) {
+ case 0:
+ if (n < 1)
+ goto restart;
+ psenc->ch[0] = *s0++;
+ psenc->chlen = 1;
+ n--;
+ break;
+ case 1:
+ break;
+ default:
+ /* illegal state */
+ goto ilseq;
+ }
+
+ c = _citrus_BIG5_check(ei, psenc->ch[0] & 0xff);
+ if (c == 0)
+ goto ilseq;
+ while (psenc->chlen < c) {
+ if (n < 1) {
+ goto restart;
+ }
+ psenc->ch[psenc->chlen] = *s0++;
+ psenc->chlen++;
+ n--;
+ }
+
+ switch (c) {
+ case 1:
+ wchar = psenc->ch[0] & 0xff;
+ break;
+ case 2:
+ if (!_citrus_BIG5_check2(ei, psenc->ch[1] & 0xff))
+ goto ilseq;
+ wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
+ break;
+ default:
+ /* illegal state */
+ goto ilseq;
+ }
+
+ if (_citrus_BIG5_check_excludes(ei, (wint_t)wchar) != 0)
+ goto ilseq;
+
+ *s = s0;
+ psenc->chlen = 0;
+ if (pwc)
+ *pwc = wchar;
+ *nresult = wchar ? c - chlenbak : 0;
+
+ return (0);
+
+ilseq:
+ psenc->chlen = 0;
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+
+restart:
+ *s = s0;
+ *nresult = (size_t)-2;
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei,
+ char * __restrict s,
+ size_t n, wchar_t wc, _BIG5State * __restrict psenc __unused,
+ size_t * __restrict nresult)
+{
+ unsigned char l;
+ int ret;
+
+ /* check invalid sequence */
+ if (wc & ~0xffff ||
+ _citrus_BIG5_check_excludes(ei, (wint_t)wc) != 0) {
+ ret = EILSEQ;
+ goto err;
+ }
+
+ if (wc & 0x8000) {
+ if (_citrus_BIG5_check(ei, (wc >> 8) & 0xff) != 2 ||
+ !_citrus_BIG5_check2(ei, wc & 0xff)) {
+ ret = EILSEQ;
+ goto err;
+ }
+ l = 2;
+ } else {
+ if (wc & ~0xff || !_citrus_BIG5_check(ei, wc & 0xff)) {
+ ret = EILSEQ;
+ goto err;
+ }
+ l = 1;
+ }
+
+ if (n < l) {
+ /* bound check failure */
+ ret = E2BIG;
+ goto err;
+ }
+
+ if (l == 2) {
+ s[0] = (wc >> 8) & 0xff;
+ s[1] = wc & 0xff;
+ } else
+ s[0] = wc & 0xff;
+
+ *nresult = l;
+
+ return (0);
+
+err:
+ *nresult = (size_t)-1;
+ return (ret);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_BIG5_stdenc_wctocs(_BIG5EncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid,
+ _index_t * __restrict idx, wchar_t wc)
+{
+
+ *csid = (wc < 0x100) ? 0 : 1;
+ *idx = (_index_t)wc;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_BIG5_stdenc_cstowc(_BIG5EncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc,
+ _csid_t csid, _index_t idx)
+{
+
+ switch (csid) {
+ case 0:
+ case 1:
+ *wc = (wchar_t)idx;
+ break;
+ default:
+ return (EILSEQ);
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_BIG5_stdenc_get_state_desc_generic(_BIG5EncodingInfo * __restrict ei __unused,
+ _BIG5State * __restrict psenc,
+ int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(BIG5);
+_CITRUS_STDENC_DEF_OPS(BIG5);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/BIG5/citrus_big5.h b/lib/libiconv_modules/BIG5/citrus_big5.h
new file mode 100644
index 0000000..e653ac6
--- /dev/null
+++ b/lib/libiconv_modules/BIG5/citrus_big5.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_big5.h,v 1.2 2003/06/25 09:51:41 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_BIG5_H_
+#define _CITRUS_BIG5_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(BIG5);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/DECHanyu/Makefile b/lib/libiconv_modules/DECHanyu/Makefile
new file mode 100644
index 0000000..c14e123
--- /dev/null
+++ b/lib/libiconv_modules/DECHanyu/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SHLIB= DECHanyu
+SRCS+= citrus_dechanyu.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/DECHanyu/citrus_dechanyu.c b/lib/libiconv_modules/DECHanyu/citrus_dechanyu.c
new file mode 100644
index 0000000..0801ac9
--- /dev/null
+++ b/lib/libiconv_modules/DECHanyu/citrus_dechanyu.c
@@ -0,0 +1,392 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_dechanyu.c,v 1.3 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2007 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_dechanyu.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+ size_t chlen;
+ char ch[4];
+} _DECHanyuState;
+
+typedef struct {
+ int dummy;
+} _DECHanyuEncodingInfo;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.__CONCAT(s_,_func_)
+
+#define _FUNCNAME(m) __CONCAT(_citrus_DECHanyu_,m)
+#define _ENCODING_INFO _DECHanyuEncodingInfo
+#define _ENCODING_STATE _DECHanyuState
+#define _ENCODING_MB_CUR_MAX(_ei_) 4
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_DECHanyu_init_state(_DECHanyuEncodingInfo * __restrict ei __unused,
+ _DECHanyuState * __restrict psenc)
+{
+
+ psenc->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_DECHanyu_pack_state(_DECHanyuEncodingInfo * __restrict ei __unused,
+ void * __restrict pspriv, const _DECHanyuState * __restrict psenc)
+{
+
+ memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_DECHanyu_unpack_state(_DECHanyuEncodingInfo * __restrict ei __unused,
+ _DECHanyuState * __restrict psenc,
+ const void * __restrict pspriv)
+{
+
+ memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static void
+/*ARGSUSED*/
+_citrus_DECHanyu_encoding_module_uninit(_DECHanyuEncodingInfo *ei __unused)
+{
+
+ /* ei may be null */
+}
+
+static int
+/*ARGSUSED*/
+_citrus_DECHanyu_encoding_module_init(_DECHanyuEncodingInfo * __restrict ei __unused,
+ const void * __restrict var __unused, size_t lenvar __unused)
+{
+
+ /* ei may be null */
+ return (0);
+}
+
+static __inline bool
+is_singlebyte(int c)
+{
+
+ return (c <= 0x7F);
+}
+
+static __inline bool
+is_leadbyte(int c)
+{
+
+ return (c >= 0xA1 && c <= 0xFE);
+}
+
+static __inline bool
+is_trailbyte(int c)
+{
+
+ c &= ~0x80;
+ return (c >= 0x21 && c <= 0x7E);
+}
+
+static __inline bool
+is_hanyu1(int c)
+{
+
+ return (c == 0xC2);
+}
+
+static __inline bool
+is_hanyu2(int c)
+{
+
+ return (c == 0xCB);
+}
+
+#define HANYUBIT 0xC2CB0000
+
+static __inline bool
+is_94charset(int c)
+{
+
+ return (c >= 0x21 && c <= 0x7E);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_DECHanyu_mbrtowc_priv(_DECHanyuEncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s, size_t n,
+ _DECHanyuState * __restrict psenc, size_t * __restrict nresult)
+{
+ char *s0;
+ wchar_t wc;
+ int ch;
+
+ if (*s == NULL) {
+ _citrus_DECHanyu_init_state(ei, psenc);
+ *nresult = _ENCODING_IS_STATE_DEPENDENT;
+ return (0);
+ }
+ s0 = *s;
+
+ wc = (wchar_t)0;
+ switch (psenc->chlen) {
+ case 0:
+ if (n-- < 1)
+ goto restart;
+ ch = *s0++ & 0xFF;
+ if (is_singlebyte(ch)) {
+ if (pwc != NULL)
+ *pwc = (wchar_t)ch;
+ *nresult = (size_t)((ch == 0) ? 0 : 1);
+ *s = s0;
+ return (0);
+ }
+ if (!is_leadbyte(ch))
+ goto ilseq;
+ psenc->ch[psenc->chlen++] = ch;
+ break;
+ case 1:
+ ch = psenc->ch[0] & 0xFF;
+ if (!is_leadbyte(ch))
+ return (EINVAL);
+ break;
+ case 2: case 3:
+ ch = psenc->ch[0] & 0xFF;
+ if (is_hanyu1(ch)) {
+ ch = psenc->ch[1] & 0xFF;
+ if (is_hanyu2(ch)) {
+ wc |= (wchar_t)HANYUBIT;
+ break;
+ }
+ }
+ /*FALLTHROUGH*/
+ default:
+ return (EINVAL);
+ }
+
+ switch (psenc->chlen) {
+ case 1:
+ if (is_hanyu1(ch)) {
+ if (n-- < 1)
+ goto restart;
+ ch = *s0++ & 0xFF;
+ if (!is_hanyu2(ch))
+ goto ilseq;
+ psenc->ch[psenc->chlen++] = ch;
+ wc |= (wchar_t)HANYUBIT;
+ if (n-- < 1)
+ goto restart;
+ ch = *s0++ & 0xFF;
+ if (!is_leadbyte(ch))
+ goto ilseq;
+ psenc->ch[psenc->chlen++] = ch;
+ }
+ break;
+ case 2:
+ if (n-- < 1)
+ goto restart;
+ ch = *s0++ & 0xFF;
+ if (!is_leadbyte(ch))
+ goto ilseq;
+ psenc->ch[psenc->chlen++] = ch;
+ break;
+ case 3:
+ ch = psenc->ch[2] & 0xFF;
+ if (!is_leadbyte(ch))
+ return (EINVAL);
+ }
+ if (n-- < 1)
+ goto restart;
+ wc |= (wchar_t)(ch << 8);
+ ch = *s0++ & 0xFF;
+ if (!is_trailbyte(ch))
+ goto ilseq;
+ wc |= (wchar_t)ch;
+ if (pwc != NULL)
+ *pwc = wc;
+ *nresult = (size_t)(s0 - *s);
+ *s = s0;
+ psenc->chlen = 0;
+
+ return (0);
+
+restart:
+ *nresult = (size_t)-2;
+ *s = s0;
+ return (0);
+
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_DECHanyu_wcrtomb_priv(_DECHanyuEncodingInfo * __restrict ei __unused,
+ char * __restrict s, size_t n, wchar_t wc,
+ _DECHanyuState * __restrict psenc, size_t * __restrict nresult)
+{
+ int ch;
+
+ if (psenc->chlen != 0)
+ return (EINVAL);
+
+ /* XXX: assume wchar_t as int */
+ if ((uint32_t)wc <= 0x7F) {
+ ch = wc & 0xFF;
+ } else {
+ if ((uint32_t)wc > 0xFFFF) {
+ if ((wc & ~0xFFFF) != (wchar_t)HANYUBIT)
+ goto ilseq;
+ psenc->ch[psenc->chlen++] = (wc >> 24) & 0xFF;
+ psenc->ch[psenc->chlen++] = (wc >> 16) & 0xFF;
+ wc &= 0xFFFF;
+ }
+ ch = (wc >> 8) & 0xFF;
+ if (!is_leadbyte(ch))
+ goto ilseq;
+ psenc->ch[psenc->chlen++] = ch;
+ ch = wc & 0xFF;
+ if (!is_trailbyte(ch))
+ goto ilseq;
+ }
+ psenc->ch[psenc->chlen++] = ch;
+ if (n < psenc->chlen) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ memcpy(s, psenc->ch, psenc->chlen);
+ *nresult = psenc->chlen;
+ psenc->chlen = 0;
+
+ return (0);
+
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_DECHanyu_stdenc_wctocs(_DECHanyuEncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+ wchar_t mask;
+ int plane;
+
+ plane = 0;
+ mask = 0x7F;
+ /* XXX: assume wchar_t as int */
+ if ((uint32_t)wc > 0x7F) {
+ if ((uint32_t)wc > 0xFFFF) {
+ if ((wc & ~0xFFFF) != (wchar_t)HANYUBIT)
+ return (EILSEQ);
+ plane += 2;
+ }
+ if (!is_leadbyte((wc >> 8) & 0xFF) ||
+ !is_trailbyte(wc & 0xFF))
+ return (EILSEQ);
+ plane += (wc & 0x80) ? 1 : 2;
+ mask |= 0x7F00;
+ }
+ *csid = plane;
+ *idx = (_index_t)(wc & mask);
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_DECHanyu_stdenc_cstowc(_DECHanyuEncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ if (csid == 0) {
+ if (idx > 0x7F)
+ return (EILSEQ);
+ } else if (csid <= 4) {
+ if (!is_94charset(idx >> 8))
+ return (EILSEQ);
+ if (!is_94charset(idx & 0xFF))
+ return (EILSEQ);
+ if (csid % 2)
+ idx |= 0x80;
+ idx |= 0x8000;
+ if (csid > 2)
+ idx |= HANYUBIT;
+ } else
+ return (EILSEQ);
+ *wc = (wchar_t)idx;
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_DECHanyu_stdenc_get_state_desc_generic(
+ _DECHanyuEncodingInfo * __restrict ei __unused,
+ _DECHanyuState * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0)
+ ? _STDENC_SDGEN_INITIAL
+ : _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(DECHanyu);
+_CITRUS_STDENC_DEF_OPS(DECHanyu);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/DECHanyu/citrus_dechanyu.h b/lib/libiconv_modules/DECHanyu/citrus_dechanyu.h
new file mode 100644
index 0000000..5f8873c
--- /dev/null
+++ b/lib/libiconv_modules/DECHanyu/citrus_dechanyu.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_dechanyu.h,v 1.1 2007/04/01 18:52:32 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DECHANYU_H_
+#define _CITRUS_DECHANYU_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(DECHanyu);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/EUC/Makefile b/lib/libiconv_modules/EUC/Makefile
new file mode 100644
index 0000000..422aab3
--- /dev/null
+++ b/lib/libiconv_modules/EUC/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= EUC
+SRCS+= citrus_euc.c
+CFLAGS+= --param max-inline-insns-single=32
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/EUC/citrus_euc.c b/lib/libiconv_modules/EUC/citrus_euc.c
new file mode 100644
index 0000000..708473b
--- /dev/null
+++ b/lib/libiconv_modules/EUC/citrus_euc.c
@@ -0,0 +1,385 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_euc.c,v 1.14 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_euc.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+ int chlen;
+ char ch[3];
+} _EUCState;
+
+typedef struct {
+ wchar_t bits[4];
+ wchar_t mask;
+ unsigned count[4];
+ unsigned mb_cur_max;
+} _EUCEncodingInfo;
+
+#define _SS2 0x008e
+#define _SS3 0x008f
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_EUC_##m
+#define _ENCODING_INFO _EUCEncodingInfo
+#define _ENCODING_STATE _EUCState
+#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+
+static __inline int
+_citrus_EUC_cs(unsigned int c)
+{
+
+ c &= 0xff;
+
+ return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
+}
+
+static __inline int
+_citrus_EUC_parse_variable(_EUCEncodingInfo *ei, const void *var,
+ size_t lenvar __unused)
+{
+ char *e;
+ const char *v;
+ int x;
+
+ /* parse variable string */
+ if (!var)
+ return (EFTYPE);
+
+ v = (const char *)var;
+
+ while (*v == ' ' || *v == '\t')
+ ++v;
+
+ ei->mb_cur_max = 1;
+ for (x = 0; x < 4; ++x) {
+ ei->count[x] = (int)_bcs_strtol(v, (char **)&e, 0);
+ if (v == e || !(v = e) || ei->count[x] < 1 || ei->count[x] > 4) {
+ return (EFTYPE);
+ }
+ if (ei->mb_cur_max < ei->count[x])
+ ei->mb_cur_max = ei->count[x];
+ while (*v == ' ' || *v == '\t')
+ ++v;
+ ei->bits[x] = (int)_bcs_strtol(v, (char **)&e, 0);
+ if (v == e || !(v = e)) {
+ return (EFTYPE);
+ }
+ while (*v == ' ' || *v == '\t')
+ ++v;
+ }
+ ei->mask = (int)_bcs_strtol(v, (char **)&e, 0);
+ if (v == e || !(v = e)) {
+ return (EFTYPE);
+ }
+
+ return (0);
+}
+
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUC_init_state(_EUCEncodingInfo *ei __unused, _EUCState *s)
+{
+
+ memset(s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUC_pack_state(_EUCEncodingInfo *ei __unused, void *pspriv,
+ const _EUCState *s)
+{
+
+ memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUC_unpack_state(_EUCEncodingInfo *ei __unused, _EUCState *s,
+ const void *pspriv)
+{
+
+ memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+_citrus_EUC_mbrtowc_priv(_EUCEncodingInfo *ei, wchar_t *pwc, char **s,
+ size_t n, _EUCState *psenc, size_t *nresult)
+{
+ wchar_t wchar;
+ int c, chlenbak, cs, len;
+ char *s0, *s1 = NULL;
+
+ s0 = *s;
+
+ if (s0 == NULL) {
+ _citrus_EUC_init_state(ei, psenc);
+ *nresult = 0; /* state independent */
+ return (0);
+ }
+
+ chlenbak = psenc->chlen;
+
+ /* make sure we have the first byte in the buffer */
+ switch (psenc->chlen) {
+ case 0:
+ if (n < 1)
+ goto restart;
+ psenc->ch[0] = *s0++;
+ psenc->chlen = 1;
+ n--;
+ break;
+ case 1:
+ case 2:
+ break;
+ default:
+ /* illgeal state */
+ goto encoding_error;
+ }
+
+ c = ei->count[cs = _citrus_EUC_cs(psenc->ch[0] & 0xff)];
+ if (c == 0)
+ goto encoding_error;
+ while (psenc->chlen < c) {
+ if (n < 1)
+ goto restart;
+ psenc->ch[psenc->chlen] = *s0++;
+ psenc->chlen++;
+ n--;
+ }
+ *s = s0;
+
+ switch (cs) {
+ case 3:
+ case 2:
+ /* skip SS2/SS3 */
+ len = c - 1;
+ s1 = &psenc->ch[1];
+ break;
+ case 1:
+ case 0:
+ len = c;
+ s1 = &psenc->ch[0];
+ break;
+ default:
+ goto encoding_error;
+ }
+ wchar = 0;
+ while (len-- > 0)
+ wchar = (wchar << 8) | (*s1++ & 0xff);
+ wchar = (wchar & ~ei->mask) | ei->bits[cs];
+
+ psenc->chlen = 0;
+ if (pwc)
+ *pwc = wchar;
+ *nresult = wchar ? (size_t)(c - chlenbak) : 0;
+ return (0);
+
+encoding_error:
+ psenc->chlen = 0;
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+
+restart:
+ *nresult = (size_t)-2;
+ *s = s0;
+ return (0);
+}
+
+static int
+_citrus_EUC_wcrtomb_priv(_EUCEncodingInfo *ei, char *s, size_t n, wchar_t wc,
+ _EUCState *psenc __unused, size_t *nresult)
+{
+ wchar_t m, nm;
+ unsigned int cs;
+ int ret;
+ short i;
+
+ m = wc & ei->mask;
+ nm = wc & ~m;
+
+ for (cs = 0; cs < sizeof(ei->count) / sizeof(ei->count[0]); cs++)
+ if (m == ei->bits[cs])
+ break;
+ /* fallback case - not sure if it is necessary */
+ if (cs == sizeof(ei->count) / sizeof(ei->count[0]))
+ cs = 1;
+
+ i = ei->count[cs];
+ if (n < (unsigned)i) {
+ ret = E2BIG;
+ goto err;
+ }
+ m = (cs) ? 0x80 : 0x00;
+ switch (cs) {
+ case 2:
+ *s++ = _SS2;
+ i--;
+ break;
+ case 3:
+ *s++ = _SS3;
+ i--;
+ break;
+ }
+
+ while (i-- > 0)
+ *s++ = ((nm >> (i << 3)) & 0xff) | m;
+
+ *nresult = (size_t)ei->count[cs];
+ return (0);
+
+err:
+ *nresult = (size_t)-1;
+ return (ret);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUC_stdenc_wctocs(_EUCEncodingInfo * __restrict ei,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+ wchar_t m, nm;
+
+ m = wc & ei->mask;
+ nm = wc & ~m;
+
+ *csid = (_citrus_csid_t)m;
+ *idx = (_citrus_index_t)nm;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUC_stdenc_cstowc(_EUCEncodingInfo * __restrict ei,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ if ((csid & ~ei->mask) != 0 || (idx & ei->mask) != 0)
+ return (EINVAL);
+
+ *wc = (wchar_t)csid | (wchar_t)idx;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUC_stdenc_get_state_desc_generic(_EUCEncodingInfo * __restrict ei __unused,
+ _EUCState * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_EUC_encoding_module_init(_EUCEncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar)
+{
+
+ return (_citrus_EUC_parse_variable(ei, var, lenvar));
+}
+
+static void
+/*ARGSUSED*/
+_citrus_EUC_encoding_module_uninit(_EUCEncodingInfo * __restrict ei __unused)
+{
+
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(EUC);
+_CITRUS_STDENC_DEF_OPS(EUC);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/EUC/citrus_euc.h b/lib/libiconv_modules/EUC/citrus_euc.h
new file mode 100644
index 0000000..e9bab9f
--- /dev/null
+++ b/lib/libiconv_modules/EUC/citrus_euc.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_euc.h,v 1.2 2003/06/25 09:51:42 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_EUC_H_
+#define _CITRUS_EUC_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(EUC);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/EUCTW/Makefile b/lib/libiconv_modules/EUCTW/Makefile
new file mode 100644
index 0000000..b85c035
--- /dev/null
+++ b/lib/libiconv_modules/EUCTW/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= EUCTW
+SRCS+= citrus_euctw.c
+CFLAGS+= --param max-inline-insns-single=32
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/EUCTW/citrus_euctw.c b/lib/libiconv_modules/EUCTW/citrus_euctw.c
new file mode 100644
index 0000000..79aa9fa
--- /dev/null
+++ b/lib/libiconv_modules/EUCTW/citrus_euctw.c
@@ -0,0 +1,377 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_euctw.c,v 1.11 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/euctw.c,v 1.13 2001/06/21 01:51:44 yamt Exp $
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.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_stdenc.h"
+#include "citrus_euctw.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+ int chlen;
+ char ch[4];
+} _EUCTWState;
+
+typedef struct {
+ int dummy;
+} _EUCTWEncodingInfo;
+
+#define _SS2 0x008e
+#define _SS3 0x008f
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_EUCTW_##m
+#define _ENCODING_INFO _EUCTWEncodingInfo
+#define _ENCODING_STATE _EUCTWState
+#define _ENCODING_MB_CUR_MAX(_ei_) 4
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+static __inline int
+_citrus_EUCTW_cs(unsigned int c)
+{
+
+ c &= 0xff;
+
+ return ((c & 0x80) ? (c == _SS2 ? 2 : 1) : 0);
+}
+
+static __inline int
+_citrus_EUCTW_count(int cs)
+{
+
+ switch (cs) {
+ case 0:
+ /*FALLTHROUGH*/
+ case 1:
+ /*FALLTHROUGH*/
+ case 2:
+ return (2^cs);
+ case 3:
+ abort();
+ /*NOTREACHED*/
+ }
+ return (0);
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUCTW_init_state(_EUCTWEncodingInfo * __restrict ei __unused,
+ _EUCTWState * __restrict s)
+{
+
+ memset(s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUCTW_pack_state(_EUCTWEncodingInfo * __restrict ei __unused,
+ void * __restrict pspriv, const _EUCTWState * __restrict s)
+{
+
+ memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_EUCTW_unpack_state(_EUCTWEncodingInfo * __restrict ei __unused,
+ _EUCTWState * __restrict s, const void * __restrict pspriv)
+{
+
+ memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_EUCTW_encoding_module_init(_EUCTWEncodingInfo * __restrict ei,
+ const void * __restrict var __unused, size_t lenvar __unused)
+{
+
+ memset((void *)ei, 0, sizeof(*ei));
+
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_EUCTW_encoding_module_uninit(_EUCTWEncodingInfo *ei __unused)
+{
+
+}
+
+static int
+_citrus_EUCTW_mbrtowc_priv(_EUCTWEncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s,
+ size_t n, _EUCTWState * __restrict psenc, size_t * __restrict nresult)
+{
+ char *s0;
+ wchar_t wchar;
+ int c, chlenbak, cs;
+
+ s0 = *s;
+
+ if (s0 == NULL) {
+ _citrus_EUCTW_init_state(ei, psenc);
+ *nresult = 0; /* state independent */
+ return (0);
+ }
+
+ chlenbak = psenc->chlen;
+
+ /* make sure we have the first byte in the buffer */
+ switch (psenc->chlen) {
+ case 0:
+ if (n < 1)
+ goto restart;
+ psenc->ch[0] = *s0++;
+ psenc->chlen = 1;
+ n--;
+ break;
+ case 1:
+ case 2:
+ break;
+ default:
+ /* illgeal state */
+ goto ilseq;
+ }
+
+ c = _citrus_EUCTW_count(cs = _citrus_EUCTW_cs(psenc->ch[0] & 0xff));
+ if (c == 0)
+ goto ilseq;
+ while (psenc->chlen < c) {
+ if (n < 1)
+ goto ilseq;
+ psenc->ch[psenc->chlen] = *s0++;
+ psenc->chlen++;
+ n--;
+ }
+
+ wchar = 0;
+ switch (cs) {
+ case 0:
+ if (psenc->ch[0] & 0x80)
+ goto ilseq;
+ wchar = psenc->ch[0] & 0xff;
+ break;
+ case 1:
+ if (!(psenc->ch[0] & 0x80) || !(psenc->ch[1] & 0x80))
+ goto ilseq;
+ wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
+ wchar |= 'G' << 24;
+ break;
+ case 2:
+ if ((unsigned char)psenc->ch[1] < 0xa1 ||
+ 0xa7 < (unsigned char)psenc->ch[1])
+ goto ilseq;
+ if (!(psenc->ch[2] & 0x80) || !(psenc->ch[3] & 0x80))
+ goto ilseq;
+ wchar = ((psenc->ch[2] & 0xff) << 8) | (psenc->ch[3] & 0xff);
+ wchar |= ('G' + psenc->ch[1] - 0xa1) << 24;
+ break;
+ default:
+ goto ilseq;
+ }
+
+ *s = s0;
+ psenc->chlen = 0;
+
+ if (pwc)
+ *pwc = wchar;
+ *nresult = wchar ? c - chlenbak : 0;
+ return (0);
+
+ilseq:
+ psenc->chlen = 0;
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+
+restart:
+ *s = s0;
+ *nresult = (size_t)-1;
+ return (0);
+}
+
+static int
+_citrus_EUCTW_wcrtomb_priv(_EUCTWEncodingInfo * __restrict ei __unused,
+ char * __restrict s, size_t n, wchar_t wc,
+ _EUCTWState * __restrict psenc __unused, size_t * __restrict nresult)
+{
+ wchar_t cs, v;
+ int clen, i, ret;
+ size_t len;
+
+ cs = wc & 0x7f000080;
+ clen = 1;
+ if (wc & 0x00007f00)
+ clen = 2;
+ if ((wc & 0x007f0000) && !(wc & 0x00800000))
+ clen = 3;
+
+ if (clen == 1 && cs == 0x00000000) {
+ /* ASCII */
+ len = 1;
+ if (n < len) {
+ ret = E2BIG;
+ goto err;
+ }
+ v = wc & 0x0000007f;
+ } else if (clen == 2 && cs == ('G' << 24)) {
+ /* CNS-11643-1 */
+ len = 2;
+ if (n < len) {
+ ret = E2BIG;
+ goto err;
+ }
+ v = wc & 0x00007f7f;
+ v |= 0x00008080;
+ } else if (clen == 2 && 'H' <= (cs >> 24) && (cs >> 24) <= 'M') {
+ /* CNS-11643-[2-7] */
+ len = 4;
+ if (n < len) {
+ ret = E2BIG;
+ goto err;
+ }
+ *s++ = _SS2;
+ *s++ = (cs >> 24) - 'H' + 0xa2;
+ v = wc & 0x00007f7f;
+ v |= 0x00008080;
+ } else {
+ ret = EILSEQ;
+ goto err;
+ }
+
+ i = clen;
+ while (i-- > 0)
+ *s++ = (v >> (i << 3)) & 0xff;
+
+ *nresult = len;
+ return (0);
+
+err:
+ *nresult = (size_t)-1;
+ return (ret);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUCTW_stdenc_wctocs(_EUCTWEncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+
+ *csid = (_csid_t)(wc >> 24) & 0xFF;
+ *idx = (_index_t)(wc & 0x7F7F);
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUCTW_stdenc_cstowc(_EUCTWEncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ if (csid == 0) {
+ if ((idx & ~0x7F) != 0)
+ return (EINVAL);
+ *wc = (wchar_t)idx;
+ } else {
+ if (csid < 'G' || csid > 'M' || (idx & ~0x7F7F) != 0)
+ return (EINVAL);
+ *wc = (wchar_t)idx | ((wchar_t)csid << 24);
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_EUCTW_stdenc_get_state_desc_generic(_EUCTWEncodingInfo * __restrict ei __unused,
+ _EUCTWState * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(EUCTW);
+_CITRUS_STDENC_DEF_OPS(EUCTW);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/EUCTW/citrus_euctw.h b/lib/libiconv_modules/EUCTW/citrus_euctw.h
new file mode 100644
index 0000000..5dde342
--- /dev/null
+++ b/lib/libiconv_modules/EUCTW/citrus_euctw.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_euctw.h,v 1.2 2003/06/25 09:51:42 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_EUCTW_H_
+#define _CITRUS_EUCTW_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(EUCTW);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/GBK2K/Makefile b/lib/libiconv_modules/GBK2K/Makefile
new file mode 100644
index 0000000..28dc796
--- /dev/null
+++ b/lib/libiconv_modules/GBK2K/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= GBK2K
+SRCS+= citrus_gbk2k.c
+CFLAGS+= --param max-inline-insns-single=16
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/GBK2K/citrus_gbk2k.c b/lib/libiconv_modules/GBK2K/citrus_gbk2k.c
new file mode 100644
index 0000000..ff31725
--- /dev/null
+++ b/lib/libiconv_modules/GBK2K/citrus_gbk2k.c
@@ -0,0 +1,417 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_gbk2k.c,v 1.7 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.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_bcs.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_gbk2k.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct _GBK2KState {
+ int chlen;
+ char ch[4];
+} _GBK2KState;
+
+typedef struct {
+ int mb_cur_max;
+} _GBK2KEncodingInfo;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_GBK2K_##m
+#define _ENCODING_INFO _GBK2KEncodingInfo
+#define _ENCODING_STATE _GBK2KState
+#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_GBK2K_init_state(_GBK2KEncodingInfo * __restrict ei __unused,
+ _GBK2KState * __restrict s)
+{
+
+ memset(s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_GBK2K_pack_state(_GBK2KEncodingInfo * __restrict ei __unused,
+ void * __restrict pspriv, const _GBK2KState * __restrict s)
+{
+
+ memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_GBK2K_unpack_state(_GBK2KEncodingInfo * __restrict ei __unused,
+ _GBK2KState * __restrict s, const void * __restrict pspriv)
+{
+
+ memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static __inline bool
+_mb_singlebyte(int c)
+{
+
+ return ((c & 0xff) <= 0x7f);
+}
+
+static __inline bool
+_mb_leadbyte(int c)
+{
+
+ c &= 0xff;
+ return (0x81 <= c && c <= 0xfe);
+}
+
+static __inline bool
+_mb_trailbyte(int c)
+{
+
+ c &= 0xff;
+ return ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfe));
+}
+
+static __inline bool
+_mb_surrogate(int c)
+{
+
+ c &= 0xff;
+ return (0x30 <= c && c <= 0x39);
+}
+
+static __inline int
+_mb_count(wchar_t v)
+{
+ uint32_t c;
+
+ c = (uint32_t)v; /* XXX */
+ if (!(c & 0xffffff00))
+ return (1);
+ if (!(c & 0xffff0000))
+ return (2);
+ return (4);
+}
+
+#define _PSENC (psenc->ch[psenc->chlen - 1])
+#define _PUSH_PSENC(c) (psenc->ch[psenc->chlen++] = (c))
+
+static int
+_citrus_GBK2K_mbrtowc_priv(_GBK2KEncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s, size_t n,
+ _GBK2KState * __restrict psenc, size_t * __restrict nresult)
+{
+ char *s0, *s1;
+ wchar_t wc;
+ int chlenbak, len;
+
+ s0 = *s;
+
+ if (s0 == NULL) {
+ /* _citrus_GBK2K_init_state(ei, psenc); */
+ psenc->chlen = 0;
+ *nresult = 0;
+ return (0);
+ }
+
+ chlenbak = psenc->chlen;
+
+ switch (psenc->chlen) {
+ case 3:
+ if (!_mb_leadbyte (_PSENC))
+ goto invalid;
+ /* FALLTHROUGH */
+ case 2:
+ if (!_mb_surrogate(_PSENC) || _mb_trailbyte(_PSENC))
+ goto invalid;
+ /* FALLTHROUGH */
+ case 1:
+ if (!_mb_leadbyte (_PSENC))
+ goto invalid;
+ /* FALLTHOROUGH */
+ case 0:
+ break;
+ default:
+ goto invalid;
+ }
+
+ for (;;) {
+ if (n-- < 1)
+ goto restart;
+
+ _PUSH_PSENC(*s0++);
+
+ switch (psenc->chlen) {
+ case 1:
+ if (_mb_singlebyte(_PSENC))
+ goto convert;
+ if (_mb_leadbyte (_PSENC))
+ continue;
+ goto ilseq;
+ case 2:
+ if (_mb_trailbyte (_PSENC))
+ goto convert;
+ if (ei->mb_cur_max == 4 &&
+ _mb_surrogate (_PSENC))
+ continue;
+ goto ilseq;
+ case 3:
+ if (_mb_leadbyte (_PSENC))
+ continue;
+ goto ilseq;
+ case 4:
+ if (_mb_surrogate (_PSENC))
+ goto convert;
+ goto ilseq;
+ }
+ }
+
+convert:
+ len = psenc->chlen;
+ s1 = &psenc->ch[0];
+ wc = 0;
+ while (len-- > 0)
+ wc = (wc << 8) | (*s1++ & 0xff);
+
+ if (pwc != NULL)
+ *pwc = wc;
+ *s = s0;
+ *nresult = (wc == 0) ? 0 : psenc->chlen - chlenbak;
+ /* _citrus_GBK2K_init_state(ei, psenc); */
+ psenc->chlen = 0;
+
+ return (0);
+
+restart:
+ *s = s0;
+ *nresult = (size_t)-2;
+
+ return (0);
+
+invalid:
+ return (EINVAL);
+
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+}
+
+static int
+_citrus_GBK2K_wcrtomb_priv(_GBK2KEncodingInfo * __restrict ei,
+ char * __restrict s, size_t n, wchar_t wc, _GBK2KState * __restrict psenc,
+ size_t * __restrict nresult)
+{
+ size_t len;
+ int ret;
+
+ if (psenc->chlen != 0) {
+ ret = EINVAL;
+ goto err;
+ }
+
+ len = _mb_count(wc);
+ if (n < len) {
+ ret = E2BIG;
+ goto err;
+ }
+
+ switch (len) {
+ case 1:
+ if (!_mb_singlebyte(_PUSH_PSENC(wc ))) {
+ ret = EILSEQ;
+ goto err;
+ }
+ break;
+ case 2:
+ if (!_mb_leadbyte (_PUSH_PSENC(wc >> 8)) ||
+ !_mb_trailbyte (_PUSH_PSENC(wc))) {
+ ret = EILSEQ;
+ goto err;
+ }
+ break;
+ case 4:
+ if (ei->mb_cur_max != 4 ||
+ !_mb_leadbyte (_PUSH_PSENC(wc >> 24)) ||
+ !_mb_surrogate (_PUSH_PSENC(wc >> 16)) ||
+ !_mb_leadbyte (_PUSH_PSENC(wc >> 8)) ||
+ !_mb_surrogate (_PUSH_PSENC(wc))) {
+ ret = EILSEQ;
+ goto err;
+ }
+ break;
+ }
+
+ memcpy(s, psenc->ch, psenc->chlen);
+ *nresult = psenc->chlen;
+ /* _citrus_GBK2K_init_state(ei, psenc); */
+ psenc->chlen = 0;
+
+ return (0);
+
+err:
+ *nresult = (size_t)-1;
+ return (ret);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_GBK2K_stdenc_wctocs(_GBK2KEncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+ uint8_t ch, cl;
+
+ if ((uint32_t)wc < 0x80) {
+ /* ISO646 */
+ *csid = 0;
+ *idx = (_index_t)wc;
+ } else if ((uint32_t)wc >= 0x10000) {
+ /* GBKUCS : XXX */
+ *csid = 3;
+ *idx = (_index_t)wc;
+ } else {
+ ch = (uint8_t)(wc >> 8);
+ cl = (uint8_t)wc;
+ if (ch >= 0xA1 && cl >= 0xA1) {
+ /* EUC G1 */
+ *csid = 1;
+ *idx = (_index_t)wc & 0x7F7FU;
+ } else {
+ /* extended area (0x8140-) */
+ *csid = 2;
+ *idx = (_index_t)wc;
+ }
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_GBK2K_stdenc_cstowc(_GBK2KEncodingInfo * __restrict ei,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ switch (csid) {
+ case 0:
+ /* ISO646 */
+ *wc = (wchar_t)idx;
+ break;
+ case 1:
+ /* EUC G1 */
+ *wc = (wchar_t)idx | 0x8080U;
+ break;
+ case 2:
+ /* extended area */
+ *wc = (wchar_t)idx;
+ break;
+ case 3:
+ /* GBKUCS : XXX */
+ if (ei->mb_cur_max != 4)
+ return (EINVAL);
+ *wc = (wchar_t)idx;
+ break;
+ default:
+ return (EILSEQ);
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_GBK2K_stdenc_get_state_desc_generic(_GBK2KEncodingInfo * __restrict ei __unused,
+ _GBK2KState * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_GBK2K_encoding_module_init(_GBK2KEncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar)
+{
+ const char *p;
+
+ p = var;
+ memset((void *)ei, 0, sizeof(*ei));
+ ei->mb_cur_max = 4;
+ while (lenvar > 0) {
+ switch (_bcs_tolower(*p)) {
+ case '2':
+ MATCH("2byte", ei->mb_cur_max = 2);
+ break;
+ }
+ p++;
+ lenvar--;
+ }
+
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_GBK2K_encoding_module_uninit(_GBK2KEncodingInfo *ei __unused)
+{
+
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(GBK2K);
+_CITRUS_STDENC_DEF_OPS(GBK2K);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/GBK2K/citrus_gbk2k.h b/lib/libiconv_modules/GBK2K/citrus_gbk2k.h
new file mode 100644
index 0000000..174a19e
--- /dev/null
+++ b/lib/libiconv_modules/GBK2K/citrus_gbk2k.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_gbk2k.h,v 1.2 2003/06/25 09:51:43 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_GBK2K_H_
+#define _CITRUS_GBK2K_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(GBK2K);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/HZ/Makefile b/lib/libiconv_modules/HZ/Makefile
new file mode 100644
index 0000000..a501187
--- /dev/null
+++ b/lib/libiconv_modules/HZ/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SHLIB= HZ
+SRCS+= citrus_hz.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/HZ/citrus_hz.c b/lib/libiconv_modules/HZ/citrus_hz.c
new file mode 100644
index 0000000..3775ea6
--- /dev/null
+++ b/lib/libiconv_modules/HZ/citrus_hz.c
@@ -0,0 +1,648 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_hz.c,v 1.2 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+
+#include "citrus_hz.h"
+#include "citrus_prop.h"
+
+/*
+ * wchar_t mapping:
+ *
+ * CTRL/ASCII 00000000 00000000 00000000 gxxxxxxx
+ * GB2312 00000000 00000000 0xxxxxxx gxxxxxxx
+ * 94/96*n (~M) 0mmmmmmm 0xxxxxxx 0xxxxxxx gxxxxxxx
+ */
+
+#define ESCAPE_CHAR '~'
+
+typedef enum {
+ CTRL = 0, ASCII = 1, GB2312 = 2, CS94 = 3, CS96 = 4
+} charset_t;
+
+typedef struct {
+ int end;
+ int start;
+ int width;
+} range_t;
+
+static const range_t ranges[] = {
+#define RANGE(start, end) { start, end, (end - start) + 1 }
+/* CTRL */ RANGE(0x00, 0x1F),
+/* ASCII */ RANGE(0x20, 0x7F),
+/* GB2312 */ RANGE(0x21, 0x7E),
+/* CS94 */ RANGE(0x21, 0x7E),
+/* CS96 */ RANGE(0x20, 0x7F),
+#undef RANGE
+};
+
+typedef struct escape_t escape_t;
+typedef struct {
+ charset_t charset;
+ escape_t *escape;
+ ssize_t length;
+#define ROWCOL_MAX 3
+} graphic_t;
+
+typedef TAILQ_HEAD(escape_list, escape_t) escape_list;
+struct escape_t {
+ TAILQ_ENTRY(escape_t) entry;
+ escape_list *set;
+ graphic_t *left;
+ graphic_t *right;
+ int ch;
+};
+
+#define GL(escape) ((escape)->left)
+#define GR(escape) ((escape)->right)
+#define SET(escape) ((escape)->set)
+#define ESC(escape) ((escape)->ch)
+#define INIT(escape) (TAILQ_FIRST(SET(escape)))
+
+static __inline escape_t *
+find_escape(escape_list *set, int ch)
+{
+ escape_t *escape;
+
+ TAILQ_FOREACH(escape, set, entry) {
+ if (ESC(escape) == ch)
+ break;
+ }
+
+ return (escape);
+}
+
+typedef struct {
+ escape_list e0;
+ escape_list e1;
+ graphic_t *ascii;
+ graphic_t *gb2312;
+} _HZEncodingInfo;
+
+#define E0SET(ei) (&(ei)->e0)
+#define E1SET(ei) (&(ei)->e1)
+#define INIT0(ei) (TAILQ_FIRST(E0SET(ei)))
+#define INIT1(ei) (TAILQ_FIRST(E1SET(ei)))
+
+typedef struct {
+ escape_t *inuse;
+ int chlen;
+ char ch[ROWCOL_MAX];
+} _HZState;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_HZ_##m
+#define _ENCODING_INFO _HZEncodingInfo
+#define _ENCODING_STATE _HZState
+#define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
+#define _ENCODING_IS_STATE_DEPENDENT 1
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->inuse == NULL)
+
+static __inline void
+_citrus_HZ_init_state(_HZEncodingInfo * __restrict ei,
+ _HZState * __restrict psenc)
+{
+
+ psenc->chlen = 0;
+ psenc->inuse = INIT0(ei);
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_HZ_pack_state(_HZEncodingInfo * __restrict ei __unused,
+ void *__restrict pspriv, const _HZState * __restrict psenc)
+{
+
+ memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_HZ_unpack_state(_HZEncodingInfo * __restrict ei __unused,
+ _HZState * __restrict psenc, const void * __restrict pspriv)
+{
+
+ memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static int
+_citrus_HZ_mbrtowc_priv(_HZEncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s, size_t n,
+ _HZState * __restrict psenc, size_t * __restrict nresult)
+{
+ escape_t *candidate, *init;
+ graphic_t *graphic;
+ const range_t *range;
+ char *s0;
+ wchar_t wc;
+ int bit, ch, head, len, tail;
+
+ if (*s == NULL) {
+ _citrus_HZ_init_state(ei, psenc);
+ *nresult = 1;
+ return (0);
+ }
+ s0 = *s;
+ if (psenc->chlen < 0 || psenc->inuse == NULL)
+ return (EINVAL);
+
+ wc = (wchar_t)0;
+ bit = head = tail = 0;
+ graphic = NULL;
+ for (len = 0; len <= MB_LEN_MAX;) {
+ if (psenc->chlen == tail) {
+ if (n-- < 1) {
+ *s = s0;
+ *nresult = (size_t)-2;
+ return (0);
+ }
+ psenc->ch[psenc->chlen++] = *s0++;
+ ++len;
+ }
+ ch = (unsigned char)psenc->ch[tail++];
+ if (tail == 1) {
+ if ((ch & ~0x80) <= 0x1F) {
+ if (psenc->inuse != INIT0(ei))
+ break;
+ wc = (wchar_t)ch;
+ goto done;
+ }
+ if (ch & 0x80) {
+ graphic = GR(psenc->inuse);
+ bit = 0x80;
+ ch &= ~0x80;
+ } else {
+ graphic = GL(psenc->inuse);
+ if (ch == ESCAPE_CHAR)
+ continue;
+ bit = 0x0;
+ }
+ if (graphic == NULL)
+ break;
+ } else if (tail == 2 && psenc->ch[0] == ESCAPE_CHAR) {
+ if (tail < psenc->chlen)
+ return (EINVAL);
+ if (ch == ESCAPE_CHAR) {
+ ++head;
+ } else if (ch == '\n') {
+ if (psenc->inuse != INIT0(ei))
+ break;
+ tail = psenc->chlen = 0;
+ continue;
+ } else {
+ candidate = NULL;
+ init = INIT0(ei);
+ if (psenc->inuse == init) {
+ init = INIT1(ei);
+ } else if (INIT(psenc->inuse) == init) {
+ if (ESC(init) != ch)
+ break;
+ candidate = init;
+ }
+ if (candidate == NULL) {
+ candidate = find_escape(
+ SET(psenc->inuse), ch);
+ if (candidate == NULL) {
+ if (init == NULL ||
+ ESC(init) != ch)
+ break;
+ candidate = init;
+ }
+ }
+ psenc->inuse = candidate;
+ tail = psenc->chlen = 0;
+ continue;
+ }
+ } else if (ch & 0x80) {
+ if (graphic != GR(psenc->inuse))
+ break;
+ ch &= ~0x80;
+ } else {
+ if (graphic != GL(psenc->inuse))
+ break;
+ }
+ range = &ranges[(size_t)graphic->charset];
+ if (range->start > ch || range->end < ch)
+ break;
+ wc <<= 8;
+ wc |= ch;
+ if (graphic->length == (tail - head)) {
+ if (graphic->charset > GB2312)
+ bit |= ESC(psenc->inuse) << 24;
+ wc |= bit;
+ goto done;
+ }
+ }
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+done:
+ if (tail < psenc->chlen)
+ return (EINVAL);
+ *s = s0;
+ if (pwc != NULL)
+ *pwc = wc;
+ psenc->chlen = 0;
+ *nresult = (wc == 0) ? 0 : len;
+
+ return (0);
+}
+
+static int
+_citrus_HZ_wcrtomb_priv(_HZEncodingInfo * __restrict ei,
+ char * __restrict s, size_t n, wchar_t wc,
+ _HZState * __restrict psenc, size_t * __restrict nresult)
+{
+ escape_t *candidate, *init;
+ graphic_t *graphic;
+ const range_t *range;
+ size_t len;
+ int bit, ch;
+
+ if (psenc->chlen != 0 || psenc->inuse == NULL)
+ return (EINVAL);
+ if (wc & 0x80) {
+ bit = 0x80;
+ wc &= ~0x80;
+ } else {
+ bit = 0x0;
+ }
+ if ((uint32_t)wc <= 0x1F) {
+ candidate = INIT0(ei);
+ graphic = (bit == 0) ? candidate->left : candidate->right;
+ if (graphic == NULL)
+ goto ilseq;
+ range = &ranges[(size_t)CTRL];
+ len = 1;
+ } else if ((uint32_t)wc <= 0x7F) {
+ graphic = ei->ascii;
+ if (graphic == NULL)
+ goto ilseq;
+ candidate = graphic->escape;
+ range = &ranges[(size_t)graphic->charset];
+ len = graphic->length;
+ } else if ((uint32_t)wc <= 0x7F7F) {
+ graphic = ei->gb2312;
+ if (graphic == NULL)
+ goto ilseq;
+ candidate = graphic->escape;
+ range = &ranges[(size_t)graphic->charset];
+ len = graphic->length;
+ } else {
+ ch = (wc >> 24) & 0xFF;
+ candidate = find_escape(E0SET(ei), ch);
+ if (candidate == NULL) {
+ candidate = find_escape(E1SET(ei), ch);
+ if (candidate == NULL)
+ goto ilseq;
+ }
+ wc &= ~0xFF000000;
+ graphic = (bit == 0) ? candidate->left : candidate->right;
+ if (graphic == NULL)
+ goto ilseq;
+ range = &ranges[(size_t)graphic->charset];
+ len = graphic->length;
+ }
+ if (psenc->inuse != candidate) {
+ init = INIT0(ei);
+ if (SET(psenc->inuse) == SET(candidate)) {
+ if (INIT(psenc->inuse) != init ||
+ psenc->inuse == init || candidate == init)
+ init = NULL;
+ } else if (candidate == (init = INIT(candidate))) {
+ init = NULL;
+ }
+ if (init != NULL) {
+ if (n < 2)
+ return (E2BIG);
+ n -= 2;
+ psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
+ psenc->ch[psenc->chlen++] = ESC(init);
+ }
+ if (n < 2)
+ return (E2BIG);
+ n -= 2;
+ psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
+ psenc->ch[psenc->chlen++] = ESC(candidate);
+ psenc->inuse = candidate;
+ }
+ if (n < len)
+ return (E2BIG);
+ while (len-- > 0) {
+ ch = (wc >> (len * 8)) & 0xFF;
+ if (range->start > ch || range->end < ch)
+ goto ilseq;
+ psenc->ch[psenc->chlen++] = ch | bit;
+ }
+ memcpy(s, psenc->ch, psenc->chlen);
+ *nresult = psenc->chlen;
+ psenc->chlen = 0;
+
+ return (0);
+
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+}
+
+static __inline int
+_citrus_HZ_put_state_reset(_HZEncodingInfo * __restrict ei,
+ char * __restrict s, size_t n, _HZState * __restrict psenc,
+ size_t * __restrict nresult)
+{
+ escape_t *candidate;
+
+ if (psenc->chlen != 0 || psenc->inuse == NULL)
+ return (EINVAL);
+ candidate = INIT0(ei);
+ if (psenc->inuse != candidate) {
+ if (n < 2)
+ return (E2BIG);
+ n -= 2;
+ psenc->ch[psenc->chlen++] = ESCAPE_CHAR;
+ psenc->ch[psenc->chlen++] = ESC(candidate);
+ }
+ if (n < 1)
+ return (E2BIG);
+ if (psenc->chlen > 0)
+ memcpy(s, psenc->ch, psenc->chlen);
+ *nresult = psenc->chlen;
+ _citrus_HZ_init_state(ei, psenc);
+
+ return (0);
+}
+
+static __inline int
+_citrus_HZ_stdenc_get_state_desc_generic(_HZEncodingInfo * __restrict ei,
+ _HZState * __restrict psenc, int * __restrict rstate)
+{
+
+ if (psenc->chlen < 0 || psenc->inuse == NULL)
+ return (EINVAL);
+ *rstate = (psenc->chlen == 0)
+ ? ((psenc->inuse == INIT0(ei))
+ ? _STDENC_SDGEN_INITIAL
+ : _STDENC_SDGEN_STABLE)
+ : ((psenc->ch[0] == ESCAPE_CHAR)
+ ? _STDENC_SDGEN_INCOMPLETE_SHIFT
+ : _STDENC_SDGEN_INCOMPLETE_CHAR);
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_HZ_stdenc_wctocs(_HZEncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+ int bit;
+
+ if (wc & 0x80) {
+ bit = 0x80;
+ wc &= ~0x80;
+ } else
+ bit = 0x0;
+ if ((uint32_t)wc <= 0x7F) {
+ *csid = (_csid_t)bit;
+ *idx = (_index_t)wc;
+ } else if ((uint32_t)wc <= 0x7F7F) {
+ *csid = (_csid_t)(bit | 0x8000);
+ *idx = (_index_t)wc;
+ } else {
+ *csid = (_index_t)(wc & ~0x00FFFF7F);
+ *idx = (_csid_t)(wc & 0x00FFFF7F);
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_HZ_stdenc_cstowc(_HZEncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ *wc = (wchar_t)idx;
+ switch (csid) {
+ case 0x80:
+ case 0x8080:
+ *wc |= (wchar_t)0x80;
+ /*FALLTHROUGH*/
+ case 0x0:
+ case 0x8000:
+ break;
+ default:
+ *wc |= (wchar_t)csid;
+ }
+
+ return (0);
+}
+
+static void
+_citrus_HZ_encoding_module_uninit(_HZEncodingInfo *ei)
+{
+ escape_t *escape;
+
+ while ((escape = TAILQ_FIRST(E0SET(ei))) != NULL) {
+ TAILQ_REMOVE(E0SET(ei), escape, entry);
+ free(GL(escape));
+ free(GR(escape));
+ free(escape);
+ }
+ while ((escape = TAILQ_FIRST(E1SET(ei))) != NULL) {
+ TAILQ_REMOVE(E1SET(ei), escape, entry);
+ free(GL(escape));
+ free(GR(escape));
+ free(escape);
+ }
+}
+
+static int
+_citrus_HZ_parse_char(void **context, const char *name __unused, const char *s)
+{
+ escape_t *escape;
+ void **p;
+
+ p = (void **)*context;
+ escape = (escape_t *)p[0];
+ if (escape->ch != '\0')
+ return (EINVAL);
+ escape->ch = *s++;
+ if (escape->ch == ESCAPE_CHAR || *s != '\0')
+ return (EINVAL);
+
+ return (0);
+}
+
+static int
+_citrus_HZ_parse_graphic(void **context, const char *name, const char *s)
+{
+ _HZEncodingInfo *ei;
+ escape_t *escape;
+ graphic_t *graphic;
+ void **p;
+
+ p = (void **)*context;
+ escape = (escape_t *)p[0];
+ ei = (_HZEncodingInfo *)p[1];
+ graphic = malloc(sizeof(*graphic));
+ if (graphic == NULL)
+ return (ENOMEM);
+ memset(graphic, 0, sizeof(*graphic));
+ if (strcmp("GL", name) == 0) {
+ if (GL(escape) != NULL)
+ goto release;
+ GL(escape) = graphic;
+ } else if (strcmp("GR", name) == 0) {
+ if (GR(escape) != NULL)
+ goto release;
+ GR(escape) = graphic;
+ } else {
+release:
+ free(graphic);
+ return (EINVAL);
+ }
+ graphic->escape = escape;
+ if (_bcs_strncasecmp("ASCII", s, 5) == 0) {
+ if (s[5] != '\0')
+ return (EINVAL);
+ graphic->charset = ASCII;
+ graphic->length = 1;
+ ei->ascii = graphic;
+ return (0);
+ } else if (_bcs_strncasecmp("GB2312", s, 6) == 0) {
+ if (s[6] != '\0')
+ return (EINVAL);
+ graphic->charset = GB2312;
+ graphic->length = 2;
+ ei->gb2312 = graphic;
+ return (0);
+ } else if (strncmp("94*", s, 3) == 0)
+ graphic->charset = CS94;
+ else if (strncmp("96*", s, 3) == 0)
+ graphic->charset = CS96;
+ else
+ return (EINVAL);
+ s += 3;
+ switch(*s) {
+ case '1': case '2': case '3':
+ graphic->length = (size_t)(*s - '0');
+ if (*++s == '\0')
+ break;
+ /*FALLTHROUGH*/
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static const _citrus_prop_hint_t escape_hints[] = {
+_CITRUS_PROP_HINT_STR("CH", &_citrus_HZ_parse_char),
+_CITRUS_PROP_HINT_STR("GL", &_citrus_HZ_parse_graphic),
+_CITRUS_PROP_HINT_STR("GR", &_citrus_HZ_parse_graphic),
+_CITRUS_PROP_HINT_END
+};
+
+static int
+_citrus_HZ_parse_escape(void **context, const char *name, const char *s)
+{
+ _HZEncodingInfo *ei;
+ escape_t *escape;
+ void *p[2];
+
+ ei = (_HZEncodingInfo *)*context;
+ escape = malloc(sizeof(*escape));
+ if (escape == NULL)
+ return (EINVAL);
+ memset(escape, 0, sizeof(*escape));
+ if (strcmp("0", name) == 0) {
+ escape->set = E0SET(ei);
+ TAILQ_INSERT_TAIL(E0SET(ei), escape, entry);
+ } else if (strcmp("1", name) == 0) {
+ escape->set = E1SET(ei);
+ TAILQ_INSERT_TAIL(E1SET(ei), escape, entry);
+ } else {
+ free(escape);
+ return (EINVAL);
+ }
+ p[0] = (void *)escape;
+ p[1] = (void *)ei;
+ return (_citrus_prop_parse_variable(
+ escape_hints, (void *)&p[0], s, strlen(s)));
+}
+
+static const _citrus_prop_hint_t root_hints[] = {
+_CITRUS_PROP_HINT_STR("0", &_citrus_HZ_parse_escape),
+_CITRUS_PROP_HINT_STR("1", &_citrus_HZ_parse_escape),
+_CITRUS_PROP_HINT_END
+};
+
+static int
+_citrus_HZ_encoding_module_init(_HZEncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar)
+{
+ int errnum;
+
+ memset(ei, 0, sizeof(*ei));
+ TAILQ_INIT(E0SET(ei));
+ TAILQ_INIT(E1SET(ei));
+ errnum = _citrus_prop_parse_variable(
+ root_hints, (void *)ei, var, lenvar);
+ if (errnum != 0)
+ _citrus_HZ_encoding_module_uninit(ei);
+ return (errnum);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(HZ);
+_CITRUS_STDENC_DEF_OPS(HZ);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/HZ/citrus_hz.h b/lib/libiconv_modules/HZ/citrus_hz.h
new file mode 100644
index 0000000..9737b7b
--- /dev/null
+++ b/lib/libiconv_modules/HZ/citrus_hz.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_hz.h,v 1.1 2006/11/22 23:38:27 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_HZ_H_
+#define _CITRUS_HZ_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(HZ);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/ISO2022/Makefile b/lib/libiconv_modules/ISO2022/Makefile
new file mode 100644
index 0000000..1e865ac
--- /dev/null
+++ b/lib/libiconv_modules/ISO2022/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= ISO2022
+SRCS+= citrus_iso2022.c
+CFLAGS+= --param max-inline-insns-single=128
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/ISO2022/citrus_iso2022.c b/lib/libiconv_modules/ISO2022/citrus_iso2022.c
new file mode 100644
index 0000000..82ad7c3
--- /dev/null
+++ b/lib/libiconv_modules/ISO2022/citrus_iso2022.c
@@ -0,0 +1,1289 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iso2022.c,v 1.19 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)1999, 2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Citrus: xpg4dl/FreeBSD/lib/libc/locale/iso2022.c,v 1.23 2001/06/21 01:51:44 yamt Exp $
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.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_stdenc.h"
+#include "citrus_iso2022.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+
+/*
+ * wchar_t mappings:
+ * ASCII (ESC ( B) 00000000 00000000 00000000 0xxxxxxx
+ * iso-8859-1 (ESC , A) 00000000 00000000 00000000 1xxxxxxx
+ * 94 charset (ESC ( F) 0fffffff 00000000 00000000 0xxxxxxx
+ * 94 charset (ESC ( M F) 0fffffff 1mmmmmmm 00000000 0xxxxxxx
+ * 96 charset (ESC , F) 0fffffff 00000000 00000000 1xxxxxxx
+ * 96 charset (ESC , M F) 0fffffff 1mmmmmmm 00000000 1xxxxxxx
+ * 94x94 charset (ESC $ ( F) 0fffffff 00000000 0xxxxxxx 0xxxxxxx
+ * 96x96 charset (ESC $ , F) 0fffffff 00000000 0xxxxxxx 1xxxxxxx
+ * 94x94 charset (ESC & V ESC $ ( F)
+ * 0fffffff 1vvvvvvv 0xxxxxxx 0xxxxxxx
+ * 94x94x94 charset (ESC $ ( F) 0fffffff 0xxxxxxx 0xxxxxxx 0xxxxxxx
+ * 96x96x96 charset (ESC $ , F) 0fffffff 0xxxxxxx 0xxxxxxx 1xxxxxxx
+ * reserved for UCS4 co-existence (UCS4 is 31bit encoding thanks to mohta bit)
+ * 1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
+ */
+
+#define CS94 (0U)
+#define CS96 (1U)
+#define CS94MULTI (2U)
+#define CS96MULTI (3U)
+
+typedef struct {
+ unsigned char interm;
+ unsigned char final;
+ unsigned char type;
+ unsigned char vers;
+} _ISO2022Charset;
+
+static const _ISO2022Charset ascii = { CS94, 'B', '\0', '\0' };
+static const _ISO2022Charset iso88591 = { CS96, 'A', '\0', '\0' };
+
+typedef struct {
+ _ISO2022Charset g[4];
+ /* need 3 bits to hold -1, 0, ..., 3 */
+ int gl:3,
+ gr:3,
+ singlegl:3,
+ singlegr:3;
+ char ch[7]; /* longest escape sequence (ESC & V ESC $ ( F) */
+ size_t chlen;
+ int flags;
+#define _ISO2022STATE_FLAG_INITIALIZED 1
+} _ISO2022State;
+
+typedef struct {
+ _ISO2022Charset *recommend[4];
+ size_t recommendsize[4];
+ _ISO2022Charset initg[4];
+ int maxcharset;
+ int flags;
+#define F_8BIT 0x0001
+#define F_NOOLD 0x0002
+#define F_SI 0x0010 /*0F*/
+#define F_SO 0x0020 /*0E*/
+#define F_LS0 0x0010 /*0F*/
+#define F_LS1 0x0020 /*0E*/
+#define F_LS2 0x0040 /*ESC n*/
+#define F_LS3 0x0080 /*ESC o*/
+#define F_LS1R 0x0100 /*ESC ~*/
+#define F_LS2R 0x0200 /*ESC }*/
+#define F_LS3R 0x0400 /*ESC |*/
+#define F_SS2 0x0800 /*ESC N*/
+#define F_SS3 0x1000 /*ESC O*/
+#define F_SS2R 0x2000 /*8E*/
+#define F_SS3R 0x4000 /*8F*/
+} _ISO2022EncodingInfo;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_ISO2022_##m
+#define _ENCODING_INFO _ISO2022EncodingInfo
+#define _ENCODING_STATE _ISO2022State
+#define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
+#define _ENCODING_IS_STATE_DEPENDENT 1
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) \
+ (!((_ps_)->flags & _ISO2022STATE_FLAG_INITIALIZED))
+
+
+#define _ISO2022INVALID (wchar_t)-1
+
+static __inline bool isc0(__uint8_t x)
+{
+
+ return ((x & 0x1f) == x);
+}
+
+static __inline bool isc1(__uint8_t x)
+{
+
+ return (0x80 <= x && x <= 0x9f);
+}
+
+static __inline bool iscntl(__uint8_t x)
+{
+
+ return (isc0(x) || isc1(x) || x == 0x7f);
+}
+
+static __inline bool is94(__uint8_t x)
+{
+
+ return (0x21 <= x && x <= 0x7e);
+}
+
+static __inline bool is96(__uint8_t x)
+{
+
+ return (0x20 <= x && x <= 0x7f);
+}
+
+static __inline bool isecma(__uint8_t x)
+{
+
+ return (0x30 <= x && x <= 0x7f);
+}
+
+static __inline bool isinterm(__uint8_t x)
+{
+
+ return (0x20 <= x && x <= 0x2f);
+}
+
+static __inline bool isthree(__uint8_t x)
+{
+
+ return (0x60 <= x && x <= 0x6f);
+}
+
+static __inline int
+getcs(const char * __restrict p, _ISO2022Charset * __restrict cs)
+{
+
+ if (!strncmp(p, "94$", 3) && p[3] && !p[4]) {
+ cs->final = (unsigned char)(p[3] & 0xff);
+ cs->interm = '\0';
+ cs->vers = '\0';
+ cs->type = CS94MULTI;
+ } else if (!strncmp(p, "96$", 3) && p[3] && !p[4]) {
+ cs->final = (unsigned char)(p[3] & 0xff);
+ cs->interm = '\0';
+ cs->vers = '\0';
+ cs->type = CS96MULTI;
+ } else if (!strncmp(p, "94", 2) && p[2] && !p[3]) {
+ cs->final = (unsigned char)(p[2] & 0xff);
+ cs->interm = '\0';
+ cs->vers = '\0';
+ cs->type = CS94;
+ } else if (!strncmp(p, "96", 2) && p[2] && !p[3]) {
+ cs->final = (unsigned char )(p[2] & 0xff);
+ cs->interm = '\0';
+ cs->vers = '\0';
+ cs->type = CS96;
+ } else
+ return (1);
+
+ return (0);
+}
+
+
+#define _NOTMATCH 0
+#define _MATCH 1
+#define _PARSEFAIL 2
+
+static __inline int
+get_recommend(_ISO2022EncodingInfo * __restrict ei,
+ const char * __restrict token)
+{
+ _ISO2022Charset cs, *p;
+ int i;
+
+ if (!strchr("0123", token[0]) || token[1] != '=')
+ return (_NOTMATCH);
+
+ if (getcs(&token[2], &cs) == 0)
+ ;
+ else if (!strcmp(&token[2], "94")) {
+ cs.final = (unsigned char)(token[4]);
+ cs.interm = '\0';
+ cs.vers = '\0';
+ cs.type = CS94;
+ } else if (!strcmp(&token[2], "96")) {
+ cs.final = (unsigned char)(token[4]);
+ cs.interm = '\0';
+ cs.vers = '\0';
+ cs.type = CS96;
+ } else if (!strcmp(&token[2], "94$")) {
+ cs.final = (unsigned char)(token[5]);
+ cs.interm = '\0';
+ cs.vers = '\0';
+ cs.type = CS94MULTI;
+ } else if (!strcmp(&token[2], "96$")) {
+ cs.final = (unsigned char)(token[5]);
+ cs.interm = '\0';
+ cs.vers = '\0';
+ cs.type = CS96MULTI;
+ } else
+ return (_PARSEFAIL);
+
+ i = token[0] - '0';
+ if (!ei->recommend[i])
+ ei->recommend[i] = malloc(sizeof(_ISO2022Charset));
+ else {
+ p = realloc(ei->recommend[i],
+ sizeof(_ISO2022Charset) * (ei->recommendsize[i] + 1));
+ if (!p)
+ return (_PARSEFAIL);
+ ei->recommend[i] = p;
+ }
+ if (!ei->recommend[i])
+ return (_PARSEFAIL);
+ ei->recommendsize[i]++;
+
+ (ei->recommend[i] + (ei->recommendsize[i] - 1))->final = cs.final;
+ (ei->recommend[i] + (ei->recommendsize[i] - 1))->interm = cs.interm;
+ (ei->recommend[i] + (ei->recommendsize[i] - 1))->vers = cs.vers;
+ (ei->recommend[i] + (ei->recommendsize[i] - 1))->type = cs.type;
+
+ return (_MATCH);
+}
+
+static __inline int
+get_initg(_ISO2022EncodingInfo * __restrict ei,
+ const char * __restrict token)
+{
+ _ISO2022Charset cs;
+
+ if (strncmp("INIT", &token[0], 4) ||
+ !strchr("0123", token[4]) ||
+ token[5] != '=')
+ return (_NOTMATCH);
+
+ if (getcs(&token[6], &cs) != 0)
+ return (_PARSEFAIL);
+
+ ei->initg[token[4] - '0'].type = cs.type;
+ ei->initg[token[4] - '0'].final = cs.final;
+ ei->initg[token[4] - '0'].interm = cs.interm;
+ ei->initg[token[4] - '0'].vers = cs.vers;
+
+ return (_MATCH);
+}
+
+static __inline int
+get_max(_ISO2022EncodingInfo * __restrict ei,
+ const char * __restrict token)
+{
+ if (!strcmp(token, "MAX1"))
+ ei->maxcharset = 1;
+ else if (!strcmp(token, "MAX2"))
+ ei->maxcharset = 2;
+ else if (!strcmp(token, "MAX3"))
+ ei->maxcharset = 3;
+ else
+ return (_NOTMATCH);
+
+ return (_MATCH);
+}
+
+
+static __inline int
+get_flags(_ISO2022EncodingInfo * __restrict ei,
+ const char * __restrict token)
+{
+ static struct {
+ const char *tag;
+ int flag;
+ } const tags[] = {
+ { "DUMMY", 0 },
+ { "8BIT", F_8BIT },
+ { "NOOLD", F_NOOLD },
+ { "SI", F_SI },
+ { "SO", F_SO },
+ { "LS0", F_LS0 },
+ { "LS1", F_LS1 },
+ { "LS2", F_LS2 },
+ { "LS3", F_LS3 },
+ { "LS1R", F_LS1R },
+ { "LS2R", F_LS2R },
+ { "LS3R", F_LS3R },
+ { "SS2", F_SS2 },
+ { "SS3", F_SS3 },
+ { "SS2R", F_SS2R },
+ { "SS3R", F_SS3R },
+ { NULL, 0 }
+ };
+ int i;
+
+ for (i = 0; tags[i].tag; i++)
+ if (!strcmp(token, tags[i].tag)) {
+ ei->flags |= tags[i].flag;
+ return (_MATCH);
+ }
+
+ return (_NOTMATCH);
+}
+
+
+static __inline int
+_citrus_ISO2022_parse_variable(_ISO2022EncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar __unused)
+{
+ char const *e, *v;
+ char buf[20];
+ size_t len;
+ int i, ret;
+
+ /*
+ * parse VARIABLE section.
+ */
+
+ if (!var)
+ return (EFTYPE);
+
+ v = (const char *) var;
+
+ /* initialize structure */
+ ei->maxcharset = 0;
+ for (i = 0; i < 4; i++) {
+ ei->recommend[i] = NULL;
+ ei->recommendsize[i] = 0;
+ }
+ ei->flags = 0;
+
+ while (*v) {
+ while (*v == ' ' || *v == '\t')
+ ++v;
+
+ /* find the token */
+ e = v;
+ while (*e && *e != ' ' && *e != '\t')
+ ++e;
+
+ len = e - v;
+ if (len == 0)
+ break;
+ if (len >= sizeof(buf))
+ goto parsefail;
+ snprintf(buf, sizeof(buf), "%.*s", (int)len, v);
+
+ if ((ret = get_recommend(ei, buf)) != _NOTMATCH)
+ ;
+ else if ((ret = get_initg(ei, buf)) != _NOTMATCH)
+ ;
+ else if ((ret = get_max(ei, buf)) != _NOTMATCH)
+ ;
+ else if ((ret = get_flags(ei, buf)) != _NOTMATCH)
+ ;
+ else
+ ret = _PARSEFAIL;
+ if (ret == _PARSEFAIL)
+ goto parsefail;
+ v = e;
+
+ }
+
+ return (0);
+
+parsefail:
+ free(ei->recommend[0]);
+ free(ei->recommend[1]);
+ free(ei->recommend[2]);
+ free(ei->recommend[3]);
+
+ return (EFTYPE);
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ISO2022_init_state(_ISO2022EncodingInfo * __restrict ei,
+ _ISO2022State * __restrict s)
+{
+ int i;
+
+ memset(s, 0, sizeof(*s));
+ s->gl = 0;
+ s->gr = (ei->flags & F_8BIT) ? 1 : -1;
+
+ for (i = 0; i < 4; i++)
+ if (ei->initg[i].final) {
+ s->g[i].type = ei->initg[i].type;
+ s->g[i].final = ei->initg[i].final;
+ s->g[i].interm = ei->initg[i].interm;
+ }
+ s->singlegl = s->singlegr = -1;
+ s->flags |= _ISO2022STATE_FLAG_INITIALIZED;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ISO2022_pack_state(_ISO2022EncodingInfo * __restrict ei __unused,
+ void * __restrict pspriv, const _ISO2022State * __restrict s)
+{
+
+ memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ISO2022_unpack_state(_ISO2022EncodingInfo * __restrict ei __unused,
+ _ISO2022State * __restrict s, const void * __restrict pspriv)
+{
+
+ memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_ISO2022_encoding_module_init(_ISO2022EncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar)
+{
+
+ return (_citrus_ISO2022_parse_variable(ei, var, lenvar));
+}
+
+static void
+/*ARGSUSED*/
+_citrus_ISO2022_encoding_module_uninit(_ISO2022EncodingInfo *ei __unused)
+{
+
+}
+
+#define ESC '\033'
+#define ECMA -1
+#define INTERM -2
+#define OECMA -3
+static const struct seqtable {
+ int type;
+ int csoff;
+ int finaloff;
+ int intermoff;
+ int versoff;
+ int len;
+ int chars[10];
+} seqtable[] = {
+ /* G0 94MULTI special */
+ { CS94MULTI, -1, 2, -1, -1, 3, { ESC, '$', OECMA }, },
+ /* G0 94MULTI special with version identification */
+ { CS94MULTI, -1, 5, -1, 2, 6, { ESC, '&', ECMA, ESC, '$', OECMA }, },
+ /* G? 94 */
+ { CS94, 1, 2, -1, -1, 3, { ESC, CS94, ECMA, }, },
+ /* G? 94 with 2nd intermediate char */
+ { CS94, 1, 3, 2, -1, 4, { ESC, CS94, INTERM, ECMA, }, },
+ /* G? 96 */
+ { CS96, 1, 2, -1, -1, 3, { ESC, CS96, ECMA, }, },
+ /* G? 96 with 2nd intermediate char */
+ { CS96, 1, 3, 2, -1, 4, { ESC, CS96, INTERM, ECMA, }, },
+ /* G? 94MULTI */
+ { CS94MULTI, 2, 3, -1, -1, 4, { ESC, '$', CS94, ECMA, }, },
+ /* G? 96MULTI */
+ { CS96MULTI, 2, 3, -1, -1, 4, { ESC, '$', CS96, ECMA, }, },
+ /* G? 94MULTI with version specification */
+ { CS94MULTI, 5, 6, -1, 2, 7, { ESC, '&', ECMA, ESC, '$', CS94, ECMA, }, },
+ /* LS2/3 */
+ { -1, -1, -1, -1, -1, 2, { ESC, 'n', }, },
+ { -1, -1, -1, -1, -1, 2, { ESC, 'o', }, },
+ /* LS1/2/3R */
+ { -1, -1, -1, -1, -1, 2, { ESC, '~', }, },
+ { -1, -1, -1, -1, -1, 2, { ESC, /*{*/ '}', }, },
+ { -1, -1, -1, -1, -1, 2, { ESC, '|', }, },
+ /* SS2/3 */
+ { -1, -1, -1, -1, -1, 2, { ESC, 'N', }, },
+ { -1, -1, -1, -1, -1, 2, { ESC, 'O', }, },
+ /* end of records */
+// { 0, }
+ { 0, 0, 0, 0, 0, 0, { ESC, 0, }, }
+};
+
+static int
+seqmatch(const char * __restrict s, size_t n,
+ const struct seqtable * __restrict sp)
+{
+ const int *p;
+
+ p = sp->chars;
+ while ((size_t)(p - sp->chars) < n && p - sp->chars < sp->len) {
+ switch (*p) {
+ case ECMA:
+ if (!isecma(*s))
+ goto terminate;
+ break;
+ case OECMA:
+ if (*s && strchr("@AB", *s))
+ break;
+ else
+ goto terminate;
+ case INTERM:
+ if (!isinterm(*s))
+ goto terminate;
+ break;
+ case CS94:
+ if (*s && strchr("()*+", *s))
+ break;
+ else
+ goto terminate;
+ case CS96:
+ if (*s && strchr(",-./", *s))
+ break;
+ else
+ goto terminate;
+ default:
+ if (*s != *p)
+ goto terminate;
+ break;
+ }
+
+ p++;
+ s++;
+ }
+
+terminate:
+ return (p - sp->chars);
+}
+
+static wchar_t
+_ISO2022_sgetwchar(_ISO2022EncodingInfo * __restrict ei __unused,
+ char * __restrict string, size_t n, char ** __restrict result,
+ _ISO2022State * __restrict psenc)
+{
+ const struct seqtable *sp;
+ wchar_t wchar = 0;
+ int i, cur, nmatch;
+
+ while (1) {
+ /* SI/SO */
+ if (1 <= n && string[0] == '\017') {
+ psenc->gl = 0;
+ string++;
+ n--;
+ continue;
+ }
+ if (1 <= n && string[0] == '\016') {
+ psenc->gl = 1;
+ string++;
+ n--;
+ continue;
+ }
+
+ /* SS2/3R */
+ if (1 <= n && string[0] && strchr("\217\216", string[0])) {
+ psenc->singlegl = psenc->singlegr =
+ (string[0] - '\216') + 2;
+ string++;
+ n--;
+ continue;
+ }
+
+ /* eat the letter if this is not ESC */
+ if (1 <= n && string[0] != '\033')
+ break;
+
+ /* look for a perfect match from escape sequences */
+ for (sp = &seqtable[0]; sp->len; sp++) {
+ nmatch = seqmatch(string, n, sp);
+ if (sp->len == nmatch && n >= (size_t)(sp->len))
+ break;
+ }
+
+ if (!sp->len)
+ goto notseq;
+
+ if (sp->type != -1) {
+ if (sp->csoff == -1)
+ i = 0;
+ else {
+ switch (sp->type) {
+ case CS94:
+ case CS94MULTI:
+ i = string[sp->csoff] - '(';
+ break;
+ case CS96:
+ case CS96MULTI:
+ i = string[sp->csoff] - ',';
+ break;
+ default:
+ return (_ISO2022INVALID);
+ }
+ }
+ psenc->g[i].type = sp->type;
+ psenc->g[i].final = '\0';
+ psenc->g[i].interm = '\0';
+ psenc->g[i].vers = '\0';
+ /* sp->finaloff must not be -1 */
+ if (sp->finaloff != -1)
+ psenc->g[i].final = string[sp->finaloff];
+ if (sp->intermoff != -1)
+ psenc->g[i].interm = string[sp->intermoff];
+ if (sp->versoff != -1)
+ psenc->g[i].vers = string[sp->versoff];
+
+ string += sp->len;
+ n -= sp->len;
+ continue;
+ }
+
+ /* LS2/3 */
+ if (2 <= n && string[0] == '\033' &&
+ string[1] && strchr("no", string[1])) {
+ psenc->gl = string[1] - 'n' + 2;
+ string += 2;
+ n -= 2;
+ continue;
+ }
+
+ /* LS1/2/3R */
+ /* XXX: { for vi showmatch */
+ if (2 <= n && string[0] == '\033' &&
+ string[1] && strchr("~}|", string[1])) {
+ psenc->gr = 3 - (string[1] - '|');
+ string += 2;
+ n -= 2;
+ continue;
+ }
+
+ /* SS2/3 */
+ if (2 <= n && string[0] == '\033' && string[1] &&
+ strchr("NO", string[1])) {
+ psenc->singlegl = (string[1] - 'N') + 2;
+ string += 2;
+ n -= 2;
+ continue;
+ }
+
+ notseq:
+ /*
+ * if we've got an unknown escape sequence, eat the ESC at the
+ * head. otherwise, wait till full escape sequence comes.
+ */
+ for (sp = &seqtable[0]; sp->len; sp++) {
+ nmatch = seqmatch(string, n, sp);
+ if (!nmatch)
+ continue;
+
+ /*
+ * if we are in the middle of escape sequence,
+ * we still need to wait for more characters to come
+ */
+ if (n < (size_t)(sp->len)) {
+ if ((size_t)(nmatch) == n) {
+ if (result)
+ *result = string;
+ return (_ISO2022INVALID);
+ }
+ } else {
+ if (nmatch == sp->len) {
+ /* this case should not happen */
+ goto eat;
+ }
+ }
+ }
+
+ break;
+ }
+
+eat:
+ /* no letter to eat */
+ if (n < 1) {
+ if (result)
+ *result = string;
+ return (_ISO2022INVALID);
+ }
+
+ /* normal chars. always eat C0/C1 as is. */
+ if (iscntl(*string & 0xff))
+ cur = -1;
+ else if (*string & 0x80)
+ cur = (psenc->singlegr == -1) ? psenc->gr : psenc->singlegr;
+ else
+ cur = (psenc->singlegl == -1) ? psenc->gl : psenc->singlegl;
+
+ if (cur == -1) {
+asis:
+ wchar = *string++ & 0xff;
+ if (result)
+ *result = string;
+ /* reset single shift state */
+ psenc->singlegr = psenc->singlegl = -1;
+ return (wchar);
+ }
+
+ /* length error check */
+ switch (psenc->g[cur].type) {
+ case CS94MULTI:
+ case CS96MULTI:
+ if (!isthree(psenc->g[cur].final)) {
+ if (2 <= n &&
+ (string[0] & 0x80) == (string[1] & 0x80))
+ break;
+ } else {
+ if (3 <= n &&
+ (string[0] & 0x80) == (string[1] & 0x80) &&
+ (string[0] & 0x80) == (string[2] & 0x80))
+ break;
+ }
+
+ /* we still need to wait for more characters to come */
+ if (result)
+ *result = string;
+ return (_ISO2022INVALID);
+
+ case CS94:
+ case CS96:
+ if (1 <= n)
+ break;
+
+ /* we still need to wait for more characters to come */
+ if (result)
+ *result = string;
+ return (_ISO2022INVALID);
+ }
+
+ /* range check */
+ switch (psenc->g[cur].type) {
+ case CS94:
+ if (!(is94(string[0] & 0x7f)))
+ goto asis;
+ case CS96:
+ if (!(is96(string[0] & 0x7f)))
+ goto asis;
+ break;
+ case CS94MULTI:
+ if (!(is94(string[0] & 0x7f) && is94(string[1] & 0x7f)))
+ goto asis;
+ break;
+ case CS96MULTI:
+ if (!(is96(string[0] & 0x7f) && is96(string[1] & 0x7f)))
+ goto asis;
+ break;
+ }
+
+ /* extract the character. */
+ switch (psenc->g[cur].type) {
+ case CS94:
+ /* special case for ASCII. */
+ if (psenc->g[cur].final == 'B' && !psenc->g[cur].interm) {
+ wchar = *string++;
+ wchar &= 0x7f;
+ break;
+ }
+ wchar = psenc->g[cur].final;
+ wchar = (wchar << 8);
+ wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0);
+ wchar = (wchar << 8);
+ wchar = (wchar << 8) | (*string++ & 0x7f);
+ break;
+ case CS96:
+ /* special case for ISO-8859-1. */
+ if (psenc->g[cur].final == 'A' && !psenc->g[cur].interm) {
+ wchar = *string++;
+ wchar &= 0x7f;
+ wchar |= 0x80;
+ break;
+ }
+ wchar = psenc->g[cur].final;
+ wchar = (wchar << 8);
+ wchar |= (psenc->g[cur].interm ? (0x80 | psenc->g[cur].interm) : 0);
+ wchar = (wchar << 8);
+ wchar = (wchar << 8) | (*string++ & 0x7f);
+ wchar |= 0x80;
+ break;
+ case CS94MULTI:
+ case CS96MULTI:
+ wchar = psenc->g[cur].final;
+ wchar = (wchar << 8);
+ if (isthree(psenc->g[cur].final))
+ wchar |= (*string++ & 0x7f);
+ wchar = (wchar << 8) | (*string++ & 0x7f);
+ wchar = (wchar << 8) | (*string++ & 0x7f);
+ if (psenc->g[cur].type == CS96MULTI)
+ wchar |= 0x80;
+ break;
+ }
+
+ if (result)
+ *result = string;
+ /* reset single shift state */
+ psenc->singlegr = psenc->singlegl = -1;
+ return (wchar);
+}
+
+
+
+static int
+_citrus_ISO2022_mbrtowc_priv(_ISO2022EncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s,
+ size_t n, _ISO2022State * __restrict psenc, size_t * __restrict nresult)
+{
+ char *p, *result, *s0;
+ wchar_t wchar;
+ int c, chlenbak;
+
+ if (*s == NULL) {
+ _citrus_ISO2022_init_state(ei, psenc);
+ *nresult = _ENCODING_IS_STATE_DEPENDENT;
+ return (0);
+ }
+ s0 = *s;
+ c = 0;
+ chlenbak = psenc->chlen;
+
+ /*
+ * if we have something in buffer, use that.
+ * otherwise, skip here
+ */
+ if (psenc->chlen > sizeof(psenc->ch)) {
+ /* illgeal state */
+ _citrus_ISO2022_init_state(ei, psenc);
+ goto encoding_error;
+ }
+ if (psenc->chlen == 0)
+ goto emptybuf;
+
+ /* buffer is not empty */
+ p = psenc->ch;
+ while (psenc->chlen < sizeof(psenc->ch)) {
+ if (n > 0) {
+ psenc->ch[psenc->chlen++] = *s0++;
+ n--;
+ }
+
+ wchar = _ISO2022_sgetwchar(ei, p, psenc->chlen - (p-psenc->ch),
+ &result, psenc);
+ c += result - p;
+ if (wchar != _ISO2022INVALID) {
+ if (psenc->chlen > (size_t)c)
+ memmove(psenc->ch, result, psenc->chlen - c);
+ if (psenc->chlen < (size_t)c)
+ psenc->chlen = 0;
+ else
+ psenc->chlen -= c;
+ goto output;
+ }
+
+ if (n == 0) {
+ if ((size_t)(result - p) == psenc->chlen)
+ /* complete shift sequence. */
+ psenc->chlen = 0;
+ goto restart;
+ }
+
+ p = result;
+ }
+
+ /* escape sequence too long? */
+ goto encoding_error;
+
+emptybuf:
+ wchar = _ISO2022_sgetwchar(ei, s0, n, &result, psenc);
+ if (wchar != _ISO2022INVALID) {
+ c += result - s0;
+ psenc->chlen = 0;
+ s0 = result;
+ goto output;
+ }
+ if (result > s0) {
+ c += (result - s0);
+ n -= (result - s0);
+ s0 = result;
+ if (n > 0)
+ goto emptybuf;
+ /* complete shift sequence. */
+ goto restart;
+ }
+ n += c;
+ if (n < sizeof(psenc->ch)) {
+ memcpy(psenc->ch, s0 - c, n);
+ psenc->chlen = n;
+ s0 = result;
+ goto restart;
+ }
+
+ /* escape sequence too long? */
+
+encoding_error:
+ psenc->chlen = 0;
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+
+output:
+ *s = s0;
+ if (pwc)
+ *pwc = wchar;
+ *nresult = wchar ? c - chlenbak : 0;
+ return (0);
+
+restart:
+ *s = s0;
+ *nresult = (size_t)-2;
+
+ return (0);
+}
+
+static int
+recommendation(_ISO2022EncodingInfo * __restrict ei,
+ _ISO2022Charset * __restrict cs)
+{
+ _ISO2022Charset *recommend;
+ size_t j;
+ int i;
+
+ /* first, try a exact match. */
+ for (i = 0; i < 4; i++) {
+ recommend = ei->recommend[i];
+ for (j = 0; j < ei->recommendsize[i]; j++) {
+ if (cs->type != recommend[j].type)
+ continue;
+ if (cs->final != recommend[j].final)
+ continue;
+ if (cs->interm != recommend[j].interm)
+ continue;
+
+ return (i);
+ }
+ }
+
+ /* then, try a wildcard match over final char. */
+ for (i = 0; i < 4; i++) {
+ recommend = ei->recommend[i];
+ for (j = 0; j < ei->recommendsize[i]; j++) {
+ if (cs->type != recommend[j].type)
+ continue;
+ if (cs->final && (cs->final != recommend[j].final))
+ continue;
+ if (cs->interm && (cs->interm != recommend[j].interm))
+ continue;
+
+ return (i);
+ }
+ }
+
+ /* there's no recommendation. make a guess. */
+ if (ei->maxcharset == 0) {
+ return (0);
+ } else {
+ switch (cs->type) {
+ case CS94:
+ case CS94MULTI:
+ return (0);
+ case CS96:
+ case CS96MULTI:
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static int
+_ISO2022_sputwchar(_ISO2022EncodingInfo * __restrict ei, wchar_t wc,
+ char * __restrict string, size_t n, char ** __restrict result,
+ _ISO2022State * __restrict psenc, size_t * __restrict nresult)
+{
+ _ISO2022Charset cs;
+ char *p;
+ char tmp[MB_LEN_MAX];
+ size_t len;
+ int bit8, i = 0, target;
+ unsigned char mask;
+
+ if (isc0(wc & 0xff)) {
+ /* go back to INIT0 or ASCII on control chars */
+ cs = ei->initg[0].final ? ei->initg[0] : ascii;
+ } else if (isc1(wc & 0xff)) {
+ /* go back to INIT1 or ISO-8859-1 on control chars */
+ cs = ei->initg[1].final ? ei->initg[1] : iso88591;
+ } else if (!(wc & ~0xff)) {
+ if (wc & 0x80) {
+ /* special treatment for ISO-8859-1 */
+ cs = iso88591;
+ } else {
+ /* special treatment for ASCII */
+ cs = ascii;
+ }
+ } else {
+ cs.final = (wc >> 24) & 0x7f;
+ if ((wc >> 16) & 0x80)
+ cs.interm = (wc >> 16) & 0x7f;
+ else
+ cs.interm = '\0';
+ if (wc & 0x80)
+ cs.type = (wc & 0x00007f00) ? CS96MULTI : CS96;
+ else
+ cs.type = (wc & 0x00007f00) ? CS94MULTI : CS94;
+ }
+ target = recommendation(ei, &cs);
+ p = tmp;
+ bit8 = ei->flags & F_8BIT;
+
+ /* designate the charset onto the target plane(G0/1/2/3). */
+ if (psenc->g[target].type == cs.type &&
+ psenc->g[target].final == cs.final &&
+ psenc->g[target].interm == cs.interm)
+ goto planeok;
+
+ *p++ = '\033';
+ if (cs.type == CS94MULTI || cs.type == CS96MULTI)
+ *p++ = '$';
+ if (target == 0 && cs.type == CS94MULTI && strchr("@AB", cs.final) &&
+ !cs.interm && !(ei->flags & F_NOOLD))
+ ;
+ else if (cs.type == CS94 || cs.type == CS94MULTI)
+ *p++ = "()*+"[target];
+ else
+ *p++ = ",-./"[target];
+ if (cs.interm)
+ *p++ = cs.interm;
+ *p++ = cs.final;
+
+ psenc->g[target].type = cs.type;
+ psenc->g[target].final = cs.final;
+ psenc->g[target].interm = cs.interm;
+
+planeok:
+ /* invoke the plane onto GL or GR. */
+ if (psenc->gl == target)
+ goto sideok;
+ if (bit8 && psenc->gr == target)
+ goto sideok;
+
+ if (target == 0 && (ei->flags & F_LS0)) {
+ *p++ = '\017';
+ psenc->gl = 0;
+ } else if (target == 1 && (ei->flags & F_LS1)) {
+ *p++ = '\016';
+ psenc->gl = 1;
+ } else if (target == 2 && (ei->flags & F_LS2)) {
+ *p++ = '\033';
+ *p++ = 'n';
+ psenc->gl = 2;
+ } else if (target == 3 && (ei->flags & F_LS3)) {
+ *p++ = '\033';
+ *p++ = 'o';
+ psenc->gl = 3;
+ } else if (bit8 && target == 1 && (ei->flags & F_LS1R)) {
+ *p++ = '\033';
+ *p++ = '~';
+ psenc->gr = 1;
+ } else if (bit8 && target == 2 && (ei->flags & F_LS2R)) {
+ *p++ = '\033';
+ /*{*/
+ *p++ = '}';
+ psenc->gr = 2;
+ } else if (bit8 && target == 3 && (ei->flags & F_LS3R)) {
+ *p++ = '\033';
+ *p++ = '|';
+ psenc->gr = 3;
+ } else if (target == 2 && (ei->flags & F_SS2)) {
+ *p++ = '\033';
+ *p++ = 'N';
+ psenc->singlegl = 2;
+ } else if (target == 3 && (ei->flags & F_SS3)) {
+ *p++ = '\033';
+ *p++ = 'O';
+ psenc->singlegl = 3;
+ } else if (bit8 && target == 2 && (ei->flags & F_SS2R)) {
+ *p++ = '\216';
+ *p++ = 'N';
+ psenc->singlegl = psenc->singlegr = 2;
+ } else if (bit8 && target == 3 && (ei->flags & F_SS3R)) {
+ *p++ = '\217';
+ *p++ = 'O';
+ psenc->singlegl = psenc->singlegr = 3;
+ } else
+ goto ilseq;
+
+sideok:
+ if (psenc->singlegl == target)
+ mask = 0x00;
+ else if (psenc->singlegr == target)
+ mask = 0x80;
+ else if (psenc->gl == target)
+ mask = 0x00;
+ else if ((ei->flags & F_8BIT) && psenc->gr == target)
+ mask = 0x80;
+ else
+ goto ilseq;
+
+ switch (cs.type) {
+ case CS94:
+ case CS96:
+ i = 1;
+ break;
+ case CS94MULTI:
+ case CS96MULTI:
+ i = !iscntl(wc & 0xff) ?
+ (isthree(cs.final) ? 3 : 2) : 1;
+ break;
+ }
+ while (i-- > 0)
+ *p++ = ((wc >> (i << 3)) & 0x7f) | mask;
+
+ /* reset single shift state */
+ psenc->singlegl = psenc->singlegr = -1;
+
+ len = (size_t)(p - tmp);
+ if (n < len) {
+ if (result)
+ *result = (char *)0;
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ if (result)
+ *result = string + len;
+ memcpy(string, tmp, len);
+ *nresult = len;
+
+ return (0);
+
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+}
+
+static int
+_citrus_ISO2022_put_state_reset(_ISO2022EncodingInfo * __restrict ei,
+ char * __restrict s, size_t n, _ISO2022State * __restrict psenc,
+ size_t * __restrict nresult)
+{
+ char *result;
+ char buf[MB_LEN_MAX];
+ size_t len;
+ int ret;
+
+ /* XXX state will be modified after this operation... */
+ ret = _ISO2022_sputwchar(ei, L'\0', buf, sizeof(buf), &result, psenc,
+ &len);
+ if (ret) {
+ *nresult = len;
+ return (ret);
+ }
+
+ if (sizeof(buf) < len || n < len-1) {
+ /* XXX should recover state? */
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+
+ memcpy(s, buf, len - 1);
+ *nresult = len - 1;
+ return (0);
+}
+
+static int
+_citrus_ISO2022_wcrtomb_priv(_ISO2022EncodingInfo * __restrict ei,
+ char * __restrict s, size_t n, wchar_t wc,
+ _ISO2022State * __restrict psenc, size_t * __restrict nresult)
+{
+ char *result;
+ char buf[MB_LEN_MAX];
+ size_t len;
+ int ret;
+
+ /* XXX state will be modified after this operation... */
+ ret = _ISO2022_sputwchar(ei, wc, buf, sizeof(buf), &result, psenc,
+ &len);
+ if (ret) {
+ *nresult = len;
+ return (ret);
+ }
+
+ if (sizeof(buf) < len || n < len) {
+ /* XXX should recover state? */
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+
+ memcpy(s, buf, len);
+ *nresult = len;
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ISO2022_stdenc_wctocs(_ISO2022EncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+ wchar_t m, nm;
+
+ m = wc & 0x7FFF8080;
+ nm = wc & 0x007F7F7F;
+ if (m & 0x00800000)
+ nm &= 0x00007F7F;
+ else
+ m &= 0x7F008080;
+ if (nm & 0x007F0000) {
+ /* ^3 mark */
+ m |= 0x007F0000;
+ } else if (nm & 0x00007F00) {
+ /* ^2 mark */
+ m |= 0x00007F00;
+ }
+ *csid = (_csid_t)m;
+ *idx = (_index_t)nm;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ISO2022_stdenc_cstowc(_ISO2022EncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ *wc = (wchar_t)(csid & 0x7F808080) | (wchar_t)idx;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ISO2022_stdenc_get_state_desc_generic(_ISO2022EncodingInfo * __restrict ei __unused,
+ _ISO2022State * __restrict psenc, int * __restrict rstate)
+{
+
+ if (psenc->chlen == 0) {
+ /* XXX: it should distinguish initial and stable. */
+ *rstate = _STDENC_SDGEN_STABLE;
+ } else
+ *rstate = (psenc->ch[0] == '\033') ?
+ _STDENC_SDGEN_INCOMPLETE_SHIFT :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(ISO2022);
+_CITRUS_STDENC_DEF_OPS(ISO2022);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/ISO2022/citrus_iso2022.h b/lib/libiconv_modules/ISO2022/citrus_iso2022.h
new file mode 100644
index 0000000..c5bbc40
--- /dev/null
+++ b/lib/libiconv_modules/ISO2022/citrus_iso2022.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iso2022.h,v 1.2 2003/06/25 09:51:44 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ISO2022_H_
+#define _CITRUS_ISO2022_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(ISO2022);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/JOHAB/Makefile b/lib/libiconv_modules/JOHAB/Makefile
new file mode 100644
index 0000000..b945445
--- /dev/null
+++ b/lib/libiconv_modules/JOHAB/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= JOHAB
+SRCS+= citrus_johab.c
+CFLAGS+= --param max-inline-insns-single=16
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/JOHAB/citrus_johab.c b/lib/libiconv_modules/JOHAB/citrus_johab.c
new file mode 100644
index 0000000..35c35f3
--- /dev/null
+++ b/lib/libiconv_modules/JOHAB/citrus_johab.c
@@ -0,0 +1,333 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_johab.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+ int chlen;
+ char ch[2];
+} _JOHABState;
+
+typedef struct {
+ int dummy;
+} _JOHABEncodingInfo;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_JOHAB_##m
+#define _ENCODING_INFO _JOHABEncodingInfo
+#define _ENCODING_STATE _JOHABState
+#define _ENCODING_MB_CUR_MAX(_ei_) 2
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+
+static __inline void
+/*ARGSUSED*/
+_citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei __unused,
+ _JOHABState * __restrict psenc)
+{
+
+ psenc->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_JOHAB_pack_state(_JOHABEncodingInfo * __restrict ei __unused,
+ void * __restrict pspriv, const _JOHABState * __restrict psenc)
+{
+
+ memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_JOHAB_unpack_state(_JOHABEncodingInfo * __restrict ei __unused,
+ _JOHABState * __restrict psenc, const void * __restrict pspriv)
+{
+
+ memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static void
+/*ARGSUSED*/
+_citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo *ei __unused)
+{
+
+ /* ei may be null */
+}
+
+static int
+/*ARGSUSED*/
+_citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei __unused,
+ const void * __restrict var __unused, size_t lenvar __unused)
+{
+
+ /* ei may be null */
+ return (0);
+}
+
+static __inline bool
+ishangul(int l, int t)
+{
+
+ return ((l >= 0x84 && l <= 0xD3) &&
+ ((t >= 0x41 && t <= 0x7E) || (t >= 0x81 && t <= 0xFE)));
+}
+
+static __inline bool
+isuda(int l, int t)
+{
+
+ return ((l == 0xD8) &&
+ ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE)));
+}
+
+static __inline bool
+ishanja(int l, int t)
+{
+
+ return (((l >= 0xD9 && l <= 0xDE) || (l >= 0xE0 && l <= 0xF9)) &&
+ ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE)));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s, size_t n,
+ _JOHABState * __restrict psenc, size_t * __restrict nresult)
+{
+ char *s0;
+ int l, t;
+
+ if (*s == NULL) {
+ _citrus_JOHAB_init_state(ei, psenc);
+ *nresult = _ENCODING_IS_STATE_DEPENDENT;
+ return (0);
+ }
+ s0 = *s;
+
+ switch (psenc->chlen) {
+ case 0:
+ if (n-- < 1)
+ goto restart;
+ l = *s0++ & 0xFF;
+ if (l <= 0x7F) {
+ if (pwc != NULL)
+ *pwc = (wchar_t)l;
+ *nresult = (l == 0) ? 0 : 1;
+ *s = s0;
+ return (0);
+ }
+ psenc->ch[psenc->chlen++] = l;
+ break;
+ case 1:
+ l = psenc->ch[0] & 0xFF;
+ break;
+ default:
+ return (EINVAL);
+ }
+ if (n-- < 1) {
+restart:
+ *nresult = (size_t)-2;
+ *s = s0;
+ return (0);
+ }
+ t = *s0++ & 0xFF;
+ if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t)) {
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ }
+ if (pwc != NULL)
+ *pwc = (wchar_t)(l << 8 | t);
+ *nresult = s0 - *s;
+ *s = s0;
+ psenc->chlen = 0;
+
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei __unused,
+ char * __restrict s, size_t n, wchar_t wc,
+ _JOHABState * __restrict psenc, size_t * __restrict nresult)
+{
+ int l, t;
+
+ if (psenc->chlen != 0)
+ return (EINVAL);
+
+ /* XXX assume wchar_t as int */
+ if ((uint32_t)wc <= 0x7F) {
+ if (n < 1)
+ goto e2big;
+ *s = wc & 0xFF;
+ *nresult = 1;
+ } else if ((uint32_t)wc <= 0xFFFF) {
+ if (n < 2) {
+e2big:
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ l = (wc >> 8) & 0xFF;
+ t = wc & 0xFF;
+ if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t))
+ goto ilseq;
+ *s++ = l;
+ *s = t;
+ *nresult = 2;
+ } else {
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ }
+ return (0);
+
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+ int m, l, linear, t;
+
+ /* XXX assume wchar_t as int */
+ if ((uint32_t)wc <= 0x7F) {
+ *idx = (_index_t)wc;
+ *csid = 0;
+ } else if ((uint32_t)wc <= 0xFFFF) {
+ l = (wc >> 8) & 0xFF;
+ t = wc & 0xFF;
+ if (ishangul(l, t) || isuda(l, t)) {
+ *idx = (_index_t)wc;
+ *csid = 1;
+ } else {
+ if (l >= 0xD9 && l <= 0xDE) {
+ linear = l - 0xD9;
+ m = 0x21;
+ } else if (l >= 0xE0 && l <= 0xF9) {
+ linear = l - 0xE0;
+ m = 0x4A;
+ } else
+ return (EILSEQ);
+ linear *= 188;
+ if (t >= 0x31 && t <= 0x7E)
+ linear += t - 0x31;
+ else if (t >= 0x91 && t <= 0xFE)
+ linear += t - 0x43;
+ else
+ return (EILSEQ);
+ l = (linear / 94) + m;
+ t = (linear % 94) + 0x21;
+ *idx = (_index_t)((l << 8) | t);
+ *csid = 2;
+ }
+ } else
+ return (EILSEQ);
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+ int m, n, l, linear, t;
+
+ switch (csid) {
+ case 0:
+ case 1:
+ *wc = (wchar_t)idx;
+ break;
+ case 2:
+ if (idx >= 0x2121 && idx <= 0x2C71) {
+ m = 0xD9;
+ n = 0x21;
+ } else if (idx >= 0x4A21 && idx <= 0x7D7E) {
+ m = 0xE0;
+ n = 0x4A;
+ } else
+ return (EILSEQ);
+ l = ((idx >> 8) & 0xFF) - n;
+ t = (idx & 0xFF) - 0x21;
+ linear = (l * 94) + t;
+ l = (linear / 188) + m;
+ t = linear % 188;
+ t += (t <= 0x4D) ? 0x31 : 0x43;
+ break;
+ default:
+ return (EILSEQ);
+ }
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei __unused,
+ _JOHABState * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(JOHAB);
+_CITRUS_STDENC_DEF_OPS(JOHAB);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/JOHAB/citrus_johab.h b/lib/libiconv_modules/JOHAB/citrus_johab.h
new file mode 100644
index 0000000..f11fb4e5
--- /dev/null
+++ b/lib/libiconv_modules/JOHAB/citrus_johab.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_johab.h,v 1.1 2006/10/18 17:54:55 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_JOHAB_H_
+#define _CITRUS_JOHAB_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(JOHAB);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/MSKanji/Makefile b/lib/libiconv_modules/MSKanji/Makefile
new file mode 100644
index 0000000..d4703eb
--- /dev/null
+++ b/lib/libiconv_modules/MSKanji/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SHLIB= MSKanji
+SRCS+= citrus_mskanji.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/MSKanji/citrus_mskanji.c b/lib/libiconv_modules/MSKanji/citrus_mskanji.c
new file mode 100644
index 0000000..e655448
--- /dev/null
+++ b/lib/libiconv_modules/MSKanji/citrus_mskanji.c
@@ -0,0 +1,473 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mskanji.c,v 1.13 2008/06/14 16:01:08 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * ja_JP.SJIS locale table for BSD4.4/rune
+ * version 1.0
+ * (C) Sin'ichiro MIYATANI / Phase One, Inc
+ * May 12, 1995
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Phase One, Inc.
+ * 4. The name of Phase One, Inc. may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.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_bcs.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_mskanji.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct _MSKanjiState {
+ int chlen;
+ char ch[2];
+} _MSKanjiState;
+
+typedef struct {
+ int mode;
+#define MODE_JIS2004 1
+} _MSKanjiEncodingInfo;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_MSKanji_##m
+#define _ENCODING_INFO _MSKanjiEncodingInfo
+#define _ENCODING_STATE _MSKanjiState
+#define _ENCODING_MB_CUR_MAX(_ei_) 2
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+
+static bool
+_mskanji1(int c)
+{
+
+ return ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xfc));
+}
+
+static bool
+_mskanji2(int c)
+{
+
+ return ((c >= 0x40 && c <= 0x7e) || (c >= 0x80 && c <= 0xfc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_MSKanji_init_state(_MSKanjiEncodingInfo * __restrict ei __unused,
+ _MSKanjiState * __restrict s)
+{
+
+ s->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_MSKanji_pack_state(_MSKanjiEncodingInfo * __restrict ei __unused,
+ void * __restrict pspriv, const _MSKanjiState * __restrict s)
+{
+
+ memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_MSKanji_unpack_state(_MSKanjiEncodingInfo * __restrict ei __unused,
+ _MSKanjiState * __restrict s, const void * __restrict pspriv)
+{
+
+ memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_MSKanji_mbrtowc_priv(_MSKanjiEncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s, size_t n,
+ _MSKanjiState * __restrict psenc, size_t * __restrict nresult)
+{
+ char *s0;
+ wchar_t wchar;
+ int chlenbak, len;
+
+ s0 = *s;
+
+ if (s0 == NULL) {
+ _citrus_MSKanji_init_state(ei, psenc);
+ *nresult = 0; /* state independent */
+ return (0);
+ }
+
+ chlenbak = psenc->chlen;
+
+ /* make sure we have the first byte in the buffer */
+ switch (psenc->chlen) {
+ case 0:
+ if (n < 1)
+ goto restart;
+ psenc->ch[0] = *s0++;
+ psenc->chlen = 1;
+ n--;
+ break;
+ case 1:
+ break;
+ default:
+ /* illegal state */
+ goto encoding_error;
+ }
+
+ len = _mskanji1(psenc->ch[0] & 0xff) ? 2 : 1;
+ while (psenc->chlen < len) {
+ if (n < 1)
+ goto restart;
+ psenc->ch[psenc->chlen] = *s0++;
+ psenc->chlen++;
+ n--;
+ }
+
+ *s = s0;
+
+ switch (len) {
+ case 1:
+ wchar = psenc->ch[0] & 0xff;
+ break;
+ case 2:
+ if (!_mskanji2(psenc->ch[1] & 0xff))
+ goto encoding_error;
+ wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff);
+ break;
+ default:
+ /* illegal state */
+ goto encoding_error;
+ }
+
+ psenc->chlen = 0;
+
+ if (pwc)
+ *pwc = wchar;
+ *nresult = wchar ? len - chlenbak : 0;
+ return (0);
+
+encoding_error:
+ psenc->chlen = 0;
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+
+restart:
+ *nresult = (size_t)-2;
+ *s = s0;
+ return (0);
+}
+
+
+static int
+_citrus_MSKanji_wcrtomb_priv(_MSKanjiEncodingInfo * __restrict ei __unused,
+ char * __restrict s, size_t n, wchar_t wc,
+ _MSKanjiState * __restrict psenc __unused, size_t * __restrict nresult)
+{
+ int ret;
+
+ /* check invalid sequence */
+ if (wc & ~0xffff) {
+ ret = EILSEQ;
+ goto err;
+ }
+
+ if (wc & 0xff00) {
+ if (n < 2) {
+ ret = E2BIG;
+ goto err;
+ }
+
+ s[0] = (wc >> 8) & 0xff;
+ s[1] = wc & 0xff;
+ if (!_mskanji1(s[0] & 0xff) || !_mskanji2(s[1] & 0xff)) {
+ ret = EILSEQ;
+ goto err;
+ }
+
+ *nresult = 2;
+ return (0);
+ } else {
+ if (n < 1) {
+ ret = E2BIG;
+ goto err;
+ }
+
+ s[0] = wc & 0xff;
+ if (_mskanji1(s[0] & 0xff)) {
+ ret = EILSEQ;
+ goto err;
+ }
+
+ *nresult = 1;
+ return (0);
+ }
+
+err:
+ *nresult = (size_t)-1;
+ return (ret);
+}
+
+
+static __inline int
+/*ARGSUSED*/
+_citrus_MSKanji_stdenc_wctocs(_MSKanjiEncodingInfo * __restrict ei,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+ _index_t col, row;
+ int offset;
+
+ if ((_wc_t)wc < 0x80) {
+ /* ISO-646 */
+ *csid = 0;
+ *idx = (_index_t)wc;
+ } else if ((_wc_t)wc < 0x100) {
+ /* KANA */
+ *csid = 1;
+ *idx = (_index_t)wc & 0x7F;
+ } else {
+ /* Kanji (containing Gaiji zone) */
+ /*
+ * 94^2 zone (contains a part of Gaiji (0xED40 - 0xEEFC)):
+ * 0x8140 - 0x817E -> 0x2121 - 0x215F
+ * 0x8180 - 0x819E -> 0x2160 - 0x217E
+ * 0x819F - 0x81FC -> 0x2221 - 0x227E
+ *
+ * 0x8240 - 0x827E -> 0x2321 - 0x235F
+ * ...
+ * 0x9F9F - 0x9FFc -> 0x5E21 - 0x5E7E
+ *
+ * 0xE040 - 0xE07E -> 0x5F21 - 0x5F5F
+ * ...
+ * 0xEF9F - 0xEFFC -> 0x7E21 - 0x7E7E
+ *
+ * extended Gaiji zone:
+ * 0xF040 - 0xFCFC
+ *
+ * JIS X0213-plane2:
+ * 0xF040 - 0xF09E -> 0x2121 - 0x217E
+ * 0xF140 - 0xF19E -> 0x2321 - 0x237E
+ * ...
+ * 0xF240 - 0xF29E -> 0x2521 - 0x257E
+ *
+ * 0xF09F - 0xF0FC -> 0x2821 - 0x287E
+ * 0xF29F - 0xF2FC -> 0x2C21 - 0x2C7E
+ * ...
+ * 0xF44F - 0xF49E -> 0x2F21 - 0x2F7E
+ *
+ * 0xF49F - 0xF4FC -> 0x6E21 - 0x6E7E
+ * ...
+ * 0xFC9F - 0xFCFC -> 0x7E21 - 0x7E7E
+ */
+ row = ((_wc_t)wc >> 8) & 0xFF;
+ col = (_wc_t)wc & 0xFF;
+ if (!_mskanji1(row) || !_mskanji2(col))
+ return (EILSEQ);
+ if ((ei->mode & MODE_JIS2004) == 0 || row < 0xF0) {
+ *csid = 2;
+ offset = 0x81;
+ } else {
+ *csid = 3;
+ if ((_wc_t)wc <= 0xF49E) {
+ offset = (_wc_t)wc >= 0xF29F ||
+ ((_wc_t)wc >= 0xF09F &&
+ (_wc_t)wc <= 0xF0FC) ? 0xED : 0xF0;
+ } else
+ offset = 0xCE;
+ }
+ row -= offset;
+ if (row >= 0x5F)
+ row -= 0x40;
+ row = row * 2 + 0x21;
+ col -= 0x1F;
+ if (col >= 0x61)
+ col -= 1;
+ if (col > 0x7E) {
+ row += 1;
+ col -= 0x5E;
+ }
+ *idx = ((_index_t)row << 8) | col;
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_MSKanji_stdenc_cstowc(_MSKanjiEncodingInfo * __restrict ei,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+ uint32_t col, row;
+ int offset;
+
+ switch (csid) {
+ case 0:
+ /* ISO-646 */
+ if (idx >= 0x80)
+ return (EILSEQ);
+ *wc = (wchar_t)idx;
+ break;
+ case 1:
+ /* kana */
+ if (idx >= 0x80)
+ return (EILSEQ);
+ *wc = (wchar_t)idx + 0x80;
+ break;
+ case 3:
+ if ((ei->mode & MODE_JIS2004) == 0)
+ return (EILSEQ);
+ /*FALLTHROUGH*/
+ case 2:
+ /* kanji */
+ row = (idx >> 8);
+ if (row < 0x21)
+ return (EILSEQ);
+ if (csid == 3) {
+ if (row <= 0x2F)
+ offset = (row == 0x22 || row >= 0x26) ?
+ 0xED : 0xF0;
+ else if (row >= 0x4D && row <= 0x7E)
+ offset = 0xCE;
+ else
+ return (EILSEQ);
+ } else {
+ if (row > 0x97)
+ return (EILSEQ);
+ offset = (row < 0x5F) ? 0x81 : 0xC1;
+ }
+ col = idx & 0xFF;
+ if (col < 0x21 || col > 0x7E)
+ return (EILSEQ);
+ row -= 0x21; col -= 0x21;
+ if ((row & 1) == 0) {
+ col += 0x40;
+ if (col >= 0x7F)
+ col += 1;
+ } else
+ col += 0x9F;
+ row = row / 2 + offset;
+ *wc = ((wchar_t)row << 8) | col;
+ break;
+ default:
+ return (EILSEQ);
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_MSKanji_stdenc_get_state_desc_generic(_MSKanjiEncodingInfo * __restrict ei __unused,
+ _MSKanjiState * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_MSKanji_encoding_module_init(_MSKanjiEncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar)
+{
+ const char *p;
+
+ p = var;
+ memset((void *)ei, 0, sizeof(*ei));
+ while (lenvar > 0) {
+ switch (_bcs_toupper(*p)) {
+ case 'J':
+ MATCH(JIS2004, ei->mode |= MODE_JIS2004);
+ break;
+ }
+ ++p;
+ --lenvar;
+ }
+
+ return (0);
+}
+
+static void
+_citrus_MSKanji_encoding_module_uninit(_MSKanjiEncodingInfo *ei __unused)
+{
+
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(MSKanji);
+_CITRUS_STDENC_DEF_OPS(MSKanji);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/MSKanji/citrus_mskanji.h b/lib/libiconv_modules/MSKanji/citrus_mskanji.h
new file mode 100644
index 0000000..3dc3852
--- /dev/null
+++ b/lib/libiconv_modules/MSKanji/citrus_mskanji.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mskanji.h,v 1.2 2003/06/25 09:51:48 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MSKANJI_H_
+#define _CITRUS_MSKANJI_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(MSKanji);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/Makefile b/lib/libiconv_modules/Makefile
new file mode 100644
index 0000000..1a72136
--- /dev/null
+++ b/lib/libiconv_modules/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+SUBDIR= BIG5 DECHanyu EUC EUCTW GBK2K HZ ISO2022 JOHAB MSKanji UES UTF1632 \
+ UTF7 UTF8 VIQR ZW iconv_none iconv_std mapper_646 mapper_none \
+ mapper_parallel mapper_serial mapper_std mapper_zone
+
+.include <bsd.subdir.mk>
diff --git a/lib/libiconv_modules/Makefile.inc b/lib/libiconv_modules/Makefile.inc
new file mode 100644
index 0000000..9949390
--- /dev/null
+++ b/lib/libiconv_modules/Makefile.inc
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../libc/iconv
+
+SHLIB_MAJOR= 4
+WARNS?= 6
+CFLAGS+= -I${.CURDIR}/../../libc/iconv
+.if !defined(COMPAT_32BIT)
+SHLIBDIR= /usr/lib/i18n
+.else
+SHLIBDIR= /usr/lib32/i18n
+.endif
+LIBDIR= ${SHLIBDIR}
+NO_PROFILE=
diff --git a/lib/libiconv_modules/UES/Makefile b/lib/libiconv_modules/UES/Makefile
new file mode 100644
index 0000000..972e496
--- /dev/null
+++ b/lib/libiconv_modules/UES/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= UES
+SRCS+= citrus_ues.c
+CFLAGS+= --param max-inline-insns-single=64
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/UES/citrus_ues.c b/lib/libiconv_modules/UES/citrus_ues.c
new file mode 100644
index 0000000..1c4bc83
--- /dev/null
+++ b/lib/libiconv_modules/UES/citrus_ues.c
@@ -0,0 +1,412 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_ues.c,v 1.1 2006/11/13 15:16:31 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_ues.h"
+
+typedef struct {
+ size_t mb_cur_max;
+ int mode;
+#define MODE_C99 1
+} _UESEncodingInfo;
+
+typedef struct {
+ int chlen;
+ char ch[12];
+} _UESState;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_UES_##m
+#define _ENCODING_INFO _UESEncodingInfo
+#define _ENCODING_STATE _UESState
+#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UES_init_state(_UESEncodingInfo * __restrict ei __unused,
+ _UESState * __restrict psenc)
+{
+
+ psenc->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UES_pack_state(_UESEncodingInfo * __restrict ei __unused,
+ void *__restrict pspriv, const _UESState * __restrict psenc)
+{
+
+ memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UES_unpack_state(_UESEncodingInfo * __restrict ei __unused,
+ _UESState * __restrict psenc, const void * __restrict pspriv)
+{
+
+ memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static __inline int
+to_int(int ch)
+{
+
+ if (ch >= '0' && ch <= '9')
+ return (ch - '0');
+ else if (ch >= 'A' && ch <= 'F')
+ return ((ch - 'A') + 10);
+ else if (ch >= 'a' && ch <= 'f')
+ return ((ch - 'a') + 10);
+ return (-1);
+}
+
+#define ESCAPE '\\'
+#define UCS2_ESC 'u'
+#define UCS4_ESC 'U'
+
+#define UCS2_BIT 16
+#define UCS4_BIT 32
+#define BMP_MAX UINT32_C(0xFFFF)
+#define UCS2_MAX UINT32_C(0x10FFFF)
+#define UCS4_MAX UINT32_C(0x7FFFFFFF)
+
+static const char *xdig = "0123456789abcdef";
+
+static __inline int
+to_str(char *s, wchar_t wc, int bit)
+{
+ char *p;
+
+ p = s;
+ *p++ = ESCAPE;
+ switch (bit) {
+ case UCS2_BIT:
+ *p++ = UCS2_ESC;
+ break;
+ case UCS4_BIT:
+ *p++ = UCS4_ESC;
+ break;
+ default:
+ abort();
+ }
+ do {
+ *p++ = xdig[(wc >> (bit -= 4)) & 0xF];
+ } while (bit > 0);
+ return (p - s);
+}
+
+static __inline bool
+is_hi_surrogate(wchar_t wc)
+{
+
+ return (wc >= 0xD800 && wc <= 0xDBFF);
+}
+
+static __inline bool
+is_lo_surrogate(wchar_t wc)
+{
+
+ return (wc >= 0xDC00 && wc <= 0xDFFF);
+}
+
+static __inline wchar_t
+surrogate_to_ucs(wchar_t hi, wchar_t lo)
+{
+
+ hi -= 0xD800;
+ lo -= 0xDC00;
+ return ((hi << 10 | lo) + 0x10000);
+}
+
+static __inline void
+ucs_to_surrogate(wchar_t wc, wchar_t * __restrict hi, wchar_t * __restrict lo)
+{
+
+ wc -= 0x10000;
+ *hi = (wc >> 10) + 0xD800;
+ *lo = (wc & 0x3FF) + 0xDC00;
+}
+
+static __inline bool
+is_basic(wchar_t wc)
+{
+
+ return ((uint32_t)wc <= 0x9F && wc != 0x24 && wc != 0x40 &&
+ wc != 0x60);
+}
+
+static int
+_citrus_UES_mbrtowc_priv(_UESEncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s, size_t n,
+ _UESState * __restrict psenc, size_t * __restrict nresult)
+{
+ char *s0;
+ int ch, head, num, tail;
+ wchar_t hi, wc;
+
+ if (*s == NULL) {
+ _citrus_UES_init_state(ei, psenc);
+ *nresult = 0;
+ return (0);
+ }
+ s0 = *s;
+
+ hi = (wchar_t)0;
+ tail = 0;
+
+surrogate:
+ wc = (wchar_t)0;
+ head = tail;
+ if (psenc->chlen == head) {
+ if (n-- < 1)
+ goto restart;
+ psenc->ch[psenc->chlen++] = *s0++;
+ }
+ ch = (unsigned char)psenc->ch[head++];
+ if (ch == ESCAPE) {
+ if (psenc->chlen == head) {
+ if (n-- < 1)
+ goto restart;
+ psenc->ch[psenc->chlen++] = *s0++;
+ }
+ switch (psenc->ch[head]) {
+ case UCS2_ESC:
+ tail += 6;
+ break;
+ case UCS4_ESC:
+ if (ei->mode & MODE_C99) {
+ tail = 10;
+ break;
+ }
+ /*FALLTHROUGH*/
+ default:
+ tail = 0;
+ }
+ ++head;
+ }
+ for (; head < tail; ++head) {
+ if (psenc->chlen == head) {
+ if (n-- < 1) {
+restart:
+ *s = s0;
+ *nresult = (size_t)-2;
+ return (0);
+ }
+ psenc->ch[psenc->chlen++] = *s0++;
+ }
+ num = to_int((int)(unsigned char)psenc->ch[head]);
+ if (num < 0) {
+ tail = 0;
+ break;
+ }
+ wc = (wc << 4) | num;
+ }
+ head = 0;
+ switch (tail) {
+ case 0:
+ break;
+ case 6:
+ if (hi != (wchar_t)0)
+ break;
+ if ((ei->mode & MODE_C99) == 0) {
+ if (is_hi_surrogate(wc) != 0) {
+ hi = wc;
+ goto surrogate;
+ }
+ if ((uint32_t)wc <= 0x7F /* XXX */ ||
+ is_lo_surrogate(wc) != 0)
+ break;
+ goto done;
+ }
+ /*FALLTHROUGH*/
+ case 10:
+ if (is_basic(wc) == 0 && (uint32_t)wc <= UCS4_MAX &&
+ is_hi_surrogate(wc) == 0 && is_lo_surrogate(wc) == 0)
+ goto done;
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ case 12:
+ if (is_lo_surrogate(wc) == 0)
+ break;
+ wc = surrogate_to_ucs(hi, wc);
+ goto done;
+ }
+ ch = (unsigned char)psenc->ch[0];
+ head = psenc->chlen;
+ if (--head > 0)
+ memmove(&psenc->ch[0], &psenc->ch[1], head);
+ wc = (wchar_t)ch;
+done:
+ psenc->chlen = head;
+ if (pwc != NULL)
+ *pwc = wc;
+ *nresult = (size_t)((wc == 0) ? 0 : (s0 - *s));
+ *s = s0;
+
+ return (0);
+}
+
+static int
+_citrus_UES_wcrtomb_priv(_UESEncodingInfo * __restrict ei,
+ char * __restrict s, size_t n, wchar_t wc,
+ _UESState * __restrict psenc, size_t * __restrict nresult)
+{
+ wchar_t hi, lo;
+
+ if (psenc->chlen != 0)
+ return (EINVAL);
+
+ if ((ei->mode & MODE_C99) ? is_basic(wc) : (uint32_t)wc <= 0x7F) {
+ if (n-- < 1)
+ goto e2big;
+ psenc->ch[psenc->chlen++] = (char)wc;
+ } else if ((uint32_t)wc <= BMP_MAX) {
+ if (n < 6)
+ goto e2big;
+ psenc->chlen = to_str(&psenc->ch[0], wc, UCS2_BIT);
+ } else if ((ei->mode & MODE_C99) == 0 && (uint32_t)wc <= UCS2_MAX) {
+ if (n < 12)
+ goto e2big;
+ ucs_to_surrogate(wc, &hi, &lo);
+ psenc->chlen += to_str(&psenc->ch[0], hi, UCS2_BIT);
+ psenc->chlen += to_str(&psenc->ch[6], lo, UCS2_BIT);
+ } else if ((ei->mode & MODE_C99) && (uint32_t)wc <= UCS4_MAX) {
+ if (n < 10)
+ goto e2big;
+ psenc->chlen = to_str(&psenc->ch[0], wc, UCS4_BIT);
+ } else {
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ }
+ memcpy(s, psenc->ch, psenc->chlen);
+ *nresult = psenc->chlen;
+ psenc->chlen = 0;
+
+ return (0);
+
+e2big:
+ *nresult = (size_t)-1;
+ return (E2BIG);
+}
+
+/*ARGSUSED*/
+static int
+_citrus_UES_stdenc_wctocs(_UESEncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+
+ *csid = 0;
+ *idx = (_index_t)wc;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UES_stdenc_cstowc(_UESEncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ if (csid != 0)
+ return (EILSEQ);
+ *wc = (wchar_t)idx;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UES_stdenc_get_state_desc_generic(_UESEncodingInfo * __restrict ei __unused,
+ _UESState * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_UES_encoding_module_uninit(_UESEncodingInfo *ei __unused)
+{
+
+ /* ei seems to be unused */
+}
+
+static int
+/*ARGSUSED*/
+_citrus_UES_encoding_module_init(_UESEncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar)
+{
+ const char *p;
+
+ p = var;
+ memset((void *)ei, 0, sizeof(*ei));
+ while (lenvar > 0) {
+ switch (_bcs_toupper(*p)) {
+ case 'C':
+ MATCH(C99, ei->mode |= MODE_C99);
+ break;
+ }
+ ++p;
+ --lenvar;
+ }
+ ei->mb_cur_max = (ei->mode & MODE_C99) ? 10 : 12;
+
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(UES);
+_CITRUS_STDENC_DEF_OPS(UES);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/UES/citrus_ues.h b/lib/libiconv_modules/UES/citrus_ues.h
new file mode 100644
index 0000000..7198cdf
--- /dev/null
+++ b/lib/libiconv_modules/UES/citrus_ues.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_ues.h,v 1.1 2006/11/13 15:16:31 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_UES_H_
+#define _CITRUS_UES_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(UES);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/UTF1632/Makefile b/lib/libiconv_modules/UTF1632/Makefile
new file mode 100644
index 0000000..71e9f88
--- /dev/null
+++ b/lib/libiconv_modules/UTF1632/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= UTF1632
+SRCS+= citrus_utf1632.c
+CFLAGS+= --param max-inline-insns-single=32
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/UTF1632/citrus_utf1632.c b/lib/libiconv_modules/UTF1632/citrus_utf1632.c
new file mode 100644
index 0000000..6682ab2
--- /dev/null
+++ b/lib/libiconv_modules/UTF1632/citrus_utf1632.c
@@ -0,0 +1,453 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_utf1632.c,v 1.9 2008/06/14 16:01:08 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/endian.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.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_stdenc.h"
+#include "citrus_bcs.h"
+
+#include "citrus_utf1632.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+ int chlen;
+ int current_endian;
+ uint8_t ch[4];
+} _UTF1632State;
+
+#define _ENDIAN_UNKNOWN 0
+#define _ENDIAN_BIG 1
+#define _ENDIAN_LITTLE 2
+#if BYTE_ORDER == BIG_ENDIAN
+#define _ENDIAN_INTERNAL _ENDIAN_BIG
+#define _ENDIAN_SWAPPED _ENDIAN_LITTLE
+#else
+#define _ENDIAN_INTERNAL _ENDIAN_LITTLE
+#define _ENDIAN_SWAPPED _ENDIAN_BIG
+#endif
+#define _MODE_UTF32 0x00000001U
+#define _MODE_FORCE_ENDIAN 0x00000002U
+
+typedef struct {
+ int preffered_endian;
+ unsigned int cur_max;
+ uint32_t mode;
+} _UTF1632EncodingInfo;
+
+#define _FUNCNAME(m) _citrus_UTF1632_##m
+#define _ENCODING_INFO _UTF1632EncodingInfo
+#define _ENCODING_STATE _UTF1632State
+#define _ENCODING_MB_CUR_MAX(_ei_) ((_ei_)->cur_max)
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF1632_init_state(_UTF1632EncodingInfo *ei __unused,
+ _UTF1632State *s)
+{
+
+ memset(s, 0, sizeof(*s));
+}
+
+static int
+_citrus_UTF1632_mbrtowc_priv(_UTF1632EncodingInfo *ei, wchar_t *pwc,
+ char **s, size_t n, _UTF1632State *psenc, size_t *nresult)
+{
+ char *s0;
+ size_t result;
+ wchar_t wc = L'\0';
+ int chlenbak, endian, needlen;
+
+ s0 = *s;
+
+ if (s0 == NULL) {
+ _citrus_UTF1632_init_state(ei, psenc);
+ *nresult = 0; /* state independent */
+ return (0);
+ }
+
+ result = 0;
+ chlenbak = psenc->chlen;
+
+refetch:
+ needlen = ((ei->mode & _MODE_UTF32) != 0 || chlenbak >= 2) ? 4 : 2;
+
+ while (chlenbak < needlen) {
+ if (n == 0)
+ goto restart;
+ psenc->ch[chlenbak++] = *s0++;
+ n--;
+ result++;
+ }
+
+ /* judge endian marker */
+ if ((ei->mode & _MODE_UTF32) == 0) {
+ /* UTF16 */
+ if (psenc->ch[0] == 0xFE && psenc->ch[1] == 0xFF) {
+ psenc->current_endian = _ENDIAN_BIG;
+ chlenbak = 0;
+ goto refetch;
+ } else if (psenc->ch[0] == 0xFF && psenc->ch[1] == 0xFE) {
+ psenc->current_endian = _ENDIAN_LITTLE;
+ chlenbak = 0;
+ goto refetch;
+ }
+ } else {
+ /* UTF32 */
+ if (psenc->ch[0] == 0x00 && psenc->ch[1] == 0x00 &&
+ psenc->ch[2] == 0xFE && psenc->ch[3] == 0xFF) {
+ psenc->current_endian = _ENDIAN_BIG;
+ chlenbak = 0;
+ goto refetch;
+ } else if (psenc->ch[0] == 0xFF && psenc->ch[1] == 0xFE &&
+ psenc->ch[2] == 0x00 && psenc->ch[3] == 0x00) {
+ psenc->current_endian = _ENDIAN_LITTLE;
+ chlenbak = 0;
+ goto refetch;
+ }
+ }
+ endian = ((ei->mode & _MODE_FORCE_ENDIAN) != 0 ||
+ psenc->current_endian == _ENDIAN_UNKNOWN) ? ei->preffered_endian :
+ psenc->current_endian;
+
+ /* get wc */
+ if ((ei->mode & _MODE_UTF32) == 0) {
+ /* UTF16 */
+ if (needlen == 2) {
+ switch (endian) {
+ case _ENDIAN_LITTLE:
+ wc = (psenc->ch[0] |
+ ((wchar_t)psenc->ch[1] << 8));
+ break;
+ case _ENDIAN_BIG:
+ wc = (psenc->ch[1] |
+ ((wchar_t)psenc->ch[0] << 8));
+ break;
+ default:
+ goto ilseq;
+ }
+ if (wc >= 0xD800 && wc <= 0xDBFF) {
+ /* surrogate high */
+ needlen = 4;
+ goto refetch;
+ }
+ } else {
+ /* surrogate low */
+ wc -= 0xD800; /* wc : surrogate high (see above) */
+ wc <<= 10;
+ switch (endian) {
+ case _ENDIAN_LITTLE:
+ if (psenc->ch[3] < 0xDC || psenc->ch[3] > 0xDF)
+ goto ilseq;
+ wc |= psenc->ch[2];
+ wc |= (wchar_t)(psenc->ch[3] & 3) << 8;
+ break;
+ case _ENDIAN_BIG:
+ if (psenc->ch[2]<0xDC || psenc->ch[2]>0xDF)
+ goto ilseq;
+ wc |= psenc->ch[3];
+ wc |= (wchar_t)(psenc->ch[2] & 3) << 8;
+ break;
+ default:
+ goto ilseq;
+ }
+ wc += 0x10000;
+ }
+ } else {
+ /* UTF32 */
+ switch (endian) {
+ case _ENDIAN_LITTLE:
+ wc = (psenc->ch[0] |
+ ((wchar_t)psenc->ch[1] << 8) |
+ ((wchar_t)psenc->ch[2] << 16) |
+ ((wchar_t)psenc->ch[3] << 24));
+ break;
+ case _ENDIAN_BIG:
+ wc = (psenc->ch[3] |
+ ((wchar_t)psenc->ch[2] << 8) |
+ ((wchar_t)psenc->ch[1] << 16) |
+ ((wchar_t)psenc->ch[0] << 24));
+ break;
+ default:
+ goto ilseq;
+ }
+ if (wc >= 0xD800 && wc <= 0xDFFF)
+ goto ilseq;
+ }
+
+
+ *pwc = wc;
+ psenc->chlen = 0;
+ *nresult = result;
+ *s = s0;
+
+ return (0);
+
+ilseq:
+ *nresult = (size_t)-1;
+ psenc->chlen = 0;
+ return (EILSEQ);
+
+restart:
+ *nresult = (size_t)-2;
+ psenc->chlen = chlenbak;
+ *s = s0;
+ return (0);
+}
+
+static int
+_citrus_UTF1632_wcrtomb_priv(_UTF1632EncodingInfo *ei, char *s, size_t n,
+ wchar_t wc, _UTF1632State *psenc, size_t *nresult)
+{
+ wchar_t wc2;
+ static const char _bom[4] = {
+ 0x00, 0x00, 0xFE, 0xFF,
+ };
+ const char *bom = &_bom[0];
+ size_t cnt;
+
+ cnt = (size_t)0;
+ if (psenc->current_endian == _ENDIAN_UNKNOWN) {
+ if ((ei->mode & _MODE_FORCE_ENDIAN) == 0) {
+ if (ei->mode & _MODE_UTF32)
+ cnt = 4;
+ else {
+ cnt = 2;
+ bom += 2;
+ }
+ if (n < cnt)
+ goto e2big;
+ memcpy(s, bom, cnt);
+ s += cnt, n -= cnt;
+ }
+ psenc->current_endian = ei->preffered_endian;
+ }
+
+ wc2 = 0;
+ if ((ei->mode & _MODE_UTF32)==0) {
+ /* UTF16 */
+ if (wc > 0xFFFF) {
+ /* surrogate */
+ if (wc > 0x10FFFF)
+ goto ilseq;
+ if (n < 4)
+ goto e2big;
+ cnt += 4;
+ wc -= 0x10000;
+ wc2 = (wc & 0x3FF) | 0xDC00;
+ wc = (wc>>10) | 0xD800;
+ } else {
+ if (n < 2)
+ goto e2big;
+ cnt += 2;
+ }
+
+surrogate:
+ switch (psenc->current_endian) {
+ case _ENDIAN_BIG:
+ s[1] = wc;
+ s[0] = (wc >>= 8);
+ break;
+ case _ENDIAN_LITTLE:
+ s[0] = wc;
+ s[1] = (wc >>= 8);
+ break;
+ }
+ if (wc2 != 0) {
+ wc = wc2;
+ wc2 = 0;
+ s += 2;
+ goto surrogate;
+ }
+ } else {
+ /* UTF32 */
+ if (wc >= 0xD800 && wc <= 0xDFFF)
+ goto ilseq;
+ if (n < 4)
+ goto e2big;
+ cnt += 4;
+ switch (psenc->current_endian) {
+ case _ENDIAN_BIG:
+ s[3] = wc;
+ s[2] = (wc >>= 8);
+ s[1] = (wc >>= 8);
+ s[0] = (wc >>= 8);
+ break;
+ case _ENDIAN_LITTLE:
+ s[0] = wc;
+ s[1] = (wc >>= 8);
+ s[2] = (wc >>= 8);
+ s[3] = (wc >>= 8);
+ break;
+ }
+ }
+ *nresult = cnt;
+
+ return (0);
+
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+e2big:
+ *nresult = (size_t)-1;
+ return (E2BIG);
+}
+
+static void
+parse_variable(_UTF1632EncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar)
+{
+ const char *p;
+
+ p = var;
+ while (lenvar > 0) {
+ switch (*p) {
+ case 'B':
+ case 'b':
+ MATCH(big, ei->preffered_endian = _ENDIAN_BIG);
+ break;
+ case 'L':
+ case 'l':
+ MATCH(little, ei->preffered_endian = _ENDIAN_LITTLE);
+ break;
+ case 'i':
+ case 'I':
+ MATCH(internal, ei->preffered_endian = _ENDIAN_INTERNAL);
+ break;
+ case 's':
+ case 'S':
+ MATCH(swapped, ei->preffered_endian = _ENDIAN_SWAPPED);
+ break;
+ case 'F':
+ case 'f':
+ MATCH(force, ei->mode |= _MODE_FORCE_ENDIAN);
+ break;
+ case 'U':
+ case 'u':
+ MATCH(utf32, ei->mode |= _MODE_UTF32);
+ break;
+ }
+ p++;
+ lenvar--;
+ }
+}
+
+static int
+/*ARGSUSED*/
+_citrus_UTF1632_encoding_module_init(_UTF1632EncodingInfo * __restrict ei,
+ const void * __restrict var, size_t lenvar)
+{
+
+ memset((void *)ei, 0, sizeof(*ei));
+
+ parse_variable(ei, var, lenvar);
+
+ ei->cur_max = ((ei->mode&_MODE_UTF32) == 0) ? 6 : 8;
+ /* 6: endian + surrogate */
+ /* 8: endian + normal */
+
+ if (ei->preffered_endian == _ENDIAN_UNKNOWN) {
+ ei->preffered_endian = _ENDIAN_BIG;
+ }
+
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_UTF1632_encoding_module_uninit(_UTF1632EncodingInfo *ei __unused)
+{
+
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF1632_stdenc_wctocs(_UTF1632EncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, _wc_t wc)
+{
+
+ *csid = 0;
+ *idx = (_index_t)wc;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF1632_stdenc_cstowc(_UTF1632EncodingInfo * __restrict ei __unused,
+ _wc_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ if (csid != 0)
+ return (EILSEQ);
+
+ *wc = (_wc_t)idx;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF1632_stdenc_get_state_desc_generic(_UTF1632EncodingInfo * __restrict ei __unused,
+ _UTF1632State * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(UTF1632);
+_CITRUS_STDENC_DEF_OPS(UTF1632);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/UTF1632/citrus_utf1632.h b/lib/libiconv_modules/UTF1632/citrus_utf1632.h
new file mode 100644
index 0000000..8ee7ada
--- /dev/null
+++ b/lib/libiconv_modules/UTF1632/citrus_utf1632.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_utf1632.h,v 1.1 2003/06/25 09:51:49 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_UTF1632_H_
+#define _CITRUS_UTF1632_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(UTF1632);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/UTF7/Makefile b/lib/libiconv_modules/UTF7/Makefile
new file mode 100644
index 0000000..8bedb73
--- /dev/null
+++ b/lib/libiconv_modules/UTF7/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= UTF7
+SRCS+= citrus_utf7.c
+CFLAGS+= --param max-inline-insns-single=32
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/UTF7/citrus_utf7.c b/lib/libiconv_modules/UTF7/citrus_utf7.c
new file mode 100644
index 0000000..e99f980
--- /dev/null
+++ b/lib/libiconv_modules/UTF7/citrus_utf7.c
@@ -0,0 +1,499 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_utf7.c,v 1.5 2006/08/23 12:57:24 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004, 2005 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_utf7.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+#define EI_MASK UINT16_C(0xff)
+#define EI_DIRECT UINT16_C(0x100)
+#define EI_OPTION UINT16_C(0x200)
+#define EI_SPACE UINT16_C(0x400)
+
+typedef struct {
+ uint16_t cell[0x80];
+} _UTF7EncodingInfo;
+
+typedef struct {
+ unsigned int
+ mode: 1, /* whether base64 mode */
+ bits: 4, /* need to hold 0 - 15 */
+ cache: 22, /* 22 = BASE64_BIT + UTF16_BIT */
+ surrogate: 1; /* whether surrogate pair or not */
+ int chlen;
+ char ch[4]; /* BASE64_IN, 3 * 6 = 18, most closed to UTF16_BIT */
+} _UTF7State;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_UTF7_##m
+#define _ENCODING_INFO _UTF7EncodingInfo
+#define _ENCODING_STATE _UTF7State
+#define _ENCODING_MB_CUR_MAX(_ei_) 4
+#define _ENCODING_IS_STATE_DEPENDENT 1
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF7_init_state(_UTF7EncodingInfo * __restrict ei __unused,
+ _UTF7State * __restrict s)
+{
+
+ memset((void *)s, 0, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF7_pack_state(_UTF7EncodingInfo * __restrict ei __unused,
+ void *__restrict pspriv, const _UTF7State * __restrict s)
+{
+
+ memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF7_unpack_state(_UTF7EncodingInfo * __restrict ei __unused,
+ _UTF7State * __restrict s, const void * __restrict pspriv)
+{
+
+ memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static const char base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+static const char direct[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789(),-./:?";
+
+static const char option[] = "!\"#$%&';<=>@[]^_`{|}";
+static const char spaces[] = " \t\r\n";
+
+#define BASE64_BIT 6
+#define UTF16_BIT 16
+
+#define BASE64_MAX 0x3f
+#define UTF16_MAX UINT16_C(0xffff)
+#define UTF32_MAX UINT32_C(0x10ffff)
+
+#define BASE64_IN '+'
+#define BASE64_OUT '-'
+
+#define SHIFT7BIT(c) ((c) >> 7)
+#define ISSPECIAL(c) ((c) == '\0' || (c) == BASE64_IN)
+
+#define FINDLEN(ei, c) \
+ (SHIFT7BIT((c)) ? -1 : (((ei)->cell[(c)] & EI_MASK) - 1))
+
+#define ISDIRECT(ei, c) (!SHIFT7BIT((c)) && (ISSPECIAL((c)) || \
+ ei->cell[(c)] & (EI_DIRECT | EI_OPTION | EI_SPACE)))
+
+#define ISSAFE(ei, c) (!SHIFT7BIT((c)) && (ISSPECIAL((c)) || \
+ (c < 0x80 && ei->cell[(c)] & (EI_DIRECT | EI_SPACE))))
+
+/* surrogate pair */
+#define SRG_BASE UINT32_C(0x10000)
+#define HISRG_MIN UINT16_C(0xd800)
+#define HISRG_MAX UINT16_C(0xdbff)
+#define LOSRG_MIN UINT16_C(0xdc00)
+#define LOSRG_MAX UINT16_C(0xdfff)
+
+static int
+_citrus_UTF7_mbtoutf16(_UTF7EncodingInfo * __restrict ei,
+ uint16_t * __restrict u16, char ** __restrict s, size_t n,
+ _UTF7State * __restrict psenc, size_t * __restrict nresult)
+{
+ _UTF7State sv;
+ char *s0;
+ int done, i, len;
+
+ s0 = *s;
+ sv = *psenc;
+
+ for (i = 0, done = 0; done == 0; i++) {
+ if (i == psenc->chlen) {
+ if (n-- < 1) {
+ *nresult = (size_t)-2;
+ *s = s0;
+ sv.chlen = psenc->chlen;
+ *psenc = sv;
+ return (0);
+ }
+ psenc->ch[psenc->chlen++] = *s0++;
+ }
+ if (SHIFT7BIT((int)psenc->ch[i]))
+ goto ilseq;
+ if (!psenc->mode) {
+ if (psenc->bits > 0 || psenc->cache > 0)
+ return (EINVAL);
+ if (psenc->ch[i] == BASE64_IN)
+ psenc->mode = 1;
+ else {
+ if (!ISDIRECT(ei, (int)psenc->ch[i]))
+ goto ilseq;
+ *u16 = (uint16_t)psenc->ch[i];
+ done = 1;
+ continue;
+ }
+ } else {
+ if (psenc->ch[i] == BASE64_OUT && psenc->cache == 0) {
+ psenc->mode = 0;
+ *u16 = (uint16_t)BASE64_IN;
+ done = 1;
+ continue;
+ }
+ len = FINDLEN(ei, (int)psenc->ch[i]);
+ if (len < 0) {
+ if (psenc->bits >= BASE64_BIT)
+ return (EINVAL);
+ psenc->mode = 0;
+ psenc->bits = psenc->cache = 0;
+ if (psenc->ch[i] != BASE64_OUT) {
+ if (!ISDIRECT(ei, (int)psenc->ch[i]))
+ goto ilseq;
+ *u16 = (uint16_t)psenc->ch[i];
+ done = 1;
+ }
+ } else {
+ psenc->cache =
+ (psenc->cache << BASE64_BIT) | len;
+ switch (psenc->bits) {
+ case 0: case 2: case 4: case 6: case 8:
+ psenc->bits += BASE64_BIT;
+ break;
+ case 10: case 12: case 14:
+ psenc->bits -= (UTF16_BIT - BASE64_BIT);
+ *u16 = (psenc->cache >> psenc->bits) &
+ UTF16_MAX;
+ done = 1;
+ break;
+ default:
+ return (EINVAL);
+ }
+ }
+ }
+ }
+
+ if (psenc->chlen > i)
+ return (EINVAL);
+ psenc->chlen = 0;
+ *nresult = (size_t)((*u16 == 0) ? 0 : s0 - *s);
+ *s = s0;
+
+ return (0);
+
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+}
+
+static int
+_citrus_UTF7_mbrtowc_priv(_UTF7EncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s, size_t n,
+ _UTF7State * __restrict psenc, size_t * __restrict nresult)
+{
+ char *s0;
+ uint32_t u32;
+ uint16_t hi, lo;
+ size_t nr, siz;
+ int err;
+
+ if (*s == NULL) {
+ _citrus_UTF7_init_state(ei, psenc);
+ *nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
+ return (0);
+ }
+ s0 = *s;
+ if (psenc->surrogate) {
+ hi = (psenc->cache >> 2) & UTF16_MAX;
+ if (hi < HISRG_MIN || hi > HISRG_MAX)
+ return (EINVAL);
+ siz = 0;
+ } else {
+ err = _citrus_UTF7_mbtoutf16(ei, &hi, &s0, n, psenc, &nr);
+ if (nr == (size_t)-1 || nr == (size_t)-2) {
+ *nresult = nr;
+ return (err);
+ }
+ if (err != 0)
+ return (err);
+ n -= nr;
+ siz = nr;
+ if (hi < HISRG_MIN || hi > HISRG_MAX) {
+ u32 = (uint32_t)hi;
+ goto done;
+ }
+ psenc->surrogate = 1;
+ }
+ err = _citrus_UTF7_mbtoutf16(ei, &lo, &s0, n, psenc, &nr);
+ if (nr == (size_t)-1 || nr == (size_t)-2) {
+ *nresult = nr;
+ return (err);
+ }
+ if (err != 0)
+ return (err);
+ hi -= HISRG_MIN;
+ lo -= LOSRG_MIN;
+ u32 = (hi << 10 | lo) + SRG_BASE;
+ siz += nr;
+done:
+ *s = s0;
+ if (pwc != NULL)
+ *pwc = (wchar_t)u32;
+ if (u32 == (uint32_t)0) {
+ *nresult = (size_t)0;
+ _citrus_UTF7_init_state(ei, psenc);
+ } else {
+ *nresult = siz;
+ psenc->surrogate = 0;
+ }
+ return (err);
+}
+
+static int
+_citrus_UTF7_utf16tomb(_UTF7EncodingInfo * __restrict ei,
+ char * __restrict s, size_t n __unused, uint16_t u16,
+ _UTF7State * __restrict psenc, size_t * __restrict nresult)
+{
+ int bits, i;
+
+ if (psenc->chlen != 0 || psenc->bits > BASE64_BIT)
+ return (EINVAL);
+
+ if (ISSAFE(ei, u16)) {
+ if (psenc->mode) {
+ if (psenc->bits > 0) {
+ bits = BASE64_BIT - psenc->bits;
+ i = (psenc->cache << bits) & BASE64_MAX;
+ psenc->ch[psenc->chlen++] = base64[i];
+ psenc->bits = psenc->cache = 0;
+ }
+ if (u16 == BASE64_OUT || FINDLEN(ei, u16) >= 0)
+ psenc->ch[psenc->chlen++] = BASE64_OUT;
+ psenc->mode = 0;
+ }
+ if (psenc->bits != 0)
+ return (EINVAL);
+ psenc->ch[psenc->chlen++] = (char)u16;
+ if (u16 == BASE64_IN)
+ psenc->ch[psenc->chlen++] = BASE64_OUT;
+ } else {
+ if (!psenc->mode) {
+ if (psenc->bits > 0)
+ return (EINVAL);
+ psenc->ch[psenc->chlen++] = BASE64_IN;
+ psenc->mode = 1;
+ }
+ psenc->cache = (psenc->cache << UTF16_BIT) | u16;
+ bits = UTF16_BIT + psenc->bits;
+ psenc->bits = bits % BASE64_BIT;
+ while ((bits -= BASE64_BIT) >= 0) {
+ i = (psenc->cache >> bits) & BASE64_MAX;
+ psenc->ch[psenc->chlen++] = base64[i];
+ }
+ }
+ memcpy(s, psenc->ch, psenc->chlen);
+ *nresult = psenc->chlen;
+ psenc->chlen = 0;
+
+ return (0);
+}
+
+static int
+_citrus_UTF7_wcrtomb_priv(_UTF7EncodingInfo * __restrict ei,
+ char * __restrict s, size_t n, wchar_t wchar,
+ _UTF7State * __restrict psenc, size_t * __restrict nresult)
+{
+ uint32_t u32;
+ uint16_t u16[2];
+ int err, i, len;
+ size_t nr, siz;
+
+ u32 = (uint32_t)wchar;
+ if (u32 <= UTF16_MAX) {
+ u16[0] = (uint16_t)u32;
+ len = 1;
+ } else if (u32 <= UTF32_MAX) {
+ u32 -= SRG_BASE;
+ u16[0] = (u32 >> 10) + HISRG_MIN;
+ u16[1] = ((uint16_t)(u32 & UINT32_C(0x3ff))) + LOSRG_MIN;
+ len = 2;
+ } else {
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ }
+ siz = 0;
+ for (i = 0; i < len; ++i) {
+ err = _citrus_UTF7_utf16tomb(ei, s, n, u16[i], psenc, &nr);
+ if (err != 0)
+ return (err); /* XXX: state has been modified */
+ s += nr;
+ n -= nr;
+ siz += nr;
+ }
+ *nresult = siz;
+
+ return (0);
+}
+
+static int
+/* ARGSUSED */
+_citrus_UTF7_put_state_reset(_UTF7EncodingInfo * __restrict ei __unused,
+ char * __restrict s, size_t n, _UTF7State * __restrict psenc,
+ size_t * __restrict nresult)
+{
+ int bits, pos;
+
+ if (psenc->chlen != 0 || psenc->bits > BASE64_BIT || psenc->surrogate)
+ return (EINVAL);
+
+ if (psenc->mode) {
+ if (psenc->bits > 0) {
+ if (n-- < 1)
+ return (E2BIG);
+ bits = BASE64_BIT - psenc->bits;
+ pos = (psenc->cache << bits) & BASE64_MAX;
+ psenc->ch[psenc->chlen++] = base64[pos];
+ psenc->ch[psenc->chlen++] = BASE64_OUT;
+ psenc->bits = psenc->cache = 0;
+ }
+ psenc->mode = 0;
+ }
+ if (psenc->bits != 0)
+ return (EINVAL);
+ if (n-- < 1)
+ return (E2BIG);
+
+ *nresult = (size_t)psenc->chlen;
+ if (psenc->chlen > 0) {
+ memcpy(s, psenc->ch, psenc->chlen);
+ psenc->chlen = 0;
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF7_stdenc_wctocs(_UTF7EncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+
+ *csid = 0;
+ *idx = (_index_t)wc;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF7_stdenc_cstowc(_UTF7EncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ if (csid != 0)
+ return (EILSEQ);
+ *wc = (wchar_t)idx;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF7_stdenc_get_state_desc_generic(_UTF7EncodingInfo * __restrict ei __unused,
+ _UTF7State * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_UTF7_encoding_module_uninit(_UTF7EncodingInfo *ei __unused)
+{
+
+ /* ei seems to be unused */
+}
+
+static int
+/*ARGSUSED*/
+_citrus_UTF7_encoding_module_init(_UTF7EncodingInfo * __restrict ei,
+ const void * __restrict var __unused, size_t lenvar __unused)
+{
+ const char *s;
+
+ memset(ei, 0, sizeof(*ei));
+
+#define FILL(str, flag) \
+do { \
+ for (s = str; *s != '\0'; s++) \
+ ei->cell[*s & 0x7f] |= flag; \
+} while (/*CONSTCOND*/0)
+
+ FILL(base64, (s - base64) + 1);
+ FILL(direct, EI_DIRECT);
+ FILL(option, EI_OPTION);
+ FILL(spaces, EI_SPACE);
+
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(UTF7);
+_CITRUS_STDENC_DEF_OPS(UTF7);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/UTF7/citrus_utf7.h b/lib/libiconv_modules/UTF7/citrus_utf7.h
new file mode 100644
index 0000000..96ca478
--- /dev/null
+++ b/lib/libiconv_modules/UTF7/citrus_utf7.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_utf7.h,v 1.1 2005/03/05 18:05:15 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004,2005 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_UTF7_H_
+#define _CITRUS_UTF7_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(UTF7);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/UTF8/Makefile b/lib/libiconv_modules/UTF8/Makefile
new file mode 100644
index 0000000..223a126
--- /dev/null
+++ b/lib/libiconv_modules/UTF8/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SHLIB= UTF8
+SRCS+= citrus_utf8.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/UTF8/citrus_utf8.c b/lib/libiconv_modules/UTF8/citrus_utf8.c
new file mode 100644
index 0000000..2bd8d81
--- /dev/null
+++ b/lib/libiconv_modules/UTF8/citrus_utf8.c
@@ -0,0 +1,349 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_utf8.c,v 1.17 2008/06/14 16:01:08 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.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_stdenc.h"
+#include "citrus_utf8.h"
+
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+static uint8_t _UTF8_count_array[256] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 - 8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 - 9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* A0 - AF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* B0 - BF */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* C0 - CF */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* D0 - DF */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* E0 - EF */
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 /* F0 - FF */
+};
+
+static uint8_t const *_UTF8_count = _UTF8_count_array;
+
+static const uint32_t _UTF8_range[] = {
+ 0, /*dummy*/
+ 0x00000000, 0x00000080, 0x00000800, 0x00010000,
+ 0x00200000, 0x04000000, 0x80000000,
+};
+
+typedef struct {
+ int chlen;
+ char ch[6];
+} _UTF8State;
+
+typedef void *_UTF8EncodingInfo;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_ei_, _func_) (_ei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_UTF8_##m
+#define _ENCODING_INFO _UTF8EncodingInfo
+#define _ENCODING_STATE _UTF8State
+#define _ENCODING_MB_CUR_MAX(_ei_) 6
+#define _ENCODING_IS_STATE_DEPENDENT 0
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+static size_t
+_UTF8_findlen(wchar_t v)
+{
+ size_t i;
+ uint32_t c;
+
+ c = (uint32_t)v; /*XXX*/
+ for (i = 1; i < sizeof(_UTF8_range) / sizeof(_UTF8_range[0]) - 1; i++)
+ if (c >= _UTF8_range[i] && c < _UTF8_range[i + 1])
+ return (i);
+
+ return (-1); /*out of range*/
+}
+
+static __inline bool
+_UTF8_surrogate(wchar_t wc)
+{
+
+ return (wc >= 0xd800 && wc <= 0xdfff);
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF8_init_state(_UTF8EncodingInfo *ei __unused, _UTF8State *s)
+{
+
+ s->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF8_pack_state(_UTF8EncodingInfo *ei __unused, void *pspriv,
+ const _UTF8State *s)
+{
+
+ memcpy(pspriv, (const void *)s, sizeof(*s));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_UTF8_unpack_state(_UTF8EncodingInfo *ei __unused, _UTF8State *s,
+ const void *pspriv)
+{
+
+ memcpy((void *)s, pspriv, sizeof(*s));
+}
+
+static int
+_citrus_UTF8_mbrtowc_priv(_UTF8EncodingInfo *ei, wchar_t *pwc, char **s,
+ size_t n, _UTF8State *psenc, size_t *nresult)
+{
+ char *s0;
+ wchar_t wchar;
+ int i;
+ uint8_t c;
+
+ s0 = *s;
+
+ if (s0 == NULL) {
+ _citrus_UTF8_init_state(ei, psenc);
+ *nresult = 0; /* state independent */
+ return (0);
+ }
+
+ /* make sure we have the first byte in the buffer */
+ if (psenc->chlen == 0) {
+ if (n-- < 1)
+ goto restart;
+ psenc->ch[psenc->chlen++] = *s0++;
+ }
+
+ c = _UTF8_count[psenc->ch[0] & 0xff];
+ if (c < 1 || c < psenc->chlen)
+ goto ilseq;
+
+ if (c == 1)
+ wchar = psenc->ch[0] & 0xff;
+ else {
+ while (psenc->chlen < c) {
+ if (n-- < 1)
+ goto restart;
+ psenc->ch[psenc->chlen++] = *s0++;
+ }
+ wchar = psenc->ch[0] & (0x7f >> c);
+ for (i = 1; i < c; i++) {
+ if ((psenc->ch[i] & 0xc0) != 0x80)
+ goto ilseq;
+ wchar <<= 6;
+ wchar |= (psenc->ch[i] & 0x3f);
+ }
+ if (_UTF8_surrogate(wchar) || _UTF8_findlen(wchar) != c)
+ goto ilseq;
+ }
+ if (pwc != NULL)
+ *pwc = wchar;
+ *nresult = (wchar == 0) ? 0 : s0 - *s;
+ *s = s0;
+ psenc->chlen = 0;
+
+ return (0);
+
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+
+restart:
+ *s = s0;
+ *nresult = (size_t)-2;
+ return (0);
+}
+
+static int
+_citrus_UTF8_wcrtomb_priv(_UTF8EncodingInfo *ei __unused, char *s, size_t n,
+ wchar_t wc, _UTF8State *psenc __unused, size_t *nresult)
+{
+ wchar_t c;
+ size_t cnt;
+ int i, ret;
+
+ if (_UTF8_surrogate(wc)) {
+ ret = EILSEQ;
+ goto err;
+ }
+ cnt = _UTF8_findlen(wc);
+ if (cnt <= 0 || cnt > 6) {
+ /* invalid UCS4 value */
+ ret = EILSEQ;
+ goto err;
+ }
+ if (n < cnt) {
+ /* bound check failure */
+ ret = E2BIG;
+ goto err;
+ }
+
+ c = wc;
+ if (s) {
+ for (i = cnt - 1; i > 0; i--) {
+ s[i] = 0x80 | (c & 0x3f);
+ c >>= 6;
+ }
+ s[0] = c;
+ if (cnt == 1)
+ s[0] &= 0x7f;
+ else {
+ s[0] &= (0x7f >> cnt);
+ s[0] |= ((0xff00 >> cnt) & 0xff);
+ }
+ }
+
+ *nresult = (size_t)cnt;
+ return (0);
+
+err:
+ *nresult = (size_t)-1;
+ return (ret);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF8_stdenc_wctocs(_UTF8EncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx,
+ wchar_t wc)
+{
+
+ *csid = 0;
+ *idx = (_citrus_index_t)wc;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF8_stdenc_cstowc(_UTF8EncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ if (csid != 0)
+ return (EILSEQ);
+
+ *wc = (wchar_t)idx;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_UTF8_stdenc_get_state_desc_generic(_UTF8EncodingInfo * __restrict ei __unused,
+ _UTF8State * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_UTF8_encoding_module_init(_UTF8EncodingInfo * __restrict ei __unused,
+ const void * __restrict var __unused, size_t lenvar __unused)
+{
+
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_UTF8_encoding_module_uninit(_UTF8EncodingInfo *ei __unused)
+{
+
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(UTF8);
+_CITRUS_STDENC_DEF_OPS(UTF8);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/UTF8/citrus_utf8.h b/lib/libiconv_modules/UTF8/citrus_utf8.h
new file mode 100644
index 0000000..fa412b7
--- /dev/null
+++ b/lib/libiconv_modules/UTF8/citrus_utf8.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_utf8.h,v 1.2 2003/06/25 09:51:49 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_UTF8_H_
+#define _CITRUS_UTF8_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(UTF8);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/VIQR/Makefile b/lib/libiconv_modules/VIQR/Makefile
new file mode 100644
index 0000000..67e367a
--- /dev/null
+++ b/lib/libiconv_modules/VIQR/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SHLIB= VIQR
+SRCS+= citrus_viqr.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/VIQR/citrus_viqr.c b/lib/libiconv_modules/VIQR/citrus_viqr.c
new file mode 100644
index 0000000..bd26749
--- /dev/null
+++ b/lib/libiconv_modules/VIQR/citrus_viqr.c
@@ -0,0 +1,494 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_viqr.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_viqr.h"
+
+#define ESCAPE '\\'
+
+/*
+ * this table generated from RFC 1456.
+ */
+static const char *mnemonic_rfc1456[0x100] = {
+ NULL , NULL , "A(?", NULL , NULL , "A(~", "A^~", NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , "Y?" , NULL , NULL , NULL ,
+ NULL , "Y~" , NULL , NULL , NULL , NULL , "Y." , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ,
+ "A." , "A('", "A(`", "A(.", "A^'", "A^`", "A^?", "A^.",
+ "E~" , "E." , "E^'", "E^`", "E^?", "E^~", "E^.", "O^'",
+ "O^`", "O^?", "O^~", "O^.", "O+.", "O+'", "O+`", "O+?",
+ "I." , "O?" , "O." , "I?" , "U?" , "U~" , "U." , "Y`" ,
+ "O~" , "a('", "a(`", "a(.", "a^'", "a^`", "a^?", "a^.",
+ "e~" , "e." , "e^'", "e^`", "e^?", "e^~", "e^.", "o^'",
+ "o^`", "o^?", "o^~", "O+~", "O+" , "o^.", "o+`", "o+?",
+ "i." , "U+.", "U+'", "U+`", "U+?", "o+" , "o+'", "U+" ,
+ "A`" , "A'" , "A^" , "A~" , "A?" , "A(" , "a(?", "a(~",
+ "E`" , "E'" , "E^" , "E?" , "I`" , "I'" , "I~" , "y`" ,
+ "DD" , "u+'", "O`" , "O'" , "O^" , "a." , "y?" , "u+`",
+ "u+?", "U`" , "U'" , "y~" , "y." , "Y'" , "o+~", "u+" ,
+ "a`" , "a'" , "a^" , "a~" , "a?" , "a(" , "u+~", "a^~",
+ "e`" , "e'" , "e^" , "e?" , "i`" , "i'" , "i~" , "i?" ,
+ "dd" , "u+.", "o`" , "o'" , "o^" , "o~" , "o?" , "o." ,
+ "u." , "u`" , "u'" , "u~" , "u?" , "y'" , "o+.", "U+~",
+};
+
+typedef struct {
+ const char *name;
+ wchar_t value;
+} mnemonic_def_t;
+
+static const mnemonic_def_t mnemonic_ext[] = {
+/* add extra mnemonic here (should be sorted by wchar_t order). */
+};
+static const size_t mnemonic_ext_size =
+ sizeof(mnemonic_ext) / sizeof(mnemonic_def_t);
+
+static const char *
+mnemonic_ext_find(wchar_t wc, const mnemonic_def_t *head, size_t n)
+{
+ const mnemonic_def_t *mid;
+
+ for (; n > 0; n >>= 1) {
+ mid = head + (n >> 1);
+ if (mid->value == wc)
+ return (mid->name);
+ else if (mid->value < wc) {
+ head = mid + 1;
+ --n;
+ }
+ }
+ return (NULL);
+}
+
+struct mnemonic_t;
+typedef TAILQ_HEAD(mnemonic_list_t, mnemonic_t) mnemonic_list_t;
+typedef struct mnemonic_t {
+ TAILQ_ENTRY(mnemonic_t) entry;
+ struct mnemonic_t *parent;
+ mnemonic_list_t child;
+ wchar_t value;
+ int ascii;
+} mnemonic_t;
+
+static mnemonic_t *
+mnemonic_list_find(mnemonic_list_t *ml, int ch)
+{
+ mnemonic_t *m;
+
+ TAILQ_FOREACH(m, ml, entry) {
+ if (m->ascii == ch)
+ return (m);
+ }
+
+ return (NULL);
+}
+
+static mnemonic_t *
+mnemonic_create(mnemonic_t *parent, int ascii, wchar_t value)
+{
+ mnemonic_t *m;
+
+ m = malloc(sizeof(*m));
+ if (m != NULL) {
+ m->parent = parent;
+ m->ascii = ascii;
+ m->value = value;
+ TAILQ_INIT(&m->child);
+ }
+
+ return (m);
+}
+
+static int
+mnemonic_append_child(mnemonic_t *m, const char *s,
+ wchar_t value, wchar_t invalid)
+{
+ mnemonic_t *m0;
+ int ch;
+
+ ch = (unsigned char)*s++;
+ if (ch == '\0')
+ return (EINVAL);
+ m0 = mnemonic_list_find(&m->child, ch);
+ if (m0 == NULL) {
+ m0 = mnemonic_create(m, ch, (wchar_t)ch);
+ if (m0 == NULL)
+ return (ENOMEM);
+ TAILQ_INSERT_TAIL(&m->child, m0, entry);
+ }
+ m = m0;
+ for (m0 = NULL; (ch = (unsigned char)*s) != '\0'; ++s) {
+ m0 = mnemonic_list_find(&m->child, ch);
+ if (m0 == NULL) {
+ m0 = mnemonic_create(m, ch, invalid);
+ if (m0 == NULL)
+ return (ENOMEM);
+ TAILQ_INSERT_TAIL(&m->child, m0, entry);
+ }
+ m = m0;
+ }
+ if (m0 == NULL)
+ return (EINVAL);
+ m0->value = value;
+
+ return (0);
+}
+
+static void
+mnemonic_destroy(mnemonic_t *m)
+{
+ mnemonic_t *m0;
+
+ TAILQ_FOREACH(m0, &m->child, entry)
+ mnemonic_destroy(m0);
+ free(m);
+}
+
+typedef struct {
+ mnemonic_t *mroot;
+ wchar_t invalid;
+ size_t mb_cur_max;
+} _VIQREncodingInfo;
+
+typedef struct {
+ int chlen;
+ char ch[MB_LEN_MAX];
+} _VIQRState;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_VIQR_##m
+#define _ENCODING_INFO _VIQREncodingInfo
+#define _ENCODING_STATE _VIQRState
+#define _ENCODING_MB_CUR_MAX(_ei_) (_ei_)->mb_cur_max
+#define _ENCODING_IS_STATE_DEPENDENT 1
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0
+
+static __inline void
+/*ARGSUSED*/
+_citrus_VIQR_init_state(_VIQREncodingInfo * __restrict ei __unused,
+ _VIQRState * __restrict psenc)
+{
+
+ psenc->chlen = 0;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_VIQR_pack_state(_VIQREncodingInfo * __restrict ei __unused,
+ void *__restrict pspriv, const _VIQRState * __restrict psenc)
+{
+
+ memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_VIQR_unpack_state(_VIQREncodingInfo * __restrict ei __unused,
+ _VIQRState * __restrict psenc, const void * __restrict pspriv)
+{
+
+ memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static int
+_citrus_VIQR_mbrtowc_priv(_VIQREncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char ** __restrict s, size_t n,
+ _VIQRState * __restrict psenc, size_t * __restrict nresult)
+{
+ mnemonic_t *m, *m0;
+ char *s0;
+ wchar_t wc;
+ ssize_t i;
+ int ch, escape;
+
+ if (*s == NULL) {
+ _citrus_VIQR_init_state(ei, psenc);
+ *nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
+ return (0);
+ }
+ s0 = *s;
+
+ i = 0;
+ m = ei->mroot;
+ for (escape = 0;;) {
+ if (psenc->chlen == i) {
+ if (n-- < 1) {
+ *s = s0;
+ *nresult = (size_t)-2;
+ return (0);
+ }
+ psenc->ch[psenc->chlen++] = *s0++;
+ }
+ ch = (unsigned char)psenc->ch[i++];
+ if (ch == ESCAPE) {
+ if (m != ei->mroot)
+ break;
+ escape = 1;
+ continue;
+ }
+ if (escape != 0)
+ break;
+ m0 = mnemonic_list_find(&m->child, ch);
+ if (m0 == NULL)
+ break;
+ m = m0;
+ }
+ while (m != ei->mroot) {
+ --i;
+ if (m->value != ei->invalid)
+ break;
+ m = m->parent;
+ }
+ if (ch == ESCAPE && m != ei->mroot)
+ ++i;
+ psenc->chlen -= i;
+ memmove(&psenc->ch[0], &psenc->ch[i], psenc->chlen);
+ wc = (m == ei->mroot) ? (wchar_t)ch : m->value;
+ if (pwc != NULL)
+ *pwc = wc;
+ *nresult = (size_t)(wc == 0 ? 0 : s0 - *s);
+ *s = s0;
+
+ return (0);
+}
+
+static int
+_citrus_VIQR_wcrtomb_priv(_VIQREncodingInfo * __restrict ei,
+ char * __restrict s, size_t n, wchar_t wc,
+ _VIQRState * __restrict psenc, size_t * __restrict nresult)
+{
+ mnemonic_t *m;
+ const char *p;
+ int ch = 0;
+
+ switch (psenc->chlen) {
+ case 0: case 1:
+ break;
+ default:
+ return (EINVAL);
+ }
+ m = NULL;
+ if ((uint32_t)wc <= 0xFF) {
+ p = mnemonic_rfc1456[wc & 0xFF];
+ if (p != NULL)
+ goto mnemonic_found;
+ if (n-- < 1)
+ goto e2big;
+ ch = (unsigned int)wc;
+ m = ei->mroot;
+ if (psenc->chlen > 0) {
+ m = mnemonic_list_find(&m->child, psenc->ch[0]);
+ if (m == NULL)
+ return (EINVAL);
+ psenc->ch[0] = ESCAPE;
+ }
+ if (mnemonic_list_find(&m->child, ch) == NULL) {
+ psenc->chlen = 0;
+ m = NULL;
+ }
+ psenc->ch[psenc->chlen++] = ch;
+ } else {
+ p = mnemonic_ext_find(wc, &mnemonic_ext[0], mnemonic_ext_size);
+ if (p == NULL) {
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ } else {
+mnemonic_found:
+ psenc->chlen = 0;
+ while (*p != '\0') {
+ if (n-- < 1)
+ goto e2big;
+ psenc->ch[psenc->chlen++] = *p++;
+ }
+ }
+ }
+ memcpy(s, psenc->ch, psenc->chlen);
+ *nresult = psenc->chlen;
+ if (m == ei->mroot) {
+ psenc->ch[0] = ch;
+ psenc->chlen = 1;
+ } else
+ psenc->chlen = 0;
+
+ return (0);
+
+e2big:
+ *nresult = (size_t)-1;
+ return (E2BIG);
+}
+
+static int
+/* ARGSUSED */
+_citrus_VIQR_put_state_reset(_VIQREncodingInfo * __restrict ei __unused,
+ char * __restrict s __unused, size_t n __unused,
+ _VIQRState * __restrict psenc, size_t * __restrict nresult)
+{
+
+ switch (psenc->chlen) {
+ case 0: case 1:
+ break;
+ default:
+ return (EINVAL);
+ }
+ *nresult = 0;
+ psenc->chlen = 0;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_VIQR_stdenc_wctocs(_VIQREncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+
+ *csid = 0;
+ *idx = (_index_t)wc;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_VIQR_stdenc_cstowc(_VIQREncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict pwc, _csid_t csid, _index_t idx)
+{
+
+ if (csid != 0)
+ return (EILSEQ);
+ *pwc = (wchar_t)idx;
+
+ return (0);
+}
+
+static void
+_citrus_VIQR_encoding_module_uninit(_VIQREncodingInfo *ei)
+{
+
+ mnemonic_destroy(ei->mroot);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_VIQR_encoding_module_init(_VIQREncodingInfo * __restrict ei,
+ const void * __restrict var __unused, size_t lenvar __unused)
+{
+ const mnemonic_def_t *p;
+ const char *s;
+ size_t i, n;
+ int errnum;
+
+ ei->mb_cur_max = 1;
+ ei->invalid = (wchar_t)-1;
+ ei->mroot = mnemonic_create(NULL, '\0', ei->invalid);
+ if (ei->mroot == NULL)
+ return (ENOMEM);
+ for (i = 0; i < sizeof(mnemonic_rfc1456) / sizeof(const char *); ++i) {
+ s = mnemonic_rfc1456[i];
+ if (s == NULL)
+ continue;
+ n = strlen(s);
+ if (ei->mb_cur_max < n)
+ ei->mb_cur_max = n;
+ errnum = mnemonic_append_child(ei->mroot,
+ s, (wchar_t)i, ei->invalid);
+ if (errnum != 0) {
+ _citrus_VIQR_encoding_module_uninit(ei);
+ return (errnum);
+ }
+ }
+ for (i = 0;; ++i) {
+ p = &mnemonic_ext[i];
+ n = strlen(p->name);
+ if (ei->mb_cur_max < n)
+ ei->mb_cur_max = n;
+ errnum = mnemonic_append_child(ei->mroot,
+ p->name, p->value, ei->invalid);
+ if (errnum != 0) {
+ _citrus_VIQR_encoding_module_uninit(ei);
+ return (errnum);
+ }
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_VIQR_stdenc_get_state_desc_generic(_VIQREncodingInfo * __restrict ei __unused,
+ _VIQRState * __restrict psenc, int * __restrict rstate)
+{
+
+ *rstate = (psenc->chlen == 0) ?
+ _STDENC_SDGEN_INITIAL :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(VIQR);
+_CITRUS_STDENC_DEF_OPS(VIQR);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/VIQR/citrus_viqr.h b/lib/libiconv_modules/VIQR/citrus_viqr.h
new file mode 100644
index 0000000..a6d943c
--- /dev/null
+++ b/lib/libiconv_modules/VIQR/citrus_viqr.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_viqr.h,v 1.1 2006/11/13 15:16:31 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_VIQR_H_
+#define _CITRUS_VIQR_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(VIQR);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/ZW/Makefile b/lib/libiconv_modules/ZW/Makefile
new file mode 100644
index 0000000..42ecd9f
--- /dev/null
+++ b/lib/libiconv_modules/ZW/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SHLIB= ZW
+SRCS+= citrus_zw.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/ZW/citrus_zw.c b/lib/libiconv_modules/ZW/citrus_zw.c
new file mode 100644
index 0000000..d57661f
--- /dev/null
+++ b/lib/libiconv_modules/ZW/citrus_zw.c
@@ -0,0 +1,455 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_zw.c,v 1.4 2008/06/14 16:01:08 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_stdenc.h"
+#include "citrus_zw.h"
+
+/* ----------------------------------------------------------------------
+ * private stuffs used by templates
+ */
+
+typedef struct {
+ int dummy;
+} _ZWEncodingInfo;
+
+typedef enum {
+ NONE, AMBIGIOUS, ASCII, GB2312
+} _ZWCharset;
+
+typedef struct {
+ _ZWCharset charset;
+ int chlen;
+ char ch[4];
+} _ZWState;
+
+#define _CEI_TO_EI(_cei_) (&(_cei_)->ei)
+#define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_
+
+#define _FUNCNAME(m) _citrus_ZW_##m
+#define _ENCODING_INFO _ZWEncodingInfo
+#define _ENCODING_STATE _ZWState
+#define _ENCODING_MB_CUR_MAX(_ei_) MB_LEN_MAX
+#define _ENCODING_IS_STATE_DEPENDENT 1
+#define _STATE_NEEDS_EXPLICIT_INIT(_ps_) ((_ps_)->charset != NONE)
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ZW_init_state(_ZWEncodingInfo * __restrict ei __unused,
+ _ZWState * __restrict psenc)
+{
+
+ psenc->chlen = 0;
+ psenc->charset = NONE;
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ZW_pack_state(_ZWEncodingInfo * __restrict ei __unused,
+ void *__restrict pspriv, const _ZWState * __restrict psenc)
+{
+
+ memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
+}
+
+static __inline void
+/*ARGSUSED*/
+_citrus_ZW_unpack_state(_ZWEncodingInfo * __restrict ei __unused,
+ _ZWState * __restrict psenc, const void * __restrict pspriv)
+{
+
+ memcpy((void *)psenc, pspriv, sizeof(*psenc));
+}
+
+static int
+_citrus_ZW_mbrtowc_priv(_ZWEncodingInfo * __restrict ei,
+ wchar_t * __restrict pwc, char **__restrict s, size_t n,
+ _ZWState * __restrict psenc, size_t * __restrict nresult)
+{
+ char *s0;
+ wchar_t wc;
+ int ch, len;
+
+ if (*s == NULL) {
+ _citrus_ZW_init_state(ei, psenc);
+ *nresult = (size_t)_ENCODING_IS_STATE_DEPENDENT;
+ return (0);
+ }
+ s0 = *s;
+ len = 0;
+
+#define STORE \
+do { \
+ if (n-- < 1) { \
+ *nresult = (size_t)-2; \
+ *s = s0; \
+ return (0); \
+ } \
+ ch = (unsigned char)*s0++; \
+ if (len++ > MB_LEN_MAX || ch > 0x7F)\
+ goto ilseq; \
+ psenc->ch[psenc->chlen++] = ch; \
+} while (/*CONSTCOND*/0)
+
+loop:
+ switch (psenc->charset) {
+ case ASCII:
+ switch (psenc->chlen) {
+ case 0:
+ STORE;
+ switch (psenc->ch[0]) {
+ case '\0': case '\n':
+ psenc->charset = NONE;
+ }
+ /*FALLTHROUGH*/
+ case 1:
+ break;
+ default:
+ return (EINVAL);
+ }
+ ch = (unsigned char)psenc->ch[0];
+ if (ch > 0x7F)
+ goto ilseq;
+ wc = (wchar_t)ch;
+ psenc->chlen = 0;
+ break;
+ case NONE:
+ if (psenc->chlen != 0)
+ return (EINVAL);
+ STORE;
+ ch = (unsigned char)psenc->ch[0];
+ if (ch != 'z') {
+ if (ch != '\n' && ch != '\0')
+ psenc->charset = ASCII;
+ wc = (wchar_t)ch;
+ psenc->chlen = 0;
+ break;
+ }
+ psenc->charset = AMBIGIOUS;
+ psenc->chlen = 0;
+ /* FALLTHROUGH */
+ case AMBIGIOUS:
+ if (psenc->chlen != 0)
+ return (EINVAL);
+ STORE;
+ if (psenc->ch[0] != 'W') {
+ psenc->charset = ASCII;
+ wc = L'z';
+ break;
+ }
+ psenc->charset = GB2312;
+ psenc->chlen = 0;
+ /* FALLTHROUGH */
+ case GB2312:
+ switch (psenc->chlen) {
+ case 0:
+ STORE;
+ ch = (unsigned char)psenc->ch[0];
+ if (ch == '\0') {
+ psenc->charset = NONE;
+ wc = (wchar_t)ch;
+ psenc->chlen = 0;
+ break;
+ } else if (ch == '\n') {
+ psenc->charset = NONE;
+ psenc->chlen = 0;
+ goto loop;
+ }
+ /*FALLTHROUGH*/
+ case 1:
+ STORE;
+ if (psenc->ch[0] == ' ') {
+ ch = (unsigned char)psenc->ch[1];
+ wc = (wchar_t)ch;
+ psenc->chlen = 0;
+ break;
+ } else if (psenc->ch[0] == '#') {
+ ch = (unsigned char)psenc->ch[1];
+ if (ch == '\n') {
+ psenc->charset = NONE;
+ wc = (wchar_t)ch;
+ psenc->chlen = 0;
+ break;
+ } else if (ch == ' ') {
+ wc = (wchar_t)ch;
+ psenc->chlen = 0;
+ break;
+ }
+ }
+ ch = (unsigned char)psenc->ch[0];
+ if (ch < 0x21 || ch > 0x7E)
+ goto ilseq;
+ wc = (wchar_t)(ch << 8);
+ ch = (unsigned char)psenc->ch[1];
+ if (ch < 0x21 || ch > 0x7E) {
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ }
+ wc |= (wchar_t)ch;
+ psenc->chlen = 0;
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+ if (pwc != NULL)
+ *pwc = wc;
+
+ *nresult = (size_t)(wc == 0 ? 0 : len);
+ *s = s0;
+
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_ZW_wcrtomb_priv(_ZWEncodingInfo * __restrict ei __unused,
+ char *__restrict s, size_t n, wchar_t wc,
+ _ZWState * __restrict psenc, size_t * __restrict nresult)
+{
+ int ch;
+
+ if (psenc->chlen != 0)
+ return (EINVAL);
+ if ((uint32_t)wc <= 0x7F) {
+ ch = (unsigned char)wc;
+ switch (psenc->charset) {
+ case NONE:
+ if (ch == '\0' || ch == '\n')
+ psenc->ch[psenc->chlen++] = ch;
+ else {
+ if (n < 4)
+ return (E2BIG);
+ n -= 4;
+ psenc->ch[psenc->chlen++] = 'z';
+ psenc->ch[psenc->chlen++] = 'W';
+ psenc->ch[psenc->chlen++] = ' ';
+ psenc->ch[psenc->chlen++] = ch;
+ psenc->charset = GB2312;
+ }
+ break;
+ case GB2312:
+ if (n < 2)
+ return (E2BIG);
+ n -= 2;
+ if (ch == '\0') {
+ psenc->ch[psenc->chlen++] = '\n';
+ psenc->ch[psenc->chlen++] = '\0';
+ psenc->charset = NONE;
+ } else if (ch == '\n') {
+ psenc->ch[psenc->chlen++] = '#';
+ psenc->ch[psenc->chlen++] = '\n';
+ psenc->charset = NONE;
+ } else {
+ psenc->ch[psenc->chlen++] = ' ';
+ psenc->ch[psenc->chlen++] = ch;
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+ } else if ((uint32_t)wc <= 0x7E7E) {
+ switch (psenc->charset) {
+ case NONE:
+ if (n < 2)
+ return (E2BIG);
+ n -= 2;
+ psenc->ch[psenc->chlen++] = 'z';
+ psenc->ch[psenc->chlen++] = 'W';
+ psenc->charset = GB2312;
+ /* FALLTHROUGH*/
+ case GB2312:
+ if (n < 2)
+ return (E2BIG);
+ n -= 2;
+ ch = (wc >> 8) & 0xFF;
+ if (ch < 0x21 || ch > 0x7E)
+ goto ilseq;
+ psenc->ch[psenc->chlen++] = ch;
+ ch = wc & 0xFF;
+ if (ch < 0x21 || ch > 0x7E)
+ goto ilseq;
+ psenc->ch[psenc->chlen++] = ch;
+ break;
+ default:
+ return (EINVAL);
+ }
+ } else {
+ilseq:
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ }
+ memcpy(s, psenc->ch, psenc->chlen);
+ *nresult = psenc->chlen;
+ psenc->chlen = 0;
+
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_ZW_put_state_reset(_ZWEncodingInfo * __restrict ei __unused,
+ char * __restrict s, size_t n, _ZWState * __restrict psenc,
+ size_t * __restrict nresult)
+{
+
+ if (psenc->chlen != 0)
+ return (EINVAL);
+ switch (psenc->charset) {
+ case GB2312:
+ if (n-- < 1)
+ return (E2BIG);
+ psenc->ch[psenc->chlen++] = '\n';
+ psenc->charset = NONE;
+ /*FALLTHROUGH*/
+ case NONE:
+ *nresult = psenc->chlen;
+ if (psenc->chlen > 0) {
+ memcpy(s, psenc->ch, psenc->chlen);
+ psenc->chlen = 0;
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ZW_stdenc_get_state_desc_generic(_ZWEncodingInfo * __restrict ei __unused,
+ _ZWState * __restrict psenc, int * __restrict rstate)
+{
+
+ switch (psenc->charset) {
+ case NONE:
+ if (psenc->chlen != 0)
+ return (EINVAL);
+ *rstate = _STDENC_SDGEN_INITIAL;
+ break;
+ case AMBIGIOUS:
+ if (psenc->chlen != 0)
+ return (EINVAL);
+ *rstate = _STDENC_SDGEN_INCOMPLETE_SHIFT;
+ break;
+ case ASCII:
+ case GB2312:
+ switch (psenc->chlen) {
+ case 0:
+ *rstate = _STDENC_SDGEN_STABLE;
+ break;
+ case 1:
+ *rstate = (psenc->ch[0] == '#') ?
+ _STDENC_SDGEN_INCOMPLETE_SHIFT :
+ _STDENC_SDGEN_INCOMPLETE_CHAR;
+ break;
+ default:
+ return (EINVAL);
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ZW_stdenc_wctocs(_ZWEncodingInfo * __restrict ei __unused,
+ _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
+{
+
+ *csid = (_csid_t)(wc <= (wchar_t)0x7FU) ? 0 : 1;
+ *idx = (_index_t)wc;
+
+ return (0);
+}
+
+static __inline int
+/*ARGSUSED*/
+_citrus_ZW_stdenc_cstowc(_ZWEncodingInfo * __restrict ei __unused,
+ wchar_t * __restrict wc, _csid_t csid, _index_t idx)
+{
+
+ switch (csid) {
+ case 0: case 1:
+ break;
+ default:
+ return (EINVAL);
+ }
+ *wc = (wchar_t)idx;
+
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_ZW_encoding_module_uninit(_ZWEncodingInfo *ei __unused)
+{
+
+}
+
+static int
+/*ARGSUSED*/
+_citrus_ZW_encoding_module_init(_ZWEncodingInfo * __restrict ei __unused,
+ const void *__restrict var __unused, size_t lenvar __unused)
+{
+
+ return (0);
+}
+
+/* ----------------------------------------------------------------------
+ * public interface for stdenc
+ */
+
+_CITRUS_STDENC_DECLS(ZW);
+_CITRUS_STDENC_DEF_OPS(ZW);
+
+#include "citrus_stdenc_template.h"
diff --git a/lib/libiconv_modules/ZW/citrus_zw.h b/lib/libiconv_modules/ZW/citrus_zw.h
new file mode 100644
index 0000000..b24485b
--- /dev/null
+++ b/lib/libiconv_modules/ZW/citrus_zw.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_zw.h,v 1.1 2006/11/22 23:38:27 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2004,2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ZW_H_
+#define _CITRUS_ZW_H_
+
+__BEGIN_DECLS
+_CITRUS_STDENC_GETOPS_FUNC(ZW);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/iconv_none/Makefile b/lib/libiconv_modules/iconv_none/Makefile
new file mode 100644
index 0000000..d6cbd02
--- /dev/null
+++ b/lib/libiconv_modules/iconv_none/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SHLIB= iconv_none
+SRCS+= citrus_iconv_none.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/iconv_none/citrus_iconv_none.c b/lib/libiconv_modules/iconv_none/citrus_iconv_none.c
new file mode 100644
index 0000000..d9230cb
--- /dev/null
+++ b/lib/libiconv_modules/iconv_none/citrus_iconv_none.c
@@ -0,0 +1,127 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv_none.c,v 1.2 2003/07/01 09:42:16 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_hash.h"
+#include "citrus_iconv.h"
+#include "citrus_iconv_none.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_ICONV_DECLS(iconv_none);
+_CITRUS_ICONV_DEF_OPS(iconv_none);
+
+
+/* ---------------------------------------------------------------------- */
+
+int
+_citrus_iconv_none_iconv_getops(struct _citrus_iconv_ops *ops)
+{
+
+ memcpy(ops, &_citrus_iconv_none_iconv_ops,
+ sizeof(_citrus_iconv_none_iconv_ops));
+
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_init_shared(
+ struct _citrus_iconv_shared * __restrict ci,
+ const char * __restrict in __unused, const char * __restrict out __unused)
+{
+
+ ci->ci_closure = NULL;
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_uninit_shared(struct _citrus_iconv_shared *ci __unused)
+{
+
+}
+
+static int
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_init_context(struct _citrus_iconv *cv)
+{
+
+ cv->cv_closure = NULL;
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_uninit_context(struct _citrus_iconv *cv __unused)
+{
+
+}
+
+static int
+/*ARGSUSED*/
+_citrus_iconv_none_iconv_convert(struct _citrus_iconv * __restrict ci __unused,
+ char * __restrict * __restrict in, size_t * __restrict inbytes,
+ char * __restrict * __restrict out, size_t * __restrict outbytes,
+ uint32_t flags __unused, size_t * __restrict invalids)
+{
+ size_t len;
+ int e2big;
+
+ if ((in == NULL) || (out == NULL) || (inbytes == NULL))
+ return (0);
+ if ((*in == NULL) || (*out == NULL) || (*inbytes == 0) || (*outbytes == 0))
+ return (0);
+ len = *inbytes;
+ e2big = 0;
+ if (*outbytes<len) {
+ e2big = 1;
+ len = *outbytes;
+ }
+ memcpy(*out, *in, len);
+ in += len;
+ *inbytes -= len;
+ out += len;
+ *outbytes -= len;
+ *invalids = 0;
+ if (e2big)
+ return (E2BIG);
+
+ return (0);
+}
diff --git a/lib/libiconv_modules/iconv_none/citrus_iconv_none.h b/lib/libiconv_modules/iconv_none/citrus_iconv_none.h
new file mode 100644
index 0000000..392af41
--- /dev/null
+++ b/lib/libiconv_modules/iconv_none/citrus_iconv_none.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv_none.h,v 1.1 2003/06/25 09:51:43 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_NONE_H_
+#define _CITRUS_ICONV_NONE_H_
+
+__BEGIN_DECLS
+_CITRUS_ICONV_GETOPS_FUNC(iconv_none);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/iconv_std/Makefile b/lib/libiconv_modules/iconv_std/Makefile
new file mode 100644
index 0000000..a873cfa
--- /dev/null
+++ b/lib/libiconv_modules/iconv_std/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= iconv_std
+SRCS+= citrus_iconv_std.c
+CFLAGS+= --param max-inline-insns-single=32
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/iconv_std/citrus_iconv_std.c b/lib/libiconv_modules/iconv_std/citrus_iconv_std.c
new file mode 100644
index 0000000..8349c46
--- /dev/null
+++ b/lib/libiconv_modules/iconv_std/citrus_iconv_std.c
@@ -0,0 +1,583 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv_std.c,v 1.15 2006/11/13 19:08:19 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/endian.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_region.h"
+#include "citrus_mmap.h"
+#include "citrus_hash.h"
+#include "citrus_iconv.h"
+#include "citrus_stdenc.h"
+#include "citrus_mapper.h"
+#include "citrus_csmapper.h"
+#include "citrus_memstream.h"
+#include "citrus_iconv_std.h"
+#include "citrus_esdb.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_ICONV_DECLS(iconv_std);
+_CITRUS_ICONV_DEF_OPS(iconv_std);
+
+
+/* ---------------------------------------------------------------------- */
+
+int
+_citrus_iconv_std_iconv_getops(struct _citrus_iconv_ops *ops)
+{
+
+ memcpy(ops, &_citrus_iconv_std_iconv_ops,
+ sizeof(_citrus_iconv_std_iconv_ops));
+
+ return (0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * convenience routines for stdenc.
+ */
+static __inline void
+save_encoding_state(struct _citrus_iconv_std_encoding *se)
+{
+
+ if (se->se_ps)
+ memcpy(se->se_pssaved, se->se_ps,
+ _stdenc_get_state_size(se->se_handle));
+}
+
+static __inline void
+restore_encoding_state(struct _citrus_iconv_std_encoding *se)
+{
+
+ if (se->se_ps)
+ memcpy(se->se_ps, se->se_pssaved,
+ _stdenc_get_state_size(se->se_handle));
+}
+
+static __inline void
+init_encoding_state(struct _citrus_iconv_std_encoding *se)
+{
+
+ if (se->se_ps)
+ _stdenc_init_state(se->se_handle, se->se_ps);
+}
+
+static __inline int
+mbtocsx(struct _citrus_iconv_std_encoding *se,
+ _csid_t *csid, _index_t *idx, char **s, size_t n, size_t *nresult,
+ struct iconv_hooks *hooks)
+{
+
+ return (_stdenc_mbtocs(se->se_handle, csid, idx, s, n, se->se_ps,
+ nresult, hooks));
+}
+
+static __inline int
+cstombx(struct _citrus_iconv_std_encoding *se,
+ char *s, size_t n, _csid_t csid, _index_t idx, size_t *nresult,
+ struct iconv_hooks *hooks)
+{
+
+ return (_stdenc_cstomb(se->se_handle, s, n, csid, idx, se->se_ps,
+ nresult, hooks));
+}
+
+static __inline int
+wctombx(struct _citrus_iconv_std_encoding *se,
+ char *s, size_t n, _wc_t wc, size_t *nresult,
+ struct iconv_hooks *hooks)
+{
+
+ return (_stdenc_wctomb(se->se_handle, s, n, wc, se->se_ps, nresult,
+ hooks));
+}
+
+static __inline int
+put_state_resetx(struct _citrus_iconv_std_encoding *se, char *s, size_t n,
+ size_t *nresult)
+{
+
+ return (_stdenc_put_state_reset(se->se_handle, s, n, se->se_ps, nresult));
+}
+
+static __inline int
+get_state_desc_gen(struct _citrus_iconv_std_encoding *se, int *rstate)
+{
+ struct _stdenc_state_desc ssd;
+ int ret;
+
+ ret = _stdenc_get_state_desc(se->se_handle, se->se_ps,
+ _STDENC_SDID_GENERIC, &ssd);
+ if (!ret)
+ *rstate = ssd.u.generic.state;
+
+ return (ret);
+}
+
+/*
+ * init encoding context
+ */
+static int
+init_encoding(struct _citrus_iconv_std_encoding *se, struct _stdenc *cs,
+ void *ps1, void *ps2)
+{
+ int ret = -1;
+
+ se->se_handle = cs;
+ se->se_ps = ps1;
+ se->se_pssaved = ps2;
+
+ if (se->se_ps)
+ ret = _stdenc_init_state(cs, se->se_ps);
+ if (!ret && se->se_pssaved)
+ ret = _stdenc_init_state(cs, se->se_pssaved);
+
+ return (ret);
+}
+
+static int
+open_csmapper(struct _csmapper **rcm, const char *src, const char *dst,
+ unsigned long *rnorm)
+{
+ struct _csmapper *cm;
+ int ret;
+
+ ret = _csmapper_open(&cm, src, dst, 0, rnorm);
+ if (ret)
+ return (ret);
+ if (_csmapper_get_src_max(cm) != 1 || _csmapper_get_dst_max(cm) != 1 ||
+ _csmapper_get_state_size(cm) != 0) {
+ _csmapper_close(cm);
+ return (EINVAL);
+ }
+
+ *rcm = cm;
+
+ return (0);
+}
+
+static void
+close_dsts(struct _citrus_iconv_std_dst_list *dl)
+{
+ struct _citrus_iconv_std_dst *sd;
+
+ while ((sd = TAILQ_FIRST(dl)) != NULL) {
+ TAILQ_REMOVE(dl, sd, sd_entry);
+ _csmapper_close(sd->sd_mapper);
+ free(sd);
+ }
+}
+
+static int
+open_dsts(struct _citrus_iconv_std_dst_list *dl,
+ const struct _esdb_charset *ec, const struct _esdb *dbdst)
+{
+ struct _citrus_iconv_std_dst *sd, *sdtmp;
+ unsigned long norm;
+ int i, ret;
+
+ sd = malloc(sizeof(*sd));
+ if (sd == NULL)
+ return (errno);
+
+ for (i = 0; i < dbdst->db_num_charsets; i++) {
+ ret = open_csmapper(&sd->sd_mapper, ec->ec_csname,
+ dbdst->db_charsets[i].ec_csname, &norm);
+ if (ret == 0) {
+ sd->sd_csid = dbdst->db_charsets[i].ec_csid;
+ sd->sd_norm = norm;
+ /* insert this mapper by sorted order. */
+ TAILQ_FOREACH(sdtmp, dl, sd_entry) {
+ if (sdtmp->sd_norm > norm) {
+ TAILQ_INSERT_BEFORE(sdtmp, sd,
+ sd_entry);
+ sd = NULL;
+ break;
+ }
+ }
+ if (sd)
+ TAILQ_INSERT_TAIL(dl, sd, sd_entry);
+ sd = malloc(sizeof(*sd));
+ if (sd == NULL) {
+ ret = errno;
+ close_dsts(dl);
+ return (ret);
+ }
+ } else if (ret != ENOENT) {
+ close_dsts(dl);
+ free(sd);
+ return (ret);
+ }
+ }
+ free(sd);
+ return (0);
+}
+
+static void
+close_srcs(struct _citrus_iconv_std_src_list *sl)
+{
+ struct _citrus_iconv_std_src *ss;
+
+ while ((ss = TAILQ_FIRST(sl)) != NULL) {
+ TAILQ_REMOVE(sl, ss, ss_entry);
+ close_dsts(&ss->ss_dsts);
+ free(ss);
+ }
+}
+
+static int
+open_srcs(struct _citrus_iconv_std_src_list *sl,
+ const struct _esdb *dbsrc, const struct _esdb *dbdst)
+{
+ struct _citrus_iconv_std_src *ss;
+ int count = 0, i, ret;
+
+ ss = malloc(sizeof(*ss));
+ if (ss == NULL)
+ return (errno);
+
+ TAILQ_INIT(&ss->ss_dsts);
+
+ for (i = 0; i < dbsrc->db_num_charsets; i++) {
+ ret = open_dsts(&ss->ss_dsts, &dbsrc->db_charsets[i], dbdst);
+ if (ret)
+ goto err;
+ if (!TAILQ_EMPTY(&ss->ss_dsts)) {
+ ss->ss_csid = dbsrc->db_charsets[i].ec_csid;
+ TAILQ_INSERT_TAIL(sl, ss, ss_entry);
+ ss = malloc(sizeof(*ss));
+ if (ss == NULL) {
+ ret = errno;
+ goto err;
+ }
+ count++;
+ TAILQ_INIT(&ss->ss_dsts);
+ }
+ }
+ free(ss);
+
+ return (count ? 0 : ENOENT);
+
+err:
+ free(ss);
+ close_srcs(sl);
+ return (ret);
+}
+
+/* do convert a character */
+#define E_NO_CORRESPONDING_CHAR ENOENT /* XXX */
+static int
+/*ARGSUSED*/
+do_conv(const struct _citrus_iconv_std_shared *is,
+ _csid_t *csid, _index_t *idx)
+{
+ struct _citrus_iconv_std_dst *sd;
+ struct _citrus_iconv_std_src *ss;
+ _index_t tmpidx;
+ int ret;
+
+ TAILQ_FOREACH(ss, &is->is_srcs, ss_entry) {
+ if (ss->ss_csid == *csid) {
+ TAILQ_FOREACH(sd, &ss->ss_dsts, sd_entry) {
+ ret = _csmapper_convert(sd->sd_mapper,
+ &tmpidx, *idx, NULL);
+ switch (ret) {
+ case _MAPPER_CONVERT_SUCCESS:
+ *csid = sd->sd_csid;
+ *idx = tmpidx;
+ return (0);
+ case _MAPPER_CONVERT_NONIDENTICAL:
+ break;
+ case _MAPPER_CONVERT_SRC_MORE:
+ /*FALLTHROUGH*/
+ case _MAPPER_CONVERT_DST_MORE:
+ /*FALLTHROUGH*/
+ case _MAPPER_CONVERT_ILSEQ:
+ return (EILSEQ);
+ case _MAPPER_CONVERT_FATAL:
+ return (EINVAL);
+ }
+ }
+ break;
+ }
+ }
+
+ return (E_NO_CORRESPONDING_CHAR);
+}
+/* ---------------------------------------------------------------------- */
+
+static int
+/*ARGSUSED*/
+_citrus_iconv_std_iconv_init_shared(struct _citrus_iconv_shared *ci,
+ const char * __restrict src, const char * __restrict dst)
+{
+ struct _citrus_esdb esdbdst, esdbsrc;
+ struct _citrus_iconv_std_shared *is;
+ int ret;
+
+ is = malloc(sizeof(*is));
+ if (is == NULL) {
+ ret = errno;
+ goto err0;
+ }
+ ret = _citrus_esdb_open(&esdbsrc, src);
+ if (ret)
+ goto err1;
+ ret = _citrus_esdb_open(&esdbdst, dst);
+ if (ret)
+ goto err2;
+ ret = _stdenc_open(&is->is_src_encoding, esdbsrc.db_encname,
+ esdbsrc.db_variable, esdbsrc.db_len_variable);
+ if (ret)
+ goto err3;
+ ret = _stdenc_open(&is->is_dst_encoding, esdbdst.db_encname,
+ esdbdst.db_variable, esdbdst.db_len_variable);
+ if (ret)
+ goto err4;
+ is->is_use_invalid = esdbdst.db_use_invalid;
+ is->is_invalid = esdbdst.db_invalid;
+
+ TAILQ_INIT(&is->is_srcs);
+ ret = open_srcs(&is->is_srcs, &esdbsrc, &esdbdst);
+ if (ret)
+ goto err5;
+
+ _esdb_close(&esdbsrc);
+ _esdb_close(&esdbdst);
+ ci->ci_closure = is;
+
+ return (0);
+
+err5:
+ _stdenc_close(is->is_dst_encoding);
+err4:
+ _stdenc_close(is->is_src_encoding);
+err3:
+ _esdb_close(&esdbdst);
+err2:
+ _esdb_close(&esdbsrc);
+err1:
+ free(is);
+err0:
+ return (ret);
+}
+
+static void
+_citrus_iconv_std_iconv_uninit_shared(struct _citrus_iconv_shared *ci)
+{
+ struct _citrus_iconv_std_shared *is = ci->ci_closure;
+
+ if (is == NULL)
+ return;
+
+ _stdenc_close(is->is_src_encoding);
+ _stdenc_close(is->is_dst_encoding);
+ close_srcs(&is->is_srcs);
+ free(is);
+}
+
+static int
+_citrus_iconv_std_iconv_init_context(struct _citrus_iconv *cv)
+{
+ const struct _citrus_iconv_std_shared *is = cv->cv_shared->ci_closure;
+ struct _citrus_iconv_std_context *sc;
+ char *ptr;
+ size_t sz, szpsdst, szpssrc;
+
+ szpssrc = _stdenc_get_state_size(is->is_src_encoding);
+ szpsdst = _stdenc_get_state_size(is->is_dst_encoding);
+
+ sz = (szpssrc + szpsdst)*2 + sizeof(struct _citrus_iconv_std_context);
+ sc = malloc(sz);
+ if (sc == NULL)
+ return (errno);
+
+ ptr = (char *)&sc[1];
+ if (szpssrc > 0)
+ init_encoding(&sc->sc_src_encoding, is->is_src_encoding,
+ ptr, ptr+szpssrc);
+ else
+ init_encoding(&sc->sc_src_encoding, is->is_src_encoding,
+ NULL, NULL);
+ ptr += szpssrc*2;
+ if (szpsdst > 0)
+ init_encoding(&sc->sc_dst_encoding, is->is_dst_encoding,
+ ptr, ptr+szpsdst);
+ else
+ init_encoding(&sc->sc_dst_encoding, is->is_dst_encoding,
+ NULL, NULL);
+
+ cv->cv_closure = (void *)sc;
+
+ return (0);
+}
+
+static void
+_citrus_iconv_std_iconv_uninit_context(struct _citrus_iconv *cv)
+{
+
+ free(cv->cv_closure);
+}
+
+static int
+_citrus_iconv_std_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 invalids)
+{
+ const struct _citrus_iconv_std_shared *is = cv->cv_shared->ci_closure;
+ struct _citrus_iconv_std_context *sc = cv->cv_closure;
+ _csid_t csid;
+ _index_t idx;
+ char *tmpin;
+ size_t inval, szrin, szrout;
+ int ret, state = 0;
+
+ inval = 0;
+ if (in == NULL || *in == NULL) {
+ /* special cases */
+ if (out != NULL && *out != NULL) {
+ /* init output state and store the shift sequence */
+ save_encoding_state(&sc->sc_src_encoding);
+ save_encoding_state(&sc->sc_dst_encoding);
+ szrout = 0;
+
+ ret = put_state_resetx(&sc->sc_dst_encoding,
+ *out, *outbytes, &szrout);
+ if (ret)
+ goto err;
+
+ if (szrout == (size_t)-2) {
+ /* too small to store the character */
+ ret = EINVAL;
+ goto err;
+ }
+ *out += szrout;
+ *outbytes -= szrout;
+ } else
+ /* otherwise, discard the shift sequence */
+ init_encoding_state(&sc->sc_dst_encoding);
+ init_encoding_state(&sc->sc_src_encoding);
+ *invalids = 0;
+ return (0);
+ }
+
+ /* normal case */
+ for (;;) {
+ if (*inbytes == 0) {
+ ret = get_state_desc_gen(&sc->sc_src_encoding, &state);
+ if (state == _STDENC_SDGEN_INITIAL ||
+ state == _STDENC_SDGEN_STABLE)
+ break;
+ }
+
+ /* save the encoding states for the error recovery */
+ save_encoding_state(&sc->sc_src_encoding);
+ save_encoding_state(&sc->sc_dst_encoding);
+
+ /* mb -> csid/index */
+ tmpin = *in;
+ szrin = szrout = 0;
+ ret = mbtocsx(&sc->sc_src_encoding, &csid, &idx, &tmpin,
+ *inbytes, &szrin, cv->cv_shared->ci_hooks);
+ if (ret)
+ goto err;
+
+ if (szrin == (size_t)-2) {
+ /* incompleted character */
+ ret = get_state_desc_gen(&sc->sc_src_encoding, &state);
+ if (ret) {
+ ret = EINVAL;
+ goto err;
+ }
+ switch (state) {
+ case _STDENC_SDGEN_INITIAL:
+ case _STDENC_SDGEN_STABLE:
+ /* fetch shift sequences only. */
+ goto next;
+ }
+ ret = EINVAL;
+ goto err;
+ }
+ /* convert the character */
+ ret = do_conv(is, &csid, &idx);
+ if (ret) {
+ if (ret == E_NO_CORRESPONDING_CHAR) {
+ inval++;
+ szrout = 0;
+ if ((((flags & _CITRUS_ICONV_F_HIDE_INVALID) == 0) &&
+ !cv->cv_shared->ci_discard_ilseq) &&
+ is->is_use_invalid) {
+ ret = wctombx(&sc->sc_dst_encoding,
+ *out, *outbytes, is->is_invalid,
+ &szrout, cv->cv_shared->ci_hooks);
+ if (ret)
+ goto err;
+ }
+ goto next;
+ } else
+ goto err;
+ }
+ /* csid/index -> mb */
+ ret = cstombx(&sc->sc_dst_encoding,
+ *out, *outbytes, csid, idx, &szrout,
+ cv->cv_shared->ci_hooks);
+ if (ret)
+ goto err;
+next:
+ *inbytes -= tmpin-*in; /* szrin is insufficient on \0. */
+ *in = tmpin;
+ *outbytes -= szrout;
+ *out += szrout;
+ }
+ *invalids = inval;
+
+ return (0);
+
+err:
+ restore_encoding_state(&sc->sc_src_encoding);
+ restore_encoding_state(&sc->sc_dst_encoding);
+ *invalids = inval;
+
+ return (ret);
+}
diff --git a/lib/libiconv_modules/iconv_std/citrus_iconv_std.h b/lib/libiconv_modules/iconv_std/citrus_iconv_std.h
new file mode 100644
index 0000000..3aef79e
--- /dev/null
+++ b/lib/libiconv_modules/iconv_std/citrus_iconv_std.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv_std.h,v 1.1 2003/06/25 09:51:44 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_STD_H_
+#define _CITRUS_ICONV_STD_H_
+
+#include "citrus_iconv_std_local.h"
+
+_CITRUS_ICONV_GETOPS_FUNC(iconv_std);
+
+#endif
diff --git a/lib/libiconv_modules/iconv_std/citrus_iconv_std_local.h b/lib/libiconv_modules/iconv_std/citrus_iconv_std_local.h
new file mode 100644
index 0000000..6e83730
--- /dev/null
+++ b/lib/libiconv_modules/iconv_std/citrus_iconv_std_local.h
@@ -0,0 +1,82 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv_std_local.h,v 1.2 2003/07/01 09:42:16 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_STD_LOCAL_H_
+#define _CITRUS_ICONV_STD_LOCAL_H_
+
+/*
+ * encoding
+ */
+struct _citrus_iconv_std_encoding {
+ struct _citrus_stdenc *se_handle;
+ void *se_ps;
+ void *se_pssaved;
+};
+
+/*
+ * dst
+ */
+struct _citrus_iconv_std_dst {
+ TAILQ_ENTRY(_citrus_iconv_std_dst) sd_entry;
+ struct _citrus_csmapper *sd_mapper;
+ _citrus_csid_t sd_csid;
+ unsigned long sd_norm;
+};
+TAILQ_HEAD(_citrus_iconv_std_dst_list, _citrus_iconv_std_dst);
+
+/*
+ * src
+ */
+struct _citrus_iconv_std_src {
+ TAILQ_ENTRY(_citrus_iconv_std_src) ss_entry;
+ struct _citrus_iconv_std_dst_list ss_dsts;
+ _citrus_csid_t ss_csid;
+};
+TAILQ_HEAD(_citrus_iconv_std_src_list, _citrus_iconv_std_src);
+
+/*
+ * iconv_std handle
+ */
+struct _citrus_iconv_std_shared {
+ struct _citrus_stdenc *is_dst_encoding;
+ struct _citrus_stdenc *is_src_encoding;
+ struct _citrus_iconv_std_src_list is_srcs;
+ _citrus_wc_t is_invalid;
+ int is_use_invalid;
+};
+
+/*
+ * iconv_std context
+ */
+struct _citrus_iconv_std_context {
+ struct _citrus_iconv_std_encoding sc_dst_encoding;
+ struct _citrus_iconv_std_encoding sc_src_encoding;
+};
+
+#endif
diff --git a/lib/libiconv_modules/mapper_646/Makefile b/lib/libiconv_modules/mapper_646/Makefile
new file mode 100644
index 0000000..7a524f4
--- /dev/null
+++ b/lib/libiconv_modules/mapper_646/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+SHLIB= mapper_646
+SRCS= citrus_mapper_646.c
+
+WARNS?= 2
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/mapper_646/citrus_mapper_646.c b/lib/libiconv_modules/mapper_646/citrus_mapper_646.c
new file mode 100644
index 0000000..b277549
--- /dev/null
+++ b/lib/libiconv_modules/mapper_646/citrus_mapper_646.c
@@ -0,0 +1,249 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_646.c,v 1.4 2003/07/14 11:37:49 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#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_bcs.h"
+#include "citrus_module.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_mapper_646.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_646);
+_CITRUS_MAPPER_DEF_OPS(mapper_646);
+
+/* ---------------------------------------------------------------------- */
+
+#define ILSEQ 0xFFFFFFFE
+#define INVALID 0xFFFFFFFF
+#define SPECIALS(x) \
+ x(0x23) \
+ x(0x24) \
+ x(0x40) \
+ x(0x5B) \
+ x(0x5C) \
+ x(0x5D) \
+ x(0x5E) \
+ x(0x60) \
+ x(0x7B) \
+ x(0x7C) \
+ x(0x7D) \
+ x(0x7E)
+
+#define INDEX(x) INDEX_##x,
+
+enum {
+ SPECIALS(INDEX)
+ NUM_OF_SPECIALS
+};
+struct _citrus_mapper_646 {
+ _index_t m6_map[NUM_OF_SPECIALS];
+ int m6_forward;
+};
+
+int
+_citrus_mapper_646_mapper_getops(struct _citrus_mapper_ops *ops)
+{
+
+ memcpy(ops, &_citrus_mapper_646_mapper_ops,
+ sizeof(_citrus_mapper_646_mapper_ops));
+
+ return (0);
+}
+
+#define T_COMM '#'
+static int
+parse_file(struct _citrus_mapper_646 *m6, const char *path)
+{
+ struct _memstream ms;
+ struct _region r;
+ const char *p;
+ char *pp;
+ size_t len;
+ char buf[PATH_MAX];
+ int i, ret;
+
+ ret = _map_file(&r, path);
+ if (ret)
+ return (ret);
+ _memstream_bind(&ms, &r);
+ for (i = 0; i < NUM_OF_SPECIALS; i++) {
+retry:
+ p = _memstream_getln(&ms, &len);
+ if (p == NULL) {
+ ret = EINVAL;
+ break;
+ }
+ p = _bcs_skip_ws_len(p, &len);
+ if (*p == T_COMM || len==0)
+ goto retry;
+ if (!_bcs_isdigit(*p)) {
+ ret = EINVAL;
+ break;
+ }
+ snprintf(buf, sizeof(buf), "%.*s", (int)len, p);
+ pp = __DECONST(void *, p);
+ m6->m6_map[i] = strtoul(buf, (char **)&pp, 0);
+ p = _bcs_skip_ws(buf);
+ if (*p != T_COMM && !*p) {
+ ret = EINVAL;
+ break;
+ }
+ }
+ _unmap_file(&r);
+
+ return (ret);
+};
+
+static int
+parse_var(struct _citrus_mapper_646 *m6, struct _memstream *ms,
+ const char *dir)
+{
+ struct _region r;
+ char path[PATH_MAX];
+
+ m6->m6_forward = 1;
+ _memstream_skip_ws(ms);
+ /* whether backward */
+ if (_memstream_peek(ms) == '!') {
+ _memstream_getc(ms);
+ m6->m6_forward = 0;
+ }
+ /* get description file path */
+ _memstream_getregion(ms, &r, _memstream_remainder(ms));
+ snprintf(path, sizeof(path), "%s/%.*s",
+ dir, (int)_region_size(&r), (char *)_region_head(&r));
+ /* remove trailing white spaces */
+ path[_bcs_skip_nonws(path)-path] = '\0';
+ return (parse_file(m6, path));
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_646_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
+ struct _citrus_mapper * __restrict cm, const char * __restrict dir,
+ const void * __restrict var, size_t lenvar,
+ struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
+{
+ struct _citrus_mapper_646 *m6;
+ struct _memstream ms;
+ struct _region r;
+ int ret;
+
+ if (lenmt < sizeof(*mt))
+ return (EINVAL);
+
+ m6 = malloc(sizeof(*m6));
+ if (m6 == NULL)
+ return (errno);
+
+ _region_init(&r, __DECONST(void *, var), lenvar);
+ _memstream_bind(&ms, &r);
+ ret = parse_var(m6, &ms, dir);
+ if (ret) {
+ free(m6);
+ return (ret);
+ }
+
+ cm->cm_closure = m6;
+ mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */
+ mt->mt_state_size = 0; /* stateless */
+
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_646_mapper_uninit(struct _citrus_mapper *cm)
+{
+
+ if (cm && cm->cm_closure)
+ free(cm->cm_closure);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_646_mapper_convert(struct _citrus_mapper * __restrict cm,
+ _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
+{
+ struct _citrus_mapper_646 *m6;
+
+ m6 = cm->cm_closure;
+ if (m6->m6_forward) {
+ /* forward */
+ if (src >= 0x80)
+ return (_MAPPER_CONVERT_ILSEQ);
+#define FORWARD(x) \
+if (src == (x)) { \
+ if (m6->m6_map[INDEX_##x]==INVALID) \
+ return (_MAPPER_CONVERT_NONIDENTICAL); \
+ *dst = m6->m6_map[INDEX_##x]; \
+ return (0); \
+} else
+ SPECIALS(FORWARD);
+ *dst = src;
+ } else {
+ /* backward */
+#define BACKWARD(x) \
+if (m6->m6_map[INDEX_##x] != INVALID && src == m6->m6_map[INDEX_##x]) { \
+ *dst = (x); \
+ return (0); \
+} else if (src == (x)) \
+ return (_MAPPER_CONVERT_ILSEQ); \
+else
+ SPECIALS(BACKWARD);
+ if (src >= 0x80)
+ return (_MAPPER_CONVERT_NONIDENTICAL);
+ *dst = src;
+ }
+
+ return (_MAPPER_CONVERT_SUCCESS);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_646_mapper_init_state(void)
+{
+
+}
diff --git a/lib/libiconv_modules/mapper_646/citrus_mapper_646.h b/lib/libiconv_modules/mapper_646/citrus_mapper_646.h
new file mode 100644
index 0000000..2fd9170
--- /dev/null
+++ b/lib/libiconv_modules/mapper_646/citrus_mapper_646.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_646.h,v 1.1 2003/06/25 09:51:45 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_646_H_
+#define _CITRUS_MAPPER_646_H_
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_646);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/mapper_none/Makefile b/lib/libiconv_modules/mapper_none/Makefile
new file mode 100644
index 0000000..4261fe7
--- /dev/null
+++ b/lib/libiconv_modules/mapper_none/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SHLIB= mapper_none
+SRCS+= citrus_mapper_none.c
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/mapper_none/citrus_mapper_none.c b/lib/libiconv_modules/mapper_none/citrus_mapper_none.c
new file mode 100644
index 0000000..b3d2bda
--- /dev/null
+++ b/lib/libiconv_modules/mapper_none/citrus_mapper_none.c
@@ -0,0 +1,104 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_none.c,v 1.2 2003/06/27 17:53:31 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/queue.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_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_mapper_none.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_none);
+_CITRUS_MAPPER_DEF_OPS(mapper_none);
+
+
+/* ---------------------------------------------------------------------- */
+
+int
+_citrus_mapper_none_mapper_getops(struct _citrus_mapper_ops *ops)
+{
+
+ memcpy(ops, &_citrus_mapper_none_mapper_ops,
+ sizeof(_citrus_mapper_none_mapper_ops));
+
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_none_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
+ struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused,
+ const void * __restrict var __unused, size_t lenvar __unused,
+ struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
+{
+
+ if (lenmt < sizeof(*mt))
+ return (EINVAL);
+
+ cm->cm_closure = NULL;
+ mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */
+ mt->mt_state_size = 0; /* stateless */
+
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_none_mapper_uninit(struct _citrus_mapper *cm __unused)
+{
+
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_none_mapper_convert(struct _citrus_mapper * __restrict cm __unused,
+ _citrus_index_t * __restrict dst, _citrus_index_t src,
+ void * __restrict ps __unused)
+{
+
+ *dst = src;
+ return (_CITRUS_MAPPER_CONVERT_SUCCESS);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_none_mapper_init_state(void)
+{
+
+}
diff --git a/lib/libiconv_modules/mapper_none/citrus_mapper_none.h b/lib/libiconv_modules/mapper_none/citrus_mapper_none.h
new file mode 100644
index 0000000..9b4e07d
--- /dev/null
+++ b/lib/libiconv_modules/mapper_none/citrus_mapper_none.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_none.h,v 1.1 2003/06/25 09:51:45 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_NONE_H_
+#define _CITRUS_MAPPER_NONE_H_
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_none);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/mapper_parallel/Makefile b/lib/libiconv_modules/mapper_parallel/Makefile
new file mode 100644
index 0000000..000c1cd
--- /dev/null
+++ b/lib/libiconv_modules/mapper_parallel/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../mapper_serial
+
+SHLIB= mapper_parallel
+SRCS+= citrus_mapper_serial.c
+CFLAGS+= --param max-inline-insns-single=32
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/mapper_serial/Makefile b/lib/libiconv_modules/mapper_serial/Makefile
new file mode 100644
index 0000000..67d4bb0
--- /dev/null
+++ b/lib/libiconv_modules/mapper_serial/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= mapper_serial
+SRCS+= citrus_mapper_serial.c
+CFLAGS+= --param max-inline-insns-single=32
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.c b/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.c
new file mode 100644
index 0000000..87f362a
--- /dev/null
+++ b/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.c
@@ -0,0 +1,246 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#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_bcs.h"
+#include "citrus_module.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_mapper_serial.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_serial);
+_CITRUS_MAPPER_DEF_OPS(mapper_serial);
+
+#define _citrus_mapper_parallel_mapper_init \
+ _citrus_mapper_serial_mapper_init
+#define _citrus_mapper_parallel_mapper_uninit \
+ _citrus_mapper_serial_mapper_uninit
+#define _citrus_mapper_parallel_mapper_init_state \
+ _citrus_mapper_serial_mapper_init_state
+static int _citrus_mapper_parallel_mapper_convert(
+ struct _citrus_mapper * __restrict, _index_t * __restrict,
+ _index_t, void * __restrict);
+_CITRUS_MAPPER_DEF_OPS(mapper_parallel);
+#undef _citrus_mapper_parallel_mapper_init
+#undef _citrus_mapper_parallel_mapper_uninit
+#undef _citrus_mapper_parallel_mapper_init_state
+
+
+/* ---------------------------------------------------------------------- */
+
+struct maplink {
+ STAILQ_ENTRY(maplink) ml_entry;
+ struct _mapper *ml_mapper;
+};
+STAILQ_HEAD(maplist, maplink);
+
+struct _citrus_mapper_serial {
+ struct maplist sr_mappers;
+};
+
+int
+_citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops)
+{
+
+ memcpy(ops, &_citrus_mapper_serial_mapper_ops,
+ sizeof(_citrus_mapper_serial_mapper_ops));
+
+ return (0);
+}
+
+int
+_citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops)
+{
+
+ memcpy(ops, &_citrus_mapper_parallel_mapper_ops,
+ sizeof(_citrus_mapper_parallel_mapper_ops));
+
+ return (0);
+}
+
+static void
+uninit(struct _citrus_mapper_serial *sr)
+{
+ struct maplink *ml;
+
+ while ((ml = STAILQ_FIRST(&sr->sr_mappers)) != NULL) {
+ STAILQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry);
+ _mapper_close(ml->ml_mapper);
+ free(ml);
+ }
+}
+
+static int
+parse_var(struct _citrus_mapper_area *__restrict ma,
+ struct _citrus_mapper_serial *sr, struct _memstream *ms)
+{
+ struct _region r;
+ struct maplink *ml;
+ char mapname[PATH_MAX];
+ int ret;
+
+ STAILQ_INIT(&sr->sr_mappers);
+ while (1) {
+ /* remove beginning white spaces */
+ _memstream_skip_ws(ms);
+ if (_memstream_iseof(ms))
+ break;
+ /* cut down a mapper name */
+ _memstream_chr(ms, &r, ',');
+ snprintf(mapname, sizeof(mapname), "%.*s",
+ (int)_region_size(&r), (char *)_region_head(&r));
+ /* remove trailing white spaces */
+ mapname[_bcs_skip_nonws(mapname)-mapname] = '\0';
+ /* create a new mapper record */
+ ml = malloc(sizeof(*ml));
+ if (ml == NULL)
+ return (errno);
+ ret = _mapper_open(ma, &ml->ml_mapper, mapname);
+ if (ret) {
+ free(ml);
+ return (ret);
+ }
+ /* support only 1:1 and stateless converter */
+ if (_mapper_get_src_max(ml->ml_mapper) != 1 ||
+ _mapper_get_dst_max(ml->ml_mapper) != 1 ||
+ _mapper_get_state_size(ml->ml_mapper) != 0) {
+ free(ml);
+ return (EINVAL);
+ }
+ STAILQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry);
+ }
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_serial_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
+ struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused,
+ const void * __restrict var, size_t lenvar,
+ struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
+{
+ struct _citrus_mapper_serial *sr;
+ struct _memstream ms;
+ struct _region r;
+
+ if (lenmt < sizeof(*mt))
+ return (EINVAL);
+
+ sr = malloc(sizeof(*sr));
+ if (sr == NULL)
+ return (errno);
+
+ _region_init(&r, __DECONST(void *, var), lenvar);
+ _memstream_bind(&ms, &r);
+ if (parse_var(ma, sr, &ms)) {
+ uninit(sr);
+ free(sr);
+ return (EINVAL);
+ }
+ cm->cm_closure = sr;
+ mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */
+ mt->mt_state_size = 0; /* stateless */
+
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm)
+{
+
+ if (cm && cm->cm_closure) {
+ uninit(cm->cm_closure);
+ free(cm->cm_closure);
+ }
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm,
+ _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
+{
+ struct _citrus_mapper_serial *sr;
+ struct maplink *ml;
+ int ret;
+
+ sr = cm->cm_closure;
+ STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) {
+ ret = _mapper_convert(ml->ml_mapper, &src, src, NULL);
+ if (ret != _MAPPER_CONVERT_SUCCESS)
+ return (ret);
+ }
+ *dst = src;
+ return (_MAPPER_CONVERT_SUCCESS);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm,
+ _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
+{
+ struct _citrus_mapper_serial *sr;
+ struct maplink *ml;
+ _index_t tmp;
+ int ret;
+
+ sr = cm->cm_closure;
+ STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) {
+ ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL);
+ if (ret == _MAPPER_CONVERT_SUCCESS) {
+ *dst = tmp;
+ return (_MAPPER_CONVERT_SUCCESS);
+ } else if (ret == _MAPPER_CONVERT_ILSEQ)
+ return (_MAPPER_CONVERT_ILSEQ);
+ }
+ return (_MAPPER_CONVERT_NONIDENTICAL);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_serial_mapper_init_state(void)
+{
+
+}
diff --git a/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.h b/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.h
new file mode 100644
index 0000000..02cb9b1
--- /dev/null
+++ b/lib/libiconv_modules/mapper_serial/citrus_mapper_serial.h
@@ -0,0 +1,38 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_serial.h,v 1.1 2003/06/25 09:51:46 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_SERIAL_H_
+#define _CITRUS_MAPPER_SERIAL_H_
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_serial);
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_parallel);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/mapper_std/Makefile b/lib/libiconv_modules/mapper_std/Makefile
new file mode 100644
index 0000000..0d35e90
--- /dev/null
+++ b/lib/libiconv_modules/mapper_std/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= mapper_std
+SRCS+= citrus_mapper_std.c
+CFLAGS+= --param max-inline-insns-single=8
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/mapper_std/citrus_mapper_std.c b/lib/libiconv_modules/mapper_std/citrus_mapper_std.c
new file mode 100644
index 0000000..bc75643
--- /dev/null
+++ b/lib/libiconv_modules/mapper_std/citrus_mapper_std.c
@@ -0,0 +1,435 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_std.c,v 1.8 2006/09/11 13:06:33 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2003, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/endian.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.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_mmap.h"
+#include "citrus_module.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_db.h"
+#include "citrus_db_hash.h"
+
+#include "citrus_mapper_std.h"
+#include "citrus_mapper_std_file.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_std);
+_CITRUS_MAPPER_DEF_OPS(mapper_std);
+
+
+/* ---------------------------------------------------------------------- */
+
+int
+_citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops *ops)
+{
+
+ memcpy(ops, &_citrus_mapper_std_mapper_ops,
+ sizeof(_citrus_mapper_std_mapper_ops));
+
+ return (0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int
+/*ARGSUSED*/
+rowcol_convert(struct _citrus_mapper_std * __restrict ms,
+ _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
+{
+ struct _citrus_mapper_std_linear_zone *lz;
+ struct _citrus_mapper_std_rowcol *rc;
+ _index_t idx = 0, n;
+ size_t i;
+ uint32_t conv;
+
+ /* ps may be unused */
+ rc = &ms->ms_rowcol;
+
+ for (i = rc->rc_src_rowcol_len * rc->rc_src_rowcol_bits,
+ lz = &rc->rc_src_rowcol[0]; i > 0; ++lz) {
+ i -= rc->rc_src_rowcol_bits;
+ n = (src >> i) & rc->rc_src_rowcol_mask;
+ if (n < lz->begin || n > lz->end) {
+ switch (rc->rc_oob_mode) {
+ case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL:
+ *dst = rc->rc_dst_invalid;
+ return (_MAPPER_CONVERT_NONIDENTICAL);
+ case _CITRUS_MAPPER_STD_OOB_ILSEQ:
+ return (_MAPPER_CONVERT_ILSEQ);
+ default:
+ return (_MAPPER_CONVERT_FATAL);
+ }
+ }
+ idx = idx * lz->width + n - lz->begin;
+ }
+ switch (rc->rc_dst_unit_bits) {
+ case 8:
+ conv = _region_peek8(&rc->rc_table, idx);
+ break;
+ case 16:
+ conv = be16toh(_region_peek16(&rc->rc_table, idx*2));
+ break;
+ case 32:
+ conv = be32toh(_region_peek32(&rc->rc_table, idx*4));
+ break;
+ default:
+ return (_MAPPER_CONVERT_FATAL);
+ }
+
+ if (conv == rc->rc_dst_invalid) {
+ *dst = rc->rc_dst_invalid;
+ return (_MAPPER_CONVERT_NONIDENTICAL);
+ }
+ if (conv == rc->rc_dst_ilseq)
+ return (_MAPPER_CONVERT_ILSEQ);
+
+ *dst = conv;
+
+ return (_MAPPER_CONVERT_SUCCESS);
+}
+
+static __inline int
+set_linear_zone(struct _citrus_mapper_std_linear_zone *lz,
+ uint32_t begin, uint32_t end)
+{
+
+ if (begin > end)
+ return (EFTYPE);
+
+ lz->begin = begin;
+ lz->end = end;
+ lz->width= end - begin + 1;
+
+ return (0);
+}
+
+static __inline int
+rowcol_parse_variable_compat(struct _citrus_mapper_std_rowcol *rc,
+ struct _region *r)
+{
+ const struct _citrus_mapper_std_rowcol_info_compat_x *rcx;
+ struct _citrus_mapper_std_linear_zone *lz;
+ uint32_t m, n;
+ int ret;
+
+ rcx = _region_head(r);
+
+ rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid);
+ rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits);
+ m = be32toh(rcx->rcx_src_col_bits);
+ n = 1 << (m - 1);
+ n |= n - 1;
+ rc->rc_src_rowcol_bits = m;
+ rc->rc_src_rowcol_mask = n;
+
+ rc->rc_src_rowcol = malloc(2 *
+ sizeof(*rc->rc_src_rowcol));
+ if (rc->rc_src_rowcol == NULL)
+ return (ENOMEM);
+ lz = rc->rc_src_rowcol;
+ rc->rc_src_rowcol_len = 1;
+ m = be32toh(rcx->rcx_src_row_begin);
+ n = be32toh(rcx->rcx_src_row_end);
+ if (m + n > 0) {
+ ret = set_linear_zone(lz, m, n);
+ if (ret != 0)
+ return (ret);
+ ++rc->rc_src_rowcol_len, ++lz;
+ }
+ m = be32toh(rcx->rcx_src_col_begin);
+ n = be32toh(rcx->rcx_src_col_end);
+
+ return (set_linear_zone(lz, m, n));
+}
+
+static __inline int
+rowcol_parse_variable(struct _citrus_mapper_std_rowcol *rc,
+ struct _region *r)
+{
+ const struct _citrus_mapper_std_rowcol_info_x *rcx;
+ struct _citrus_mapper_std_linear_zone *lz;
+ size_t i;
+ uint32_t m, n;
+ int ret;
+
+ rcx = _region_head(r);
+
+ rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid);
+ rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits);
+
+ m = be32toh(rcx->rcx_src_rowcol_bits);
+ n = 1 << (m - 1);
+ n |= n - 1;
+ rc->rc_src_rowcol_bits = m;
+ rc->rc_src_rowcol_mask = n;
+
+ rc->rc_src_rowcol_len = be32toh(rcx->rcx_src_rowcol_len);
+ if (rc->rc_src_rowcol_len > _CITRUS_MAPPER_STD_ROWCOL_MAX)
+ return (EFTYPE);
+ rc->rc_src_rowcol = malloc(rc->rc_src_rowcol_len *
+ sizeof(*rc->rc_src_rowcol));
+ if (rc->rc_src_rowcol == NULL)
+ return (ENOMEM);
+ for (i = 0, lz = rc->rc_src_rowcol;
+ i < rc->rc_src_rowcol_len; ++i, ++lz) {
+ m = be32toh(rcx->rcx_src_rowcol[i].begin),
+ n = be32toh(rcx->rcx_src_rowcol[i].end);
+ ret = set_linear_zone(lz, m, n);
+ if (ret != 0) {
+ free(rc->rc_src_rowcol);
+ rc->rc_src_rowcol = NULL;
+ return (ret);
+ }
+ }
+ return (0);
+}
+
+static void
+rowcol_uninit(struct _citrus_mapper_std *ms)
+{
+ struct _citrus_mapper_std_rowcol *rc;
+
+ rc = &ms->ms_rowcol;
+ free(rc->rc_src_rowcol);
+}
+
+static int
+rowcol_init(struct _citrus_mapper_std *ms)
+{
+ struct _citrus_mapper_std_linear_zone *lz;
+ struct _citrus_mapper_std_rowcol *rc;
+ const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x *eix;
+ struct _region r;
+ uint64_t table_size;
+ size_t i;
+ int ret;
+
+ ms->ms_convert = &rowcol_convert;
+ ms->ms_uninit = &rowcol_uninit;
+ rc = &ms->ms_rowcol;
+
+ /* get table region */
+ ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TABLE,
+ &rc->rc_table, NULL);
+ if (ret) {
+ if (ret == ENOENT)
+ ret = EFTYPE;
+ return (ret);
+ }
+
+ /* get table information */
+ ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_INFO, &r, NULL);
+ if (ret) {
+ if (ret == ENOENT)
+ ret = EFTYPE;
+ return (ret);
+ }
+ switch (_region_size(&r)) {
+ case _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE:
+ ret = rowcol_parse_variable_compat(rc, &r);
+ break;
+ case _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE:
+ ret = rowcol_parse_variable(rc, &r);
+ break;
+ default:
+ return (EFTYPE);
+ }
+ if (ret != 0)
+ return (ret);
+ /* sanity check */
+ switch (rc->rc_src_rowcol_bits) {
+ case 8: case 16: case 32:
+ if (rc->rc_src_rowcol_len <= 32 / rc->rc_src_rowcol_bits)
+ break;
+ /*FALLTHROUGH*/
+ default:
+ return (EFTYPE);
+ }
+
+ /* ilseq extension */
+ rc->rc_oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL;
+ rc->rc_dst_ilseq = rc->rc_dst_invalid;
+ ret = _db_lookup_by_s(ms->ms_db,
+ _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ, &r, NULL);
+ if (ret && ret != ENOENT)
+ return (ret);
+ if (_region_size(&r) < sizeof(*eix))
+ return (EFTYPE);
+ if (ret == 0) {
+ eix = _region_head(&r);
+ rc->rc_oob_mode = be32toh(eix->eix_oob_mode);
+ rc->rc_dst_ilseq = be32toh(eix->eix_dst_ilseq);
+ }
+
+ /* calcurate expected table size */
+ i = rc->rc_src_rowcol_len;
+ lz = &rc->rc_src_rowcol[--i];
+ table_size = lz->width;
+ while (i > 0) {
+ lz = &rc->rc_src_rowcol[--i];
+ table_size *= lz->width;
+ }
+ table_size *= rc->rc_dst_unit_bits/8;
+
+ if (table_size > UINT32_MAX ||
+ _region_size(&rc->rc_table) < table_size)
+ return (EFTYPE);
+
+ return (0);
+}
+
+typedef int (*initfunc_t)(struct _citrus_mapper_std *);
+static const struct {
+ initfunc_t t_init;
+ const char *t_name;
+} types[] = {
+ { &rowcol_init, _CITRUS_MAPPER_STD_TYPE_ROWCOL },
+};
+#define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_std_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
+ struct _citrus_mapper * __restrict cm, const char * __restrict curdir,
+ const void * __restrict var, size_t lenvar,
+ struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
+{
+ struct _citrus_mapper_std *ms;
+ char path[PATH_MAX];
+ const char *type;
+ int id, ret;
+
+ /* set traits */
+ if (lenmt < sizeof(*mt)) {
+ ret = EINVAL;
+ goto err0;
+ }
+ mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */
+ mt->mt_state_size = 0; /* stateless */
+
+ /* alloc mapper std structure */
+ ms = malloc(sizeof(*ms));
+ if (ms == NULL) {
+ ret = errno;
+ goto err0;
+ }
+
+ /* open mapper file */
+ snprintf(path, sizeof(path), "%s/%.*s", curdir, (int)lenvar,
+ (const char *)var);
+ ret = _map_file(&ms->ms_file, path);
+ if (ret)
+ goto err1;
+
+ ret = _db_open(&ms->ms_db, &ms->ms_file, _CITRUS_MAPPER_STD_MAGIC,
+ &_db_hash_std, NULL);
+ if (ret)
+ goto err2;
+
+ /* get mapper type */
+ ret = _db_lookupstr_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TYPE,
+ &type, NULL);
+ if (ret) {
+ if (ret == ENOENT)
+ ret = EFTYPE;
+ goto err3;
+ }
+ for (id = 0; id < NUM_OF_TYPES; id++)
+ if (_bcs_strcasecmp(type, types[id].t_name) == 0)
+ break;
+
+ if (id == NUM_OF_TYPES)
+ goto err3;
+
+ /* init the per-type structure */
+ ret = (*types[id].t_init)(ms);
+ if (ret)
+ goto err3;
+
+ cm->cm_closure = ms;
+
+ return (0);
+
+err3:
+ _db_close(ms->ms_db);
+err2:
+ _unmap_file(&ms->ms_file);
+err1:
+ free(ms);
+err0:
+ return (ret);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_std_mapper_uninit(struct _citrus_mapper *cm)
+{
+ struct _citrus_mapper_std *ms;
+
+ ms = cm->cm_closure;
+ if (ms->ms_uninit)
+ (*ms->ms_uninit)(ms);
+ _db_close(ms->ms_db);
+ _unmap_file(&ms->ms_file);
+ free(ms);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_std_mapper_init_state(void)
+{
+
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm,
+ _index_t * __restrict dst, _index_t src, void * __restrict ps)
+{
+ struct _citrus_mapper_std *ms;
+
+ ms = cm->cm_closure;
+ return ((*ms->ms_convert)(ms, dst, src, ps));
+}
diff --git a/lib/libiconv_modules/mapper_std/citrus_mapper_std.h b/lib/libiconv_modules/mapper_std/citrus_mapper_std.h
new file mode 100644
index 0000000..d6a0b62
--- /dev/null
+++ b/lib/libiconv_modules/mapper_std/citrus_mapper_std.h
@@ -0,0 +1,39 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_std.h,v 1.1 2003/06/25 09:51:47 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_STD_H_
+#define _CITRUS_MAPPER_STD_H_
+
+#include "citrus_mapper_std_local.h"
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_std);
+__END_DECLS
+
+#endif
diff --git a/lib/libiconv_modules/mapper_std/citrus_mapper_std_file.h b/lib/libiconv_modules/mapper_std/citrus_mapper_std_file.h
new file mode 100644
index 0000000..d433c74
--- /dev/null
+++ b/lib/libiconv_modules/mapper_std/citrus_mapper_std_file.h
@@ -0,0 +1,76 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_std_file.h,v 1.3 2006/09/09 14:35:17 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2003, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_STD_FILE_H_
+#define _CITRUS_MAPPER_STD_FILE_H_
+
+#define _CITRUS_MAPPER_STD_MAGIC "MAPPER\0\0"
+
+#define _CITRUS_MAPPER_STD_SYM_TYPE "type"
+#define _CITRUS_MAPPER_STD_SYM_INFO "info"
+#define _CITRUS_MAPPER_STD_SYM_TABLE "table"
+
+#define _CITRUS_MAPPER_STD_TYPE_ROWCOL "rowcol"
+struct _citrus_mapper_std_rowcol_info_x {
+ uint32_t rcx_src_rowcol_bits;
+ uint32_t rcx_dst_invalid;
+#define _CITRUS_MAPPER_STD_ROWCOL_MAX 4
+ struct {
+ uint32_t begin;
+ uint32_t end;
+ } __packed rcx_src_rowcol[_CITRUS_MAPPER_STD_ROWCOL_MAX];
+ uint32_t rcx_dst_unit_bits;
+ uint32_t rcx_src_rowcol_len;
+} __packed;
+#define _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE 48
+
+/* old file layout */
+struct _citrus_mapper_std_rowcol_info_compat_x {
+ uint32_t rcx_src_col_bits;
+ uint32_t rcx_dst_invalid;
+ uint32_t rcx_src_row_begin;
+ uint32_t rcx_src_row_end;
+ uint32_t rcx_src_col_begin;
+ uint32_t rcx_src_col_end;
+ uint32_t rcx_dst_unit_bits;
+ uint32_t rcx_pad;
+} __packed;
+#define _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE 32
+
+/* rowcol oob extension info */
+#define _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ "rowcol_ext_ilseq"
+struct _citrus_mapper_std_rowcol_ext_ilseq_info_x {
+#define _CITRUS_MAPPER_STD_OOB_NONIDENTICAL 0
+#define _CITRUS_MAPPER_STD_OOB_ILSEQ 1
+ uint32_t eix_oob_mode;
+ uint32_t eix_dst_ilseq;
+} __packed;
+#define _CITRUS_MAPPER_STD_ROWCOL_EXT_ILSEQ_SIZE 8
+
+#endif
diff --git a/lib/libiconv_modules/mapper_std/citrus_mapper_std_local.h b/lib/libiconv_modules/mapper_std/citrus_mapper_std_local.h
new file mode 100644
index 0000000..f76f606
--- /dev/null
+++ b/lib/libiconv_modules/mapper_std/citrus_mapper_std_local.h
@@ -0,0 +1,71 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_std_local.h,v 1.3 2006/09/09 14:35:17 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2003, 2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_STD_LOCAL_H_
+#define _CITRUS_MAPPER_STD_LOCAL_H_
+
+typedef uint32_t (*_citrus_mapper_std_getvalfunc_t)(const void *, uint32_t);
+
+struct _citrus_mapper_std_linear_zone {
+ _citrus_index_t begin;
+ _citrus_index_t end;
+ _citrus_index_t width;
+};
+struct _citrus_mapper_std_rowcol {
+ struct _citrus_region rc_table;
+ size_t rc_src_rowcol_len;
+ struct _citrus_mapper_std_linear_zone
+ *rc_src_rowcol;
+ _citrus_index_t rc_src_rowcol_bits;
+ _citrus_index_t rc_src_rowcol_mask;
+ _citrus_index_t rc_dst_invalid;
+ _citrus_index_t rc_dst_unit_bits;
+ int rc_oob_mode;
+ _citrus_index_t rc_dst_ilseq;
+};
+
+struct _citrus_mapper_std;
+
+typedef int (*_citrus_mapper_std_convert_t)(
+ struct _citrus_mapper_std *__restrict,
+ _index_t *__restrict, _index_t, void *__restrict);
+typedef void (*_citrus_mapper_std_uninit_t)(struct _citrus_mapper_std *);
+
+struct _citrus_mapper_std {
+ struct _citrus_region ms_file;
+ struct _citrus_db *ms_db;
+ _citrus_mapper_std_convert_t ms_convert;
+ _citrus_mapper_std_uninit_t ms_uninit;
+ union {
+ struct _citrus_mapper_std_rowcol rowcol;
+ } u;
+#define ms_rowcol u.rowcol
+};
+
+#endif
diff --git a/lib/libiconv_modules/mapper_zone/Makefile b/lib/libiconv_modules/mapper_zone/Makefile
new file mode 100644
index 0000000..287bc24
--- /dev/null
+++ b/lib/libiconv_modules/mapper_zone/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+SHLIB= mapper_zone
+SRCS+= citrus_mapper_zone.c
+CFLAGS+= --param max-inline-insns-single=8
+
+.include <bsd.lib.mk>
diff --git a/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.c b/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.c
new file mode 100644
index 0000000..f1117f4
--- /dev/null
+++ b/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.c
@@ -0,0 +1,385 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_zone.c,v 1.4 2003/07/12 15:39:21 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_mapper_zone.h"
+
+/* ---------------------------------------------------------------------- */
+
+_CITRUS_MAPPER_DECLS(mapper_zone);
+_CITRUS_MAPPER_DEF_OPS(mapper_zone);
+
+
+/* ---------------------------------------------------------------------- */
+
+struct _zone {
+ uint32_t z_begin;
+ uint32_t z_end;
+};
+
+struct _citrus_mapper_zone {
+ struct _zone mz_col;
+ struct _zone mz_row;
+ int32_t mz_col_offset;
+ int32_t mz_row_offset;
+ int mz_col_bits;
+};
+
+struct _parse_state {
+ enum { S_BEGIN, S_OFFSET } ps_state;
+ union {
+ uint32_t u_imm;
+ int32_t s_imm;
+ struct _zone zone;
+ } u;
+#define ps_u_imm u.u_imm
+#define ps_s_imm u.s_imm
+#define ps_zone u.zone
+ int ps_top;
+};
+
+int
+_citrus_mapper_zone_mapper_getops(struct _citrus_mapper_ops *ops)
+{
+
+ memcpy(ops, &_citrus_mapper_zone_mapper_ops,
+ sizeof(_citrus_mapper_zone_mapper_ops));
+
+ return (0);
+}
+
+#define BUFSIZE 20
+#define T_ERR 0x100
+#define T_IMM 0x101
+
+static int
+get_imm(struct _memstream *ms, struct _parse_state *ps)
+{
+ int c, i, sign = 0;
+ char buf[BUFSIZE + 1];
+ char *p;
+
+ for (i = 0; i < BUFSIZE; i++) {
+retry:
+ c = _memstream_peek(ms);
+ if (i == 0) {
+ if (sign == 0 && (c == '+' || c == '-')) {
+ sign = c;
+ _memstream_getc(ms);
+ goto retry;
+ } else if (!_bcs_isdigit(c))
+ break;
+ } else if (!_bcs_isxdigit(c))
+ if (!(i == 1 && c == 'x'))
+ break;
+ buf[i] = _memstream_getc(ms);
+ }
+ buf[i] = '\0';
+ ps->ps_u_imm = strtoul(buf, &p, 0);
+ if ((p - buf) != i)
+ return (T_ERR);
+ if (sign == '-')
+ ps->ps_u_imm = (unsigned long)-(long)ps->ps_u_imm;
+ return (T_IMM);
+}
+
+static int
+get_tok(struct _memstream *ms, struct _parse_state *ps)
+{
+ int c;
+
+loop:
+ c = _memstream_peek(ms);
+ if (c == 0x00)
+ return (EOF);
+ if (_bcs_isspace(c)) {
+ _memstream_getc(ms);
+ goto loop;
+ }
+
+ switch (ps->ps_state) {
+ case S_BEGIN:
+ switch (c) {
+ case ':':
+ case '-':
+ case '/':
+ _memstream_getc(ms);
+ return (c);
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return (get_imm(ms, ps));
+ }
+ break;
+ case S_OFFSET:
+ switch (c) {
+ case '/':
+ _memstream_getc(ms);
+ return (c);
+ case '+':
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return (get_imm(ms, ps));
+ }
+ break;
+ }
+ return (T_ERR);
+}
+
+static int
+parse_zone(struct _memstream *ms, struct _parse_state *ps, struct _zone *z)
+{
+
+ if (get_tok(ms, ps) != T_IMM)
+ return (-1);
+ z->z_begin = ps->ps_u_imm;
+ if (get_tok(ms, ps) != '-')
+ return (-1);
+ if (get_tok(ms, ps) != T_IMM)
+ return (-1);
+ z->z_end = ps->ps_u_imm;
+
+ if (z->z_begin > z->z_end)
+ return (-1);
+
+ return (0);
+}
+
+static int
+check_rowcol(struct _zone *z, int32_t ofs, uint32_t maxval)
+{
+ uint32_t remain;
+
+ if (maxval != 0 && z->z_end >= maxval)
+ return (-1);
+
+ if (ofs > 0) {
+ if (maxval == 0)
+ /* this should 0x100000000 - z->z_end */
+ remain = (z->z_end == 0) ? 0xFFFFFFFF :
+ 0xFFFFFFFF - z->z_end + 1;
+ else
+ remain = maxval - z->z_end;
+ if ((uint32_t)ofs > remain)
+ return (-1);
+ } else if (ofs < 0) {
+ if (z->z_begin < (uint32_t)-ofs)
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+parse_var(struct _citrus_mapper_zone *mz, struct _memstream *ms)
+{
+ struct _parse_state ps;
+ uint32_t colmax, rowmax;
+ int isrc, ret;
+
+ ps.ps_state = S_BEGIN;
+
+ if (parse_zone(ms, &ps, &mz->mz_col))
+ return (-1);
+
+ ret = get_tok(ms, &ps);
+ if (ret == '/') {
+ /* rowzone / colzone / bits */
+ isrc = 1;
+ mz->mz_row = mz->mz_col;
+
+ if (parse_zone(ms, &ps, &mz->mz_col))
+ return (-1);
+ if (get_tok(ms, &ps) != '/')
+ return (-1);
+ if (get_tok(ms, &ps) != T_IMM)
+ return (-1);
+ mz->mz_col_bits = ps.ps_u_imm;
+ if (mz->mz_col_bits < 0 || mz->mz_col_bits > 32)
+ return (-1);
+ ret = get_tok(ms, &ps);
+ } else {
+ /* colzone */
+ isrc = 0;
+ mz->mz_col_bits = 32;
+ mz->mz_row.z_begin = mz->mz_row.z_end = 0;
+ }
+ if (ret == ':') {
+ /* offset */
+ ps.ps_state = S_OFFSET;
+ if (get_tok(ms, &ps) != T_IMM)
+ return (-1);
+ mz->mz_col_offset = ps.ps_s_imm;
+ if (isrc) {
+ /* row/col */
+ mz->mz_row_offset = mz->mz_col_offset;
+ if (get_tok(ms, &ps) != '/')
+ return (-1);
+ if (get_tok(ms, &ps) != T_IMM)
+ return (-1);
+ mz->mz_col_offset = ps.ps_s_imm;
+ } else
+ mz->mz_row_offset = 0;
+ ret = get_tok(ms, &ps);
+ }
+ if (ret != EOF)
+ return (-1);
+
+ /* sanity check */
+ colmax = (mz->mz_col_bits == 32) ? 0 : 1 << mz->mz_col_bits;
+ rowmax = (mz->mz_col_bits == 0) ? 0 : 1 << (32-mz->mz_col_bits);
+ if (check_rowcol(&mz->mz_col, mz->mz_col_offset, colmax))
+ return (-1);
+ if (check_rowcol(&mz->mz_row, mz->mz_row_offset, rowmax))
+ return (-1);
+
+ return (0);
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_zone_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
+ struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused,
+ const void * __restrict var, size_t lenvar,
+ struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
+{
+ struct _citrus_mapper_zone *mz;
+ struct _memstream ms;
+ struct _region r;
+
+ if (lenmt < sizeof(*mt))
+ return (EINVAL);
+
+ mz = malloc(sizeof(*mz));
+ if (mz == NULL)
+ return (errno);
+
+ mz->mz_col.z_begin = mz->mz_col.z_end = 0;
+ mz->mz_row.z_begin = mz->mz_row.z_end = 0;
+ mz->mz_col_bits = 0;
+ mz->mz_row_offset = 0;
+ mz->mz_col_offset = 0;
+
+ _region_init(&r, __DECONST(void *, var), lenvar);
+ _memstream_bind(&ms, &r);
+ if (parse_var(mz, &ms)) {
+ free(mz);
+ return (EINVAL);
+ }
+ cm->cm_closure = mz;
+ mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */
+ mt->mt_state_size = 0; /* stateless */
+
+ return (0);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_zone_mapper_uninit(struct _citrus_mapper *cm __unused)
+{
+
+}
+
+static int
+/*ARGSUSED*/
+_citrus_mapper_zone_mapper_convert(struct _citrus_mapper * __restrict cm,
+ _citrus_index_t * __restrict dst, _citrus_index_t src,
+ void * __restrict ps __unused)
+{
+ struct _citrus_mapper_zone *mz = cm->cm_closure;
+ uint32_t col, row;
+
+ if (mz->mz_col_bits == 32) {
+ col = src;
+ row = 0;
+ if (col < mz->mz_col.z_begin || col > mz->mz_col.z_end)
+ return (_CITRUS_MAPPER_CONVERT_NONIDENTICAL);
+ if (mz->mz_col_offset > 0)
+ col += (uint32_t)mz->mz_col_offset;
+ else
+ col -= (uint32_t)-mz->mz_col_offset;
+ *dst = col;
+ } else {
+ col = src & (((uint32_t)1 << mz->mz_col_bits) - 1);
+ row = src >> mz->mz_col_bits;
+ if (row < mz->mz_row.z_begin || row > mz->mz_row.z_end ||
+ col < mz->mz_col.z_begin || col > mz->mz_col.z_end)
+ return (_CITRUS_MAPPER_CONVERT_NONIDENTICAL);
+ if (mz->mz_col_offset > 0)
+ col += (uint32_t)mz->mz_col_offset;
+ else
+ col -= (uint32_t)-mz->mz_col_offset;
+ if (mz->mz_row_offset > 0)
+ row += (uint32_t)mz->mz_row_offset;
+ else
+ row -= (uint32_t)-mz->mz_row_offset;
+ *dst = col | (row << mz->mz_col_bits);
+ }
+ return (_CITRUS_MAPPER_CONVERT_SUCCESS);
+}
+
+static void
+/*ARGSUSED*/
+_citrus_mapper_zone_mapper_init_state(void)
+{
+
+}
diff --git a/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.h b/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.h
new file mode 100644
index 0000000..590cee6
--- /dev/null
+++ b/lib/libiconv_modules/mapper_zone/citrus_mapper_zone.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_zone.h,v 1.1 2003/06/25 09:51:48 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_ZONE_H_
+#define _CITRUS_MAPPER_ZONE_H_
+
+__BEGIN_DECLS
+_CITRUS_MAPPER_GETOPS_FUNC(mapper_zone);
+__END_DECLS
+
+#endif
OpenPOWER on IntegriCloud