summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorgabor <gabor@FreeBSD.org>2011-02-25 00:04:39 +0000
committergabor <gabor@FreeBSD.org>2011-02-25 00:04:39 +0000
commitc91ab1769b1237e3663d59888cebe31ceee47570 (patch)
treeed256cfe2a006269f4a380597f93880be8d5c1cd /lib
parent5aabdb149c1a96a1e9717d45fde4096807423095 (diff)
downloadFreeBSD-src-c91ab1769b1237e3663d59888cebe31ceee47570.zip
FreeBSD-src-c91ab1769b1237e3663d59888cebe31ceee47570.tar.gz
Add the BSD-licensed Citrus iconv to the base system with default off
setting. It can be built by setting the WITH_ICONV knob. While this knob is unset, the library part, the binaries, the header file and the metadata files will not be built or installed so it makes no impact on the system if left turned off. This work is based on the iconv implementation in NetBSD but a great number of improvements and feature additions have been included: - Some utilities have been added. There is a conversion table generator, which can compare conversion tables to reference data generated by GNU libiconv. This helps ensuring conversion compatibility. - UTF-16 surrogate support and some endianness issues have been fixed. - The rather chaotic Makefiles to build metadata have been refactored and cleaned up, now it is easy to read and it is also easier to add support for new encodings. - A bunch of new encodings and encoding aliases have been added. - Support for 1->2, 1->3 and 1->4 mappings, which is needed for transliterating with flying accents as GNU does, like "u. - Lots of warnings have been fixed, the major part of the code is now WARNS=6 clean. - New section 1 and section 5 manual pages have been added. - Some GNU-specific calls have been implemented: iconvlist(), iconvctl(), iconv_canonicalize(), iconv_open_into() - Support for GNU's //IGNORE suffix has been added. - The "-" argument for stdin is now recognized in iconv(1) as per POSIX. - The Big5 conversion module has been fixed. - The iconv.h header files is supposed to be compatible with the GNU version, i.e. sources should build with base iconv.h and GNU libiconv. It also includes a macro magic to deal with the char ** and const char ** incompatibility. - GNU compatibility: "" or "char" means the current local encoding in use - Various cleanups and style(9) fixes. Approved by: delphij (mentor) Obtained from: The NetBSD Project Sponsored by: Google Summer of Code 2009
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