guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] GNU Guile branch, string_abstraction2, updated. b507262d


From: Michael Gran
Subject: [Guile-commits] GNU Guile branch, string_abstraction2, updated. b507262d75db26b6034328396b0be8837f2d1437
Date: Fri, 22 May 2009 02:11:58 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

http://git.savannah.gnu.org/cgit/guile.git/commit/?id=b507262d75db26b6034328396b0be8837f2d1437

The branch, string_abstraction2 has been updated
       via  b507262d75db26b6034328396b0be8837f2d1437 (commit)
       via  03455b48fe28003b8cf1333ba593224d8fe34e2e (commit)
      from  c9dc2528cfdc97351f5f9182e5b9b66ba2d2c21f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit b507262d75db26b6034328396b0be8837f2d1437
Author: Michael Gran <address@hidden>
Date:   Thu May 21 19:06:23 2009 -0700

    Use Latin1 & UTF-32 as internal string encoding
    
        * test-suite/tests/ports.test: Tests now require that a binary
        encoding be specified
    
        * test-suite/tests/i18n.test: Tests now require that a Latin1
        encoding be declared.
    
        * m4/gnulib-cache.m4: New funcs needed for locale
        conversion (striconveh).
    
        * libguile/throw.c: wide-string aware throw/catch messages
    
        * libguile/strings.h: Declare new funcs
        scm_set_conversion_error_behavior_x scm_i_make_wide_string
        scm_i_string_set_from_wchar scm_i_symbol_wide_chars
        scm_i_is_narrow_symbol
    
        * libguile/strings.c: change the internal representation of
        strings to be with Latin1 or UTF-32.  Add helper funcs to convert
        between latin1 and utf-32.  Add helper funcs to access wide string
        internals, especially scm_i_string_wide_chars.  Add functionality
        to control decoding error behavior, including func
        set-conversion-error-behavior!
    
        * libguile/posix.h: new func setbinary
    
        * libguile/posix.c: set the port character encoding when setlocale
        is called.  New func setbinary to unset the port character encoding.
    
        * libguile/ports.c (scm_lfwrite_substr): convert strings to the
          locale instead of unpacking them.
    
        * lib/Makefile.am: gnulib update
    
        * a bunch of gnulib files

commit 03455b48fe28003b8cf1333ba593224d8fe34e2e
Author: Michael Gran <address@hidden>
Date:   Wed May 20 21:30:19 2009 -0700

    string abstraction -- avoid unpacking strings in gentemp
    
        * libguile/deprecated.c: use scm_to_locale_string instead
          of scm_i_string_chars in gentemp

-----------------------------------------------------------------------

Summary of changes:
 lib/Makefile.am                   |  170 +++++-
 lib/alloca.h                      |   57 ++
 lib/c-ctype.c                     |  396 ++++++++++++
 lib/c-ctype.h                     |  295 +++++++++
 lib/c-strcase.h                   |   55 ++
 lib/c-strcasecmp.c                |   57 ++
 lib/c-strcaseeq.h                 |  184 ++++++
 lib/c-strncasecmp.c               |   57 ++
 lib/charset.alias                 |    5 +
 lib/configmake.h                  |   26 +
 lib/iconv.in.h                    |   71 +++
 lib/iconv_open-aix.gperf          |   44 ++
 lib/iconv_open-aix.h              |  256 ++++++++
 lib/iconv_open-hpux.gperf         |   56 ++
 lib/iconv_open-hpux.h             |  299 +++++++++
 lib/iconv_open-irix.gperf         |   31 +
 lib/iconv_open-irix.h             |  199 ++++++
 lib/iconv_open-osf.gperf          |   50 ++
 lib/iconv_open-osf.h              |  278 ++++++++
 lib/iconv_open.c                  |  172 +++++
 lib/iconveh.h                     |   41 ++
 lib/ref-add.sed                   |   10 +
 lib/ref-del.sed                   |    5 +
 lib/stdint.in.h                   |  567 +++++++++++++++++
 lib/striconveh.c                  | 1251 +++++++++++++++++++++++++++++++++++++
 lib/striconveh.h                  |  120 ++++
 lib/strings.h                     |  119 ++++
 lib/time.h                        |  119 ++++
 lib/unistd.h                      |  607 ++++++++++++++++++
 lib/unistr.h                      |  681 ++++++++++++++++++++
 lib/unistr/u8-mbtouc-aux.c        |  158 +++++
 lib/unistr/u8-mbtouc-unsafe-aux.c |  168 +++++
 lib/unistr/u8-mbtouc-unsafe.c     |  179 ++++++
 lib/unistr/u8-mbtouc.c            |  168 +++++
 lib/unistr/u8-mbtoucr.c           |  285 +++++++++
 lib/unistr/u8-prev.c              |   93 +++
 lib/unistr/u8-uctomb-aux.c        |   69 ++
 lib/unistr/u8-uctomb.c            |   88 +++
 lib/unitypes.h                    |   26 +
 libguile/deprecated.c             |    7 +-
 libguile/ports.c                  |    8 +-
 libguile/posix.c                  |   32 +-
 libguile/posix.h                  |    1 +
 libguile/strings.c                |  678 ++++++++++++++++++---
 libguile/strings.h                |    8 +
 libguile/throw.c                  |    9 +-
 m4/gnulib-cache.m4                |    3 +-
 m4/gnulib-comp.m4                 |   44 ++
 m4/iconv_h.m4                     |   34 +
 m4/iconv_open.m4                  |  237 +++++++
 m4/longlong.m4                    |  106 ++++
 m4/multiarch.m4                   |   65 ++
 m4/stdint.m4                      |  472 ++++++++++++++
 test-suite/tests/i18n.test        |    5 +
 test-suite/tests/ports.test       |    3 +
 55 files changed, 9128 insertions(+), 96 deletions(-)
 create mode 100644 lib/alloca.h
 create mode 100644 lib/c-ctype.c
 create mode 100644 lib/c-ctype.h
 create mode 100644 lib/c-strcase.h
 create mode 100644 lib/c-strcasecmp.c
 create mode 100644 lib/c-strcaseeq.h
 create mode 100644 lib/c-strncasecmp.c
 create mode 100644 lib/charset.alias
 create mode 100644 lib/configmake.h
 create mode 100644 lib/iconv.in.h
 create mode 100644 lib/iconv_open-aix.gperf
 create mode 100644 lib/iconv_open-aix.h
 create mode 100644 lib/iconv_open-hpux.gperf
 create mode 100644 lib/iconv_open-hpux.h
 create mode 100644 lib/iconv_open-irix.gperf
 create mode 100644 lib/iconv_open-irix.h
 create mode 100644 lib/iconv_open-osf.gperf
 create mode 100644 lib/iconv_open-osf.h
 create mode 100644 lib/iconv_open.c
 create mode 100644 lib/iconveh.h
 create mode 100644 lib/ref-add.sed
 create mode 100644 lib/ref-del.sed
 create mode 100644 lib/stdint.in.h
 create mode 100644 lib/striconveh.c
 create mode 100644 lib/striconveh.h
 create mode 100644 lib/strings.h
 create mode 100644 lib/time.h
 create mode 100644 lib/unistd.h
 create mode 100644 lib/unistr.h
 create mode 100644 lib/unistr/u8-mbtouc-aux.c
 create mode 100644 lib/unistr/u8-mbtouc-unsafe-aux.c
 create mode 100644 lib/unistr/u8-mbtouc-unsafe.c
 create mode 100644 lib/unistr/u8-mbtouc.c
 create mode 100644 lib/unistr/u8-mbtoucr.c
 create mode 100644 lib/unistr/u8-prev.c
 create mode 100644 lib/unistr/u8-uctomb-aux.c
 create mode 100644 lib/unistr/u8-uctomb.c
 create mode 100644 lib/unitypes.h
 create mode 100644 m4/iconv_h.m4
 create mode 100644 m4/iconv_open.m4
 create mode 100644 m4/longlong.m4
 create mode 100644 m4/multiarch.m4
 create mode 100644 m4/stdint.m4

diff --git a/lib/Makefile.am b/lib/Makefile.am
index a5bac70..a8e9a85 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -9,9 +9,9 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib 
--m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl 
--libtool --macro-prefix=gl --no-vc-files alloca-opt autobuild count-one-bits 
extensions full-read full-write libunistring strcase strftime
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib 
--m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl 
--libtool --macro-prefix=gl --no-vc-files alloca-opt autobuild count-one-bits 
extensions full-read full-write libunistring strcase strftime striconveh
 
-AUTOMAKE_OPTIONS = 1.5 gnits
+AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects
 
 SUBDIRS =
 noinst_HEADERS =
@@ -54,6 +54,25 @@ EXTRA_DIST += alloca.in.h
 
 ## end   gnulib module alloca-opt
 
+## begin gnulib module c-ctype
+
+libgnu_la_SOURCES += c-ctype.h c-ctype.c
+
+## end   gnulib module c-ctype
+
+## begin gnulib module c-strcase
+
+libgnu_la_SOURCES += c-strcase.h c-strcasecmp.c c-strncasecmp.c
+
+## end   gnulib module c-strcase
+
+## begin gnulib module c-strcaseeq
+
+
+EXTRA_DIST += c-strcaseeq.h
+
+## end   gnulib module c-strcaseeq
+
 ## begin gnulib module configmake
 
 # Retrieve values of the variables through 'configure' followed by
@@ -134,6 +153,12 @@ libgnu_la_SOURCES += full-write.h full-write.c
 
 ## end   gnulib module full-write
 
+## begin gnulib module gperf
+
+GPERF = gperf
+
+## end   gnulib module gperf
+
 ## begin gnulib module havelib
 
 
@@ -141,6 +166,50 @@ EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath
 
 ## end   gnulib module havelib
 
+## begin gnulib module iconv_open
+
+BUILT_SOURCES += $(ICONV_H)
+
+# We need the following in order to create <iconv.h> when the system
+# doesn't have one that works with the given compiler.
+iconv.h: iconv.in.h
+       rm -f address@hidden $@
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+         sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+             -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+             -e 's|@''NEXT_ICONV_H''@|$(NEXT_ICONV_H)|g' \
+             -e 's|@''ICONV_CONST''@|$(ICONV_CONST)|g' \
+             -e 's|@''REPLACE_ICONV''@|$(REPLACE_ICONV)|g' \
+             -e 's|@''REPLACE_ICONV_OPEN''@|$(REPLACE_ICONV_OPEN)|g' \
+             -e 's|@''REPLACE_ICONV_UTF''@|$(REPLACE_ICONV_UTF)|g' \
+             < $(srcdir)/iconv.in.h; \
+       } > address@hidden
+       mv address@hidden $@
+MOSTLYCLEANFILES += iconv.h iconv.h-t
+
+iconv_open-aix.h: iconv_open-aix.gperf
+       $(GPERF) -m 10 $(srcdir)/iconv_open-aix.gperf > 
$(srcdir)/iconv_open-aix.h-t
+       mv $(srcdir)/iconv_open-aix.h-t $(srcdir)/iconv_open-aix.h
+iconv_open-hpux.h: iconv_open-hpux.gperf
+       $(GPERF) -m 10 $(srcdir)/iconv_open-hpux.gperf > 
$(srcdir)/iconv_open-hpux.h-t
+       mv $(srcdir)/iconv_open-hpux.h-t $(srcdir)/iconv_open-hpux.h
+iconv_open-irix.h: iconv_open-irix.gperf
+       $(GPERF) -m 10 $(srcdir)/iconv_open-irix.gperf > 
$(srcdir)/iconv_open-irix.h-t
+       mv $(srcdir)/iconv_open-irix.h-t $(srcdir)/iconv_open-irix.h
+iconv_open-osf.h: iconv_open-osf.gperf
+       $(GPERF) -m 10 $(srcdir)/iconv_open-osf.gperf > 
$(srcdir)/iconv_open-osf.h-t
+       mv $(srcdir)/iconv_open-osf.h-t $(srcdir)/iconv_open-osf.h
+BUILT_SOURCES        += iconv_open-aix.h iconv_open-hpux.h iconv_open-irix.h 
iconv_open-osf.h
+MOSTLYCLEANFILES     += iconv_open-aix.h-t iconv_open-hpux.h-t 
iconv_open-irix.h-t iconv_open-osf.h-t
+MAINTAINERCLEANFILES += iconv_open-aix.h iconv_open-hpux.h iconv_open-irix.h 
iconv_open-osf.h
+EXTRA_DIST           += iconv_open-aix.h iconv_open-hpux.h iconv_open-irix.h 
iconv_open-osf.h
+
+EXTRA_DIST += iconv.in.h iconv_open-aix.gperf iconv_open-hpux.gperf 
iconv_open-irix.gperf iconv_open-osf.gperf iconv_open.c
+
+EXTRA_libgnu_la_SOURCES += iconv_open.c
+
+## end   gnulib module iconv_open
+
 ## begin gnulib module link-warning
 
 LINK_WARNING_H=$(top_srcdir)/build-aux/link-warning.h
@@ -286,6 +355,48 @@ EXTRA_DIST += stdbool.in.h
 
 ## end   gnulib module stdbool
 
+## begin gnulib module stdint
+
+BUILT_SOURCES += $(STDINT_H)
+
+# We need the following in order to create <stdint.h> when the system
+# doesn't have one that works with the given compiler.
+stdint.h: stdint.in.h
+       rm -f address@hidden $@
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         sed -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \
+             -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+             -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+             -e 's|@''NEXT_STDINT_H''@|$(NEXT_STDINT_H)|g' \
+             -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \
+             -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
+             -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \
+             -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \
+             -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
+             -e 
's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
+             -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \
+             -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \
+             -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \
+             -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \
+             -e 
's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \
+             -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \
+             -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \
+             -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \
+             -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \
+             -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \
+             -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \
+             -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \
+             -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \
+             -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \
+             < $(srcdir)/stdint.in.h; \
+       } > address@hidden
+       mv address@hidden $@
+MOSTLYCLEANFILES += stdint.h stdint.h-t
+
+EXTRA_DIST += stdint.in.h
+
+## end   gnulib module stdint
+
 ## begin gnulib module strcase
 
 
@@ -311,6 +422,17 @@ EXTRA_libgnu_la_SOURCES += strftime.c
 
 ## end   gnulib module strftime
 
+## begin gnulib module striconveh
+
+libgnu_la_SOURCES += striconveh.h striconveh.c
+if GL_COND_LIBTOOL
+libgnu_la_LDFLAGS += $(LTLIBICONV)
+endif
+
+EXTRA_DIST += iconveh.h
+
+## end   gnulib module striconveh
+
 ## begin gnulib module strings
 
 BUILT_SOURCES += strings.h
@@ -441,6 +563,50 @@ EXTRA_DIST += unistd.in.h
 
 ## end   gnulib module unistd
 
+## begin gnulib module unistr/base
+
+
+EXTRA_DIST += unistr.h
+
+## end   gnulib module unistr/base
+
+## begin gnulib module unistr/u8-mbtouc
+
+libgnu_la_SOURCES += unistr/u8-mbtouc.c unistr/u8-mbtouc-aux.c
+
+## end   gnulib module unistr/u8-mbtouc
+
+## begin gnulib module unistr/u8-mbtouc-unsafe
+
+libgnu_la_SOURCES += unistr/u8-mbtouc-unsafe.c unistr/u8-mbtouc-unsafe-aux.c
+
+## end   gnulib module unistr/u8-mbtouc-unsafe
+
+## begin gnulib module unistr/u8-mbtoucr
+
+libgnu_la_SOURCES += unistr/u8-mbtoucr.c
+
+## end   gnulib module unistr/u8-mbtoucr
+
+## begin gnulib module unistr/u8-prev
+
+libgnu_la_SOURCES += unistr/u8-prev.c
+
+## end   gnulib module unistr/u8-prev
+
+## begin gnulib module unistr/u8-uctomb
+
+libgnu_la_SOURCES += unistr/u8-uctomb.c unistr/u8-uctomb-aux.c
+
+## end   gnulib module unistr/u8-uctomb
+
+## begin gnulib module unitypes
+
+
+EXTRA_DIST += unitypes.h
+
+## end   gnulib module unitypes
+
 ## begin gnulib module verify
 
 libgnu_la_SOURCES += verify.h
diff --git a/lib/alloca.h b/lib/alloca.h
new file mode 100644
index 0000000..d59852f
--- /dev/null
+++ b/lib/alloca.h
@@ -0,0 +1,57 @@
+/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
+/* Memory allocation on the stack.
+
+   Copyright (C) 1995, 1999, 2001-2004, 2006-2008 Free Software
+   Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+   USA.  */
+
+/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H
+   means there is a real alloca function.  */
+#ifndef _GL_ALLOCA_H
+#define _GL_ALLOCA_H
+
+/* alloca (N) returns a pointer to N bytes of memory
+   allocated on the stack, which will last until the function returns.
+   Use of alloca should be avoided:
+     - inside arguments of function calls - undefined behaviour,
+     - in inline functions - the allocation may actually last until the
+       calling function returns,
+     - for huge N (say, N >= 65536) - you never know how large (or small)
+       the stack is, and when the stack cannot fulfill the memory allocation
+       request, the program just crashes.
+ */
+
+#ifndef alloca
+# ifdef __GNUC__
+#  define alloca __builtin_alloca
+# elif defined _AIX
+#  define alloca __alloca
+# elif defined _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# elif defined __DECC && defined __VMS
+#  define alloca __ALLOCA
+# else
+#  include <stddef.h>
+#  ifdef  __cplusplus
+extern "C"
+#  endif
+void *alloca (size_t);
+# endif
+#endif
+
+#endif /* _GL_ALLOCA_H */
diff --git a/lib/c-ctype.c b/lib/c-ctype.c
new file mode 100644
index 0000000..e36a513
--- /dev/null
+++ b/lib/c-ctype.c
@@ -0,0 +1,396 @@
+/* Character handling in C locale.
+
+   Copyright 2000-2003, 2006 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#define NO_C_CTYPE_MACROS
+#include "c-ctype.h"
+
+/* The function isascii is not locale dependent. Its use in EBCDIC is
+   questionable. */
+bool
+c_isascii (int c)
+{
+  return (c >= 0x00 && c <= 0x7f);
+}
+
+bool
+c_isalnum (int c)
+{
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+  return ((c >= '0' && c <= '9')
+          || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z'));
+#else
+  return ((c >= '0' && c <= '9')
+          || (c >= 'A' && c <= 'Z')
+          || (c >= 'a' && c <= 'z'));
+#endif
+#else
+  switch (c)
+    {
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isalpha (int c)
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+  return ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z');
+#else
+  return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'));
+#endif
+#else
+  switch (c)
+    {
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isblank (int c)
+{
+  return (c == ' ' || c == '\t');
+}
+
+bool
+c_iscntrl (int c)
+{
+#if C_CTYPE_ASCII
+  return ((c & ~0x1f) == 0 || c == 0x7f);
+#else
+  switch (c)
+    {
+    case ' ': case '!': case '"': case '#': case '$': case '%':
+    case '&': case '\'': case '(': case ')': case '*': case '+':
+    case ',': case '-': case '.': case '/':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+    case '{': case '|': case '}': case '~':
+      return 0;
+    default:
+      return 1;
+    }
+#endif
+}
+
+bool
+c_isdigit (int c)
+{
+#if C_CTYPE_CONSECUTIVE_DIGITS
+  return (c >= '0' && c <= '9');
+#else
+  switch (c)
+    {
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_islower (int c)
+{
+#if C_CTYPE_CONSECUTIVE_LOWERCASE
+  return (c >= 'a' && c <= 'z');
+#else
+  switch (c)
+    {
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isgraph (int c)
+{
+#if C_CTYPE_ASCII
+  return (c >= '!' && c <= '~');
+#else
+  switch (c)
+    {
+    case '!': case '"': case '#': case '$': case '%': case '&':
+    case '\'': case '(': case ')': case '*': case '+': case ',':
+    case '-': case '.': case '/':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+    case '{': case '|': case '}': case '~':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isprint (int c)
+{
+#if C_CTYPE_ASCII
+  return (c >= ' ' && c <= '~');
+#else
+  switch (c)
+    {
+    case ' ': case '!': case '"': case '#': case '$': case '%':
+    case '&': case '\'': case '(': case ')': case '*': case '+':
+    case ',': case '-': case '.': case '/':
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+    case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+    case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+    case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+    case 'y': case 'z':
+    case '{': case '|': case '}': case '~':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_ispunct (int c)
+{
+#if C_CTYPE_ASCII
+  return ((c >= '!' && c <= '~')
+          && !((c >= '0' && c <= '9')
+               || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'Z')));
+#else
+  switch (c)
+    {
+    case '!': case '"': case '#': case '$': case '%': case '&':
+    case '\'': case '(': case ')': case '*': case '+': case ',':
+    case '-': case '.': case '/':
+    case ':': case ';': case '<': case '=': case '>': case '?':
+    case '@':
+    case '[': case '\\': case ']': case '^': case '_': case '`':
+    case '{': case '|': case '}': case '~':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isspace (int c)
+{
+  return (c == ' ' || c == '\t'
+          || c == '\n' || c == '\v' || c == '\f' || c == '\r');
+}
+
+bool
+c_isupper (int c)
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE
+  return (c >= 'A' && c <= 'Z');
+#else
+  switch (c)
+    {
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+    case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+    case 'Y': case 'Z':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+bool
+c_isxdigit (int c)
+{
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+  return ((c >= '0' && c <= '9')
+          || ((c & ~0x20) >= 'A' && (c & ~0x20) <= 'F'));
+#else
+  return ((c >= '0' && c <= '9')
+          || (c >= 'A' && c <= 'F')
+          || (c >= 'a' && c <= 'f'));
+#endif
+#else
+  switch (c)
+    {
+    case '0': case '1': case '2': case '3': case '4': case '5':
+    case '6': case '7': case '8': case '9':
+    case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+    case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+      return 1;
+    default:
+      return 0;
+    }
+#endif
+}
+
+int
+c_tolower (int c)
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+  return (c >= 'A' && c <= 'Z' ? c - 'A' + 'a' : c);
+#else
+  switch (c)
+    {
+    case 'A': return 'a';
+    case 'B': return 'b';
+    case 'C': return 'c';
+    case 'D': return 'd';
+    case 'E': return 'e';
+    case 'F': return 'f';
+    case 'G': return 'g';
+    case 'H': return 'h';
+    case 'I': return 'i';
+    case 'J': return 'j';
+    case 'K': return 'k';
+    case 'L': return 'l';
+    case 'M': return 'm';
+    case 'N': return 'n';
+    case 'O': return 'o';
+    case 'P': return 'p';
+    case 'Q': return 'q';
+    case 'R': return 'r';
+    case 'S': return 's';
+    case 'T': return 't';
+    case 'U': return 'u';
+    case 'V': return 'v';
+    case 'W': return 'w';
+    case 'X': return 'x';
+    case 'Y': return 'y';
+    case 'Z': return 'z';
+    default: return c;
+    }
+#endif
+}
+
+int
+c_toupper (int c)
+{
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+  return (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c);
+#else
+  switch (c)
+    {
+    case 'a': return 'A';
+    case 'b': return 'B';
+    case 'c': return 'C';
+    case 'd': return 'D';
+    case 'e': return 'E';
+    case 'f': return 'F';
+    case 'g': return 'G';
+    case 'h': return 'H';
+    case 'i': return 'I';
+    case 'j': return 'J';
+    case 'k': return 'K';
+    case 'l': return 'L';
+    case 'm': return 'M';
+    case 'n': return 'N';
+    case 'o': return 'O';
+    case 'p': return 'P';
+    case 'q': return 'Q';
+    case 'r': return 'R';
+    case 's': return 'S';
+    case 't': return 'T';
+    case 'u': return 'U';
+    case 'v': return 'V';
+    case 'w': return 'W';
+    case 'x': return 'X';
+    case 'y': return 'Y';
+    case 'z': return 'Z';
+    default: return c;
+    }
+#endif
+}
diff --git a/lib/c-ctype.h b/lib/c-ctype.h
new file mode 100644
index 0000000..d7b067e
--- /dev/null
+++ b/lib/c-ctype.h
@@ -0,0 +1,295 @@
+/* Character handling in C locale.
+
+   These functions work like the corresponding functions in <ctype.h>,
+   except that they have the C (POSIX) locale hardwired, whereas the
+   <ctype.h> functions' behaviour depends on the current locale set via
+   setlocale.
+
+   Copyright (C) 2000-2003, 2006, 2008 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef C_CTYPE_H
+#define C_CTYPE_H
+
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* The functions defined in this file assume the "C" locale and a character
+   set without diacritics (ASCII-US or EBCDIC-US or something like that).
+   Even if the "C" locale on a particular system is an extension of the ASCII
+   character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
+   is ISO-8859-1), the functions in this file recognize only the ASCII
+   characters.  */
+
+
+/* Check whether the ASCII optimizations apply. */
+
+/* ANSI C89 (and ISO C99 5.2.1.3 too) already guarantees that
+   '0', '1', ..., '9' have consecutive integer values.  */
+#define C_CTYPE_CONSECUTIVE_DIGITS 1
+
+#if ('A' <= 'Z') \
+    && ('A' + 1 == 'B') && ('B' + 1 == 'C') && ('C' + 1 == 'D') \
+    && ('D' + 1 == 'E') && ('E' + 1 == 'F') && ('F' + 1 == 'G') \
+    && ('G' + 1 == 'H') && ('H' + 1 == 'I') && ('I' + 1 == 'J') \
+    && ('J' + 1 == 'K') && ('K' + 1 == 'L') && ('L' + 1 == 'M') \
+    && ('M' + 1 == 'N') && ('N' + 1 == 'O') && ('O' + 1 == 'P') \
+    && ('P' + 1 == 'Q') && ('Q' + 1 == 'R') && ('R' + 1 == 'S') \
+    && ('S' + 1 == 'T') && ('T' + 1 == 'U') && ('U' + 1 == 'V') \
+    && ('V' + 1 == 'W') && ('W' + 1 == 'X') && ('X' + 1 == 'Y') \
+    && ('Y' + 1 == 'Z')
+#define C_CTYPE_CONSECUTIVE_UPPERCASE 1
+#endif
+
+#if ('a' <= 'z') \
+    && ('a' + 1 == 'b') && ('b' + 1 == 'c') && ('c' + 1 == 'd') \
+    && ('d' + 1 == 'e') && ('e' + 1 == 'f') && ('f' + 1 == 'g') \
+    && ('g' + 1 == 'h') && ('h' + 1 == 'i') && ('i' + 1 == 'j') \
+    && ('j' + 1 == 'k') && ('k' + 1 == 'l') && ('l' + 1 == 'm') \
+    && ('m' + 1 == 'n') && ('n' + 1 == 'o') && ('o' + 1 == 'p') \
+    && ('p' + 1 == 'q') && ('q' + 1 == 'r') && ('r' + 1 == 's') \
+    && ('s' + 1 == 't') && ('t' + 1 == 'u') && ('u' + 1 == 'v') \
+    && ('v' + 1 == 'w') && ('w' + 1 == 'x') && ('x' + 1 == 'y') \
+    && ('y' + 1 == 'z')
+#define C_CTYPE_CONSECUTIVE_LOWERCASE 1
+#endif
+
+#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+    && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+    && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+    && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+    && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+    && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+    && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+    && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+    && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+    && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+    && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+    && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+    && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+    && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+    && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+    && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+    && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+    && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+    && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+    && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+    && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+    && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+    && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
+/* The character set is ASCII or one of its variants or extensions, not EBCDIC.
+   Testing the value of '\n' and '\r' is not relevant.  */
+#define C_CTYPE_ASCII 1
+#endif
+
+
+/* Function declarations. */
+
+/* Unlike the functions in <ctype.h>, which require an argument in the range
+   of the 'unsigned char' type, the functions here operate on values that are
+   in the 'unsigned char' range or in the 'char' range.  In other words,
+   when you have a 'char' value, you need to cast it before using it as
+   argument to a <ctype.h> function:
+
+         const char *s = ...;
+         if (isalpha ((unsigned char) *s)) ...
+
+   but you don't need to cast it for the functions defined in this file:
+
+         const char *s = ...;
+         if (c_isalpha (*s)) ...
+ */
+
+extern bool c_isascii (int c); /* not locale dependent */
+
+extern bool c_isalnum (int c);
+extern bool c_isalpha (int c);
+extern bool c_isblank (int c);
+extern bool c_iscntrl (int c);
+extern bool c_isdigit (int c);
+extern bool c_islower (int c);
+extern bool c_isgraph (int c);
+extern bool c_isprint (int c);
+extern bool c_ispunct (int c);
+extern bool c_isspace (int c);
+extern bool c_isupper (int c);
+extern bool c_isxdigit (int c);
+
+extern int c_tolower (int c);
+extern int c_toupper (int c);
+
+
+#if defined __GNUC__ && defined __OPTIMIZE__ && !defined __OPTIMIZE_SIZE__ && 
!defined NO_C_CTYPE_MACROS
+
+/* ASCII optimizations. */
+
+#undef c_isascii
+#define c_isascii(c) \
+  ({ int __c = (c); \
+     (__c >= 0x00 && __c <= 0x7f); \
+   })
+
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+#undef c_isalnum
+#define c_isalnum(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z')); \
+   })
+#else
+#undef c_isalnum
+#define c_isalnum(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || (__c >= 'A' && __c <= 'Z') \
+      || (__c >= 'a' && __c <= 'z')); \
+   })
+#endif
+#endif
+
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+#undef c_isalpha
+#define c_isalpha(c) \
+  ({ int __c = (c); \
+     ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'Z'); \
+   })
+#else
+#undef c_isalpha
+#define c_isalpha(c) \
+  ({ int __c = (c); \
+     ((__c >= 'A' && __c <= 'Z') || (__c >= 'a' && __c <= 'z')); \
+   })
+#endif
+#endif
+
+#undef c_isblank
+#define c_isblank(c) \
+  ({ int __c = (c); \
+     (__c == ' ' || __c == '\t'); \
+   })
+
+#if C_CTYPE_ASCII
+#undef c_iscntrl
+#define c_iscntrl(c) \
+  ({ int __c = (c); \
+     ((__c & ~0x1f) == 0 || __c == 0x7f); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_DIGITS
+#undef c_isdigit
+#define c_isdigit(c) \
+  ({ int __c = (c); \
+     (__c >= '0' && __c <= '9'); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_LOWERCASE
+#undef c_islower
+#define c_islower(c) \
+  ({ int __c = (c); \
+     (__c >= 'a' && __c <= 'z'); \
+   })
+#endif
+
+#if C_CTYPE_ASCII
+#undef c_isgraph
+#define c_isgraph(c) \
+  ({ int __c = (c); \
+     (__c >= '!' && __c <= '~'); \
+   })
+#endif
+
+#if C_CTYPE_ASCII
+#undef c_isprint
+#define c_isprint(c) \
+  ({ int __c = (c); \
+     (__c >= ' ' && __c <= '~'); \
+   })
+#endif
+
+#if C_CTYPE_ASCII
+#undef c_ispunct
+#define c_ispunct(c) \
+  ({ int _c = (c); \
+     (c_isgraph (_c) && ! c_isalnum (_c)); \
+   })
+#endif
+
+#undef c_isspace
+#define c_isspace(c) \
+  ({ int __c = (c); \
+     (__c == ' ' || __c == '\t' \
+      || __c == '\n' || __c == '\v' || __c == '\f' || __c == '\r'); \
+   })
+
+#if C_CTYPE_CONSECUTIVE_UPPERCASE
+#undef c_isupper
+#define c_isupper(c) \
+  ({ int __c = (c); \
+     (__c >= 'A' && __c <= 'Z'); \
+   })
+#endif
+
+#if C_CTYPE_CONSECUTIVE_DIGITS \
+    && C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#if C_CTYPE_ASCII
+#undef c_isxdigit
+#define c_isxdigit(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || ((__c & ~0x20) >= 'A' && (__c & ~0x20) <= 'F')); \
+   })
+#else
+#undef c_isxdigit
+#define c_isxdigit(c) \
+  ({ int __c = (c); \
+     ((__c >= '0' && __c <= '9') \
+      || (__c >= 'A' && __c <= 'F') \
+      || (__c >= 'a' && __c <= 'f')); \
+   })
+#endif
+#endif
+
+#if C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#undef c_tolower
+#define c_tolower(c) \
+  ({ int __c = (c); \
+     (__c >= 'A' && __c <= 'Z' ? __c - 'A' + 'a' : __c); \
+   })
+#undef c_toupper
+#define c_toupper(c) \
+  ({ int __c = (c); \
+     (__c >= 'a' && __c <= 'z' ? __c - 'a' + 'A' : __c); \
+   })
+#endif
+
+#endif /* optimizing for speed */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* C_CTYPE_H */
diff --git a/lib/c-strcase.h b/lib/c-strcase.h
new file mode 100644
index 0000000..714a3c6
--- /dev/null
+++ b/lib/c-strcase.h
@@ -0,0 +1,55 @@
+/* Case-insensitive string comparison functions in C locale.
+   Copyright (C) 1995-1996, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef C_STRCASE_H
+#define C_STRCASE_H
+
+#include <stddef.h>
+
+
+/* The functions defined in this file assume the "C" locale and a character
+   set without diacritics (ASCII-US or EBCDIC-US or something like that).
+   Even if the "C" locale on a particular system is an extension of the ASCII
+   character set (like on BeOS, where it is UTF-8, or on AmigaOS, where it
+   is ISO-8859-1), the functions in this file recognize only the ASCII
+   characters.  More precisely, one of the string arguments must be an ASCII
+   string; the other one can also contain non-ASCII characters (but then
+   the comparison result will be nonzero).  */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
+   greater than zero if S1 is lexicographically less than, equal to or greater
+   than S2.  */
+extern int c_strcasecmp (const char *s1, const char *s2);
+
+/* Compare no more than N characters of strings S1 and S2, ignoring case,
+   returning less than, equal to or greater than zero if S1 is
+   lexicographically less than, equal to or greater than S2.  */
+extern int c_strncasecmp (const char *s1, const char *s2, size_t n);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* C_STRCASE_H */
diff --git a/lib/c-strcasecmp.c b/lib/c-strcasecmp.c
new file mode 100644
index 0000000..a523898
--- /dev/null
+++ b/lib/c-strcasecmp.c
@@ -0,0 +1,57 @@
+/* c-strcasecmp.c -- case insensitive string comparator in C locale
+   Copyright (C) 1998-1999, 2005-2006 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "c-strcase.h"
+
+#include <limits.h>
+
+#include "c-ctype.h"
+
+int
+c_strcasecmp (const char *s1, const char *s2)
+{
+  register const unsigned char *p1 = (const unsigned char *) s1;
+  register const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+
+  if (p1 == p2)
+    return 0;
+
+  do
+    {
+      c1 = c_tolower (*p1);
+      c2 = c_tolower (*p2);
+
+      if (c1 == '\0')
+       break;
+
+      ++p1;
+      ++p2;
+    }
+  while (c1 == c2);
+
+  if (UCHAR_MAX <= INT_MAX)
+    return c1 - c2;
+  else
+    /* On machines where 'char' and 'int' are types of the same size, the
+       difference of two 'unsigned char' values - including the sign bit -
+       doesn't fit in an 'int'.  */
+    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+}
diff --git a/lib/c-strcaseeq.h b/lib/c-strcaseeq.h
new file mode 100644
index 0000000..cd29b66
--- /dev/null
+++ b/lib/c-strcaseeq.h
@@ -0,0 +1,184 @@
+/* Optimized case-insensitive string comparison in C locale.
+   Copyright (C) 2001-2002, 2007 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <address@hidden>.  */
+
+#include "c-strcase.h"
+#include "c-ctype.h"
+
+/* STRCASEEQ allows to optimize string comparison with a small literal string.
+     STRCASEEQ (s, "UTF-8", 'U','T','F','-','8',0,0,0,0)
+   is semantically equivalent to
+     c_strcasecmp (s, "UTF-8") == 0
+   just faster.  */
+
+/* Help GCC to generate good code for string comparisons with
+   immediate strings. */
+#if defined (__GNUC__) && defined (__OPTIMIZE__)
+
+/* Case insensitive comparison of ASCII characters.  */
+# if C_CTYPE_ASCII
+#  define CASEEQ(other,upper) \
+     (c_isupper (upper) ? ((other) & ~0x20) == (upper) : (other) == (upper))
+# elif C_CTYPE_CONSECUTIVE_UPPERCASE && C_CTYPE_CONSECUTIVE_LOWERCASE
+#  define CASEEQ(other,upper) \
+     (c_isupper (upper) ? (other) == (upper) || (other) == (upper) - 'A' + 'a' 
: (other) == (upper))
+# else
+#  define CASEEQ(other,upper) \
+     (c_toupper (other) == (upper))
+# endif
+
+static inline int
+strcaseeq9 (const char *s1, const char *s2)
+{
+  return c_strcasecmp (s1 + 9, s2 + 9) == 0;
+}
+
+static inline int
+strcaseeq8 (const char *s1, const char *s2, char s28)
+{
+  if (CASEEQ (s1[8], s28))
+    {
+      if (s28 == 0)
+        return 1;
+      else
+        return strcaseeq9 (s1, s2);
+    }
+  else
+    return 0;
+}
+
+static inline int
+strcaseeq7 (const char *s1, const char *s2, char s27, char s28)
+{
+  if (CASEEQ (s1[7], s27))
+    {
+      if (s27 == 0)
+        return 1;
+      else
+        return strcaseeq8 (s1, s2, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+strcaseeq6 (const char *s1, const char *s2, char s26, char s27, char s28)
+{
+  if (CASEEQ (s1[6], s26))
+    {
+      if (s26 == 0)
+        return 1;
+      else
+        return strcaseeq7 (s1, s2, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+strcaseeq5 (const char *s1, const char *s2, char s25, char s26, char s27, char 
s28)
+{
+  if (CASEEQ (s1[5], s25))
+    {
+      if (s25 == 0)
+        return 1;
+      else
+        return strcaseeq6 (s1, s2, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+strcaseeq4 (const char *s1, const char *s2, char s24, char s25, char s26, char 
s27, char s28)
+{
+  if (CASEEQ (s1[4], s24))
+    {
+      if (s24 == 0)
+        return 1;
+      else
+        return strcaseeq5 (s1, s2, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+strcaseeq3 (const char *s1, const char *s2, char s23, char s24, char s25, char 
s26, char s27, char s28)
+{
+  if (CASEEQ (s1[3], s23))
+    {
+      if (s23 == 0)
+        return 1;
+      else
+        return strcaseeq4 (s1, s2, s24, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+strcaseeq2 (const char *s1, const char *s2, char s22, char s23, char s24, char 
s25, char s26, char s27, char s28)
+{
+  if (CASEEQ (s1[2], s22))
+    {
+      if (s22 == 0)
+        return 1;
+      else
+        return strcaseeq3 (s1, s2, s23, s24, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+strcaseeq1 (const char *s1, const char *s2, char s21, char s22, char s23, char 
s24, char s25, char s26, char s27, char s28)
+{
+  if (CASEEQ (s1[1], s21))
+    {
+      if (s21 == 0)
+        return 1;
+      else
+        return strcaseeq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+static inline int
+strcaseeq0 (const char *s1, const char *s2, char s20, char s21, char s22, char 
s23, char s24, char s25, char s26, char s27, char s28)
+{
+  if (CASEEQ (s1[0], s20))
+    {
+      if (s20 == 0)
+        return 1;
+      else
+        return strcaseeq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28);
+    }
+  else
+    return 0;
+}
+
+#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
+  strcaseeq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28)
+
+#else
+
+#define STRCASEEQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \
+  (c_strcasecmp (s1, s2) == 0)
+
+#endif
diff --git a/lib/c-strncasecmp.c b/lib/c-strncasecmp.c
new file mode 100644
index 0000000..c1496ca
--- /dev/null
+++ b/lib/c-strncasecmp.c
@@ -0,0 +1,57 @@
+/* c-strncasecmp.c -- case insensitive string comparator in C locale
+   Copyright (C) 1998-1999, 2005-2006 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "c-strcase.h"
+
+#include <limits.h>
+
+#include "c-ctype.h"
+
+int
+c_strncasecmp (const char *s1, const char *s2, size_t n)
+{
+  register const unsigned char *p1 = (const unsigned char *) s1;
+  register const unsigned char *p2 = (const unsigned char *) s2;
+  unsigned char c1, c2;
+
+  if (p1 == p2 || n == 0)
+    return 0;
+
+  do
+    {
+      c1 = c_tolower (*p1);
+      c2 = c_tolower (*p2);
+
+      if (--n == 0 || c1 == '\0')
+       break;
+
+      ++p1;
+      ++p2;
+    }
+  while (c1 == c2);
+
+  if (UCHAR_MAX <= INT_MAX)
+    return c1 - c2;
+  else
+    /* On machines where 'char' and 'int' are types of the same size, the
+       difference of two 'unsigned char' values - including the sign bit -
+       doesn't fit in an 'int'.  */
+    return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
+}
diff --git a/lib/charset.alias b/lib/charset.alias
new file mode 100644
index 0000000..d9501e2
--- /dev/null
+++ b/lib/charset.alias
@@ -0,0 +1,5 @@
+# This file contains a table of character encoding aliases,
+# suitable for operating system 'linux-gnu'.
+# It was automatically generated from config.charset.
+# Packages using this file: 
+ISO_646.IRV:1983 ASCII
diff --git a/lib/configmake.h b/lib/configmake.h
new file mode 100644
index 0000000..e0f7a52
--- /dev/null
+++ b/lib/configmake.h
@@ -0,0 +1,26 @@
+/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
+#define PREFIX "/usr/local"
+#define EXEC_PREFIX "/usr/local"
+#define BINDIR "/usr/local/bin"
+#define SBINDIR "/usr/local/sbin"
+#define LIBEXECDIR "/usr/local/libexec"
+#define DATAROOTDIR "/usr/local/share"
+#define DATADIR "/usr/local/share"
+#define SYSCONFDIR "/usr/local/etc"
+#define SHAREDSTATEDIR "/usr/local/com"
+#define LOCALSTATEDIR "/usr/local/var"
+#define INCLUDEDIR "/usr/local/include"
+#define OLDINCLUDEDIR "/usr/include"
+#define DOCDIR "/usr/local/share/doc/guile"
+#define INFODIR "/usr/local/share/info"
+#define HTMLDIR "/usr/local/share/doc/guile"
+#define DVIDIR "/usr/local/share/doc/guile"
+#define PDFDIR "/usr/local/share/doc/guile"
+#define PSDIR "/usr/local/share/doc/guile"
+#define LIBDIR "/usr/local/lib"
+#define LISPDIR "/usr/local/share/emacs/site-lisp"
+#define LOCALEDIR "/usr/local/share/locale"
+#define MANDIR "/usr/local/share/man"
+#define PKGDATADIR "/usr/local/share/guile"
+#define PKGINCLUDEDIR "/usr/local/include/guile"
+#define PKGLIBDIR "/usr/local/lib/guile"
diff --git a/lib/iconv.in.h b/lib/iconv.in.h
new file mode 100644
index 0000000..915dce2
--- /dev/null
+++ b/lib/iconv.in.h
@@ -0,0 +1,71 @@
+/* A GNU-like <iconv.h>.
+
+   Copyright (C) 2007-2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GL_ICONV_H
+
+#if __GNUC__ >= 3
address@hidden@
+#endif
+
+/* The include_next requires a split double-inclusion guard.  */
address@hidden@ @NEXT_ICONV_H@
+
+#ifndef _GL_ICONV_H
+#define _GL_ICONV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if @REPLACE_ICONV_OPEN@
+/* An iconv_open wrapper that supports the IANA standardized encoding names
+   ("ISO-8859-1" etc.) as far as possible.  */
+# define iconv_open rpl_iconv_open
+extern iconv_t iconv_open (const char *tocode, const char *fromcode);
+#endif
+
+#if @REPLACE_ICONV_UTF@
+/* Special constants for supporting UTF-{16,32}{BE,LE} encodings.
+   Not public.  */
+# define _ICONV_UTF8_UTF16BE (iconv_t)(-161)
+# define _ICONV_UTF8_UTF16LE (iconv_t)(-162)
+# define _ICONV_UTF8_UTF32BE (iconv_t)(-163)
+# define _ICONV_UTF8_UTF32LE (iconv_t)(-164)
+# define _ICONV_UTF16BE_UTF8 (iconv_t)(-165)
+# define _ICONV_UTF16LE_UTF8 (iconv_t)(-166)
+# define _ICONV_UTF32BE_UTF8 (iconv_t)(-167)
+# define _ICONV_UTF32LE_UTF8 (iconv_t)(-168)
+#endif
+
+#if @REPLACE_ICONV@
+# define iconv rpl_iconv
+extern size_t iconv (iconv_t cd,
+                    @ICONV_CONST@ char **inbuf, size_t *inbytesleft,
+                    char **outbuf, size_t *outbytesleft);
+# define iconv_close rpl_iconv_close
+extern int iconv_close (iconv_t cd);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_ICONV_H */
+#endif /* _GL_ICONV_H */
diff --git a/lib/iconv_open-aix.gperf b/lib/iconv_open-aix.gperf
new file mode 100644
index 0000000..6782b99
--- /dev/null
+++ b/lib/iconv_open-aix.gperf
@@ -0,0 +1,44 @@
+struct mapping { int standard_name; const char vendor_name[10 + 1]; };
+%struct-type
+%language=ANSI-C
+%define slot-name standard_name
+%define hash-function-name mapping_hash
+%define lookup-function-name mapping_lookup
+%readonly-tables
+%global-table
+%define word-array-name mappings
+%pic
+%%
+# On AIX 5.1, look in /usr/lib/nls/loc/uconvTable.
+ISO-8859-1, "ISO8859-1"
+ISO-8859-2, "ISO8859-2"
+ISO-8859-3, "ISO8859-3"
+ISO-8859-4, "ISO8859-4"
+ISO-8859-5, "ISO8859-5"
+ISO-8859-6, "ISO8859-6"
+ISO-8859-7, "ISO8859-7"
+ISO-8859-8, "ISO8859-8"
+ISO-8859-9, "ISO8859-9"
+ISO-8859-15, "ISO8859-15"
+CP437, "IBM-437"
+CP850, "IBM-850"
+CP852, "IBM-852"
+CP856, "IBM-856"
+CP857, "IBM-857"
+CP861, "IBM-861"
+CP865, "IBM-865"
+CP869, "IBM-869"
+ISO-8859-13, "IBM-921"
+CP922, "IBM-922"
+CP932, "IBM-932"
+CP943, "IBM-943"
+CP1046, "IBM-1046"
+CP1124, "IBM-1124"
+CP1125, "IBM-1125"
+CP1129, "IBM-1129"
+CP1252, "IBM-1252"
+GB2312, "IBM-eucCN"
+EUC-JP, "IBM-eucJP"
+EUC-KR, "IBM-eucKR"
+EUC-TW, "IBM-eucTW"
+BIG5, "big5"
diff --git a/lib/iconv_open-aix.h b/lib/iconv_open-aix.h
new file mode 100644
index 0000000..0ffc3fe
--- /dev/null
+++ b/lib/iconv_open-aix.h
@@ -0,0 +1,256 @@
+/* ANSI-C code produced by gperf version 3.0.3 */
+/* Command-line: gperf -m 10 ./iconv_open-aix.gperf  */
+/* Computed positions: -k'4,$' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. 
Please report a bug to <address@hidden>."
+#endif
+
+#line 1 "./iconv_open-aix.gperf"
+struct mapping { int standard_name; const char vendor_name[10 + 1]; };
+
+#define TOTAL_KEYWORDS 32
+#define MIN_WORD_LENGTH 4
+#define MAX_WORD_LENGTH 11
+#define MIN_HASH_VALUE 6
+#define MAX_HASH_VALUE 44
+/* maximum key range = 39, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+mapping_hash (register const char *str, register unsigned int len)
+{
+  static const unsigned char asso_values[] =
+    {
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45,  0,  4, 25,
+       0, 11, 24,  9, 17,  3, 14, 21, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+       3, 45,  1, 45, 45, 45, 45,  0, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+      45, 45, 45, 45, 45, 45, 45, 45
+    };
+  return len + asso_values[(unsigned char)str[3]+2] + asso_values[(unsigned 
char)str[len - 1]];
+}
+
+struct stringpool_t
+  {
+    char stringpool_str6[sizeof("EUC-TW")];
+    char stringpool_str7[sizeof("EUC-KR")];
+    char stringpool_str8[sizeof("CP852")];
+    char stringpool_str9[sizeof("EUC-JP")];
+    char stringpool_str10[sizeof("ISO-8859-2")];
+    char stringpool_str11[sizeof("CP857")];
+    char stringpool_str12[sizeof("CP850")];
+    char stringpool_str13[sizeof("ISO-8859-7")];
+    char stringpool_str14[sizeof("CP932")];
+    char stringpool_str15[sizeof("GB2312")];
+    char stringpool_str16[sizeof("BIG5")];
+    char stringpool_str17[sizeof("CP437")];
+    char stringpool_str19[sizeof("ISO-8859-5")];
+    char stringpool_str20[sizeof("ISO-8859-15")];
+    char stringpool_str21[sizeof("ISO-8859-3")];
+    char stringpool_str22[sizeof("ISO-8859-13")];
+    char stringpool_str23[sizeof("CP1046")];
+    char stringpool_str24[sizeof("ISO-8859-8")];
+    char stringpool_str25[sizeof("CP856")];
+    char stringpool_str26[sizeof("CP1125")];
+    char stringpool_str27[sizeof("ISO-8859-6")];
+    char stringpool_str28[sizeof("CP865")];
+    char stringpool_str29[sizeof("CP922")];
+    char stringpool_str30[sizeof("CP1252")];
+    char stringpool_str31[sizeof("ISO-8859-9")];
+    char stringpool_str33[sizeof("CP943")];
+    char stringpool_str34[sizeof("ISO-8859-4")];
+    char stringpool_str35[sizeof("ISO-8859-1")];
+    char stringpool_str38[sizeof("CP1129")];
+    char stringpool_str40[sizeof("CP869")];
+    char stringpool_str41[sizeof("CP1124")];
+    char stringpool_str44[sizeof("CP861")];
+  };
+static const struct stringpool_t stringpool_contents =
+  {
+    "EUC-TW",
+    "EUC-KR",
+    "CP852",
+    "EUC-JP",
+    "ISO-8859-2",
+    "CP857",
+    "CP850",
+    "ISO-8859-7",
+    "CP932",
+    "GB2312",
+    "BIG5",
+    "CP437",
+    "ISO-8859-5",
+    "ISO-8859-15",
+    "ISO-8859-3",
+    "ISO-8859-13",
+    "CP1046",
+    "ISO-8859-8",
+    "CP856",
+    "CP1125",
+    "ISO-8859-6",
+    "CP865",
+    "CP922",
+    "CP1252",
+    "ISO-8859-9",
+    "CP943",
+    "ISO-8859-4",
+    "ISO-8859-1",
+    "CP1129",
+    "CP869",
+    "CP1124",
+    "CP861"
+  };
+#define stringpool ((const char *) &stringpool_contents)
+
+static const struct mapping mappings[] =
+  {
+    {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 43 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str6, "IBM-eucTW"},
+#line 42 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, "IBM-eucKR"},
+#line 25 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str8, "IBM-852"},
+#line 41 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, "IBM-eucJP"},
+#line 14 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, "ISO8859-2"},
+#line 27 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, "IBM-857"},
+#line 24 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, "IBM-850"},
+#line 19 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, "ISO8859-7"},
+#line 33 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, "IBM-932"},
+#line 40 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, "IBM-eucCN"},
+#line 44 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str16, "big5"},
+#line 23 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, "IBM-437"},
+    {-1},
+#line 17 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, "ISO8859-5"},
+#line 22 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, "ISO8859-15"},
+#line 15 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, "ISO8859-3"},
+#line 31 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, "IBM-921"},
+#line 35 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, "IBM-1046"},
+#line 20 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str24, "ISO8859-8"},
+#line 26 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str25, "IBM-856"},
+#line 37 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str26, "IBM-1125"},
+#line 18 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str27, "ISO8859-6"},
+#line 29 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str28, "IBM-865"},
+#line 32 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str29, "IBM-922"},
+#line 39 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str30, "IBM-1252"},
+#line 21 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str31, "ISO8859-9"},
+    {-1},
+#line 34 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str33, "IBM-943"},
+#line 16 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str34, "ISO8859-4"},
+#line 13 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, "ISO8859-1"},
+    {-1}, {-1},
+#line 38 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str38, "IBM-1129"},
+    {-1},
+#line 30 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str40, "IBM-869"},
+#line 36 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str41, "IBM-1124"},
+    {-1}, {-1},
+#line 28 "./iconv_open-aix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str44, "IBM-861"}
+  };
+
+#ifdef __GNUC__
+__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct mapping *
+mapping_lookup (register const char *str, register unsigned int len)
+{
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = mapping_hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= 0)
+        {
+          register int o = mappings[key].standard_name;
+          if (o >= 0)
+            {
+              register const char *s = o + stringpool;
+
+              if (*str == *s && !strcmp (str + 1, s + 1))
+                return &mappings[key];
+            }
+        }
+    }
+  return 0;
+}
diff --git a/lib/iconv_open-hpux.gperf b/lib/iconv_open-hpux.gperf
new file mode 100644
index 0000000..5a35c83
--- /dev/null
+++ b/lib/iconv_open-hpux.gperf
@@ -0,0 +1,56 @@
+struct mapping { int standard_name; const char vendor_name[9 + 1]; };
+%struct-type
+%language=ANSI-C
+%define slot-name standard_name
+%define hash-function-name mapping_hash
+%define lookup-function-name mapping_lookup
+%readonly-tables
+%global-table
+%define word-array-name mappings
+%pic
+%%
+# On HP-UX 11.11, look in /usr/lib/nls/iconv.
+ISO-8859-1, "iso88591"
+ISO-8859-2, "iso88592"
+ISO-8859-5, "iso88595"
+ISO-8859-6, "iso88596"
+ISO-8859-7, "iso88597"
+ISO-8859-8, "iso88598"
+ISO-8859-9, "iso88599"
+ISO-8859-15, "iso885915"
+CP437, "cp437"
+CP775, "cp775"
+CP850, "cp850"
+CP852, "cp852"
+CP855, "cp855"
+CP857, "cp857"
+CP861, "cp861"
+CP862, "cp862"
+CP864, "cp864"
+CP865, "cp865"
+CP866, "cp866"
+CP869, "cp869"
+CP874, "cp874"
+CP1250, "cp1250"
+CP1251, "cp1251"
+CP1252, "cp1252"
+CP1253, "cp1253"
+CP1254, "cp1254"
+CP1255, "cp1255"
+CP1256, "cp1256"
+CP1257, "cp1257"
+CP1258, "cp1258"
+HP-ROMAN8, "roman8"
+HP-ARABIC8, "arabic8"
+HP-GREEK8, "greek8"
+HP-HEBREW8, "hebrew8"
+HP-TURKISH8, "turkish8"
+HP-KANA8, "kana8"
+TIS-620, "tis620"
+GB2312, "hp15CN"
+EUC-JP, "eucJP"
+EUC-KR, "eucKR"
+EUC-TW, "eucTW"
+BIG5, "big5"
+SHIFT_JIS, "sjis"
+UTF-8, "utf8"
diff --git a/lib/iconv_open-hpux.h b/lib/iconv_open-hpux.h
new file mode 100644
index 0000000..8f9f0a9
--- /dev/null
+++ b/lib/iconv_open-hpux.h
@@ -0,0 +1,299 @@
+/* ANSI-C code produced by gperf version 3.0.3 */
+/* Command-line: gperf -m 10 ./iconv_open-hpux.gperf  */
+/* Computed positions: -k'4,$' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. 
Please report a bug to <address@hidden>."
+#endif
+
+#line 1 "./iconv_open-hpux.gperf"
+struct mapping { int standard_name; const char vendor_name[9 + 1]; };
+
+#define TOTAL_KEYWORDS 44
+#define MIN_WORD_LENGTH 4
+#define MAX_WORD_LENGTH 11
+#define MIN_HASH_VALUE 6
+#define MAX_HASH_VALUE 49
+/* maximum key range = 44, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+mapping_hash (register const char *str, register unsigned int len)
+{
+  static const unsigned char asso_values[] =
+    {
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50,  1,  2,
+      24, 43,  5, 10,  0, 13, 32,  3, 19, 18,
+      50, 50, 50, 50, 50, 50, 50, 50, 50,  5,
+      50, 50, 50, 50, 14,  5,  0, 50, 50,  0,
+      27, 50, 12, 14, 50, 50,  0,  5,  2, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+      50, 50, 50, 50, 50, 50, 50, 50, 50, 50
+    };
+  return len + asso_values[(unsigned char)str[3]+4] + asso_values[(unsigned 
char)str[len - 1]];
+}
+
+struct stringpool_t
+  {
+    char stringpool_str6[sizeof("CP1256")];
+    char stringpool_str7[sizeof("CP1250")];
+    char stringpool_str8[sizeof("CP1251")];
+    char stringpool_str9[sizeof("CP850")];
+    char stringpool_str10[sizeof("TIS-620")];
+    char stringpool_str11[sizeof("CP1254")];
+    char stringpool_str12[sizeof("ISO-8859-6")];
+    char stringpool_str13[sizeof("EUC-TW")];
+    char stringpool_str14[sizeof("ISO-8859-1")];
+    char stringpool_str15[sizeof("ISO-8859-9")];
+    char stringpool_str16[sizeof("CP1255")];
+    char stringpool_str17[sizeof("BIG5")];
+    char stringpool_str18[sizeof("CP855")];
+    char stringpool_str19[sizeof("CP1257")];
+    char stringpool_str20[sizeof("EUC-KR")];
+    char stringpool_str21[sizeof("CP857")];
+    char stringpool_str22[sizeof("ISO-8859-5")];
+    char stringpool_str23[sizeof("ISO-8859-15")];
+    char stringpool_str24[sizeof("CP866")];
+    char stringpool_str25[sizeof("ISO-8859-7")];
+    char stringpool_str26[sizeof("CP861")];
+    char stringpool_str27[sizeof("CP869")];
+    char stringpool_str28[sizeof("CP874")];
+    char stringpool_str29[sizeof("CP864")];
+    char stringpool_str30[sizeof("CP1252")];
+    char stringpool_str31[sizeof("CP437")];
+    char stringpool_str32[sizeof("CP852")];
+    char stringpool_str33[sizeof("CP775")];
+    char stringpool_str34[sizeof("CP865")];
+    char stringpool_str35[sizeof("EUC-JP")];
+    char stringpool_str36[sizeof("ISO-8859-2")];
+    char stringpool_str37[sizeof("SHIFT_JIS")];
+    char stringpool_str38[sizeof("CP1258")];
+    char stringpool_str39[sizeof("UTF-8")];
+    char stringpool_str40[sizeof("HP-KANA8")];
+    char stringpool_str41[sizeof("HP-ROMAN8")];
+    char stringpool_str42[sizeof("HP-HEBREW8")];
+    char stringpool_str43[sizeof("GB2312")];
+    char stringpool_str44[sizeof("ISO-8859-8")];
+    char stringpool_str45[sizeof("HP-TURKISH8")];
+    char stringpool_str46[sizeof("HP-GREEK8")];
+    char stringpool_str47[sizeof("HP-ARABIC8")];
+    char stringpool_str48[sizeof("CP862")];
+    char stringpool_str49[sizeof("CP1253")];
+  };
+static const struct stringpool_t stringpool_contents =
+  {
+    "CP1256",
+    "CP1250",
+    "CP1251",
+    "CP850",
+    "TIS-620",
+    "CP1254",
+    "ISO-8859-6",
+    "EUC-TW",
+    "ISO-8859-1",
+    "ISO-8859-9",
+    "CP1255",
+    "BIG5",
+    "CP855",
+    "CP1257",
+    "EUC-KR",
+    "CP857",
+    "ISO-8859-5",
+    "ISO-8859-15",
+    "CP866",
+    "ISO-8859-7",
+    "CP861",
+    "CP869",
+    "CP874",
+    "CP864",
+    "CP1252",
+    "CP437",
+    "CP852",
+    "CP775",
+    "CP865",
+    "EUC-JP",
+    "ISO-8859-2",
+    "SHIFT_JIS",
+    "CP1258",
+    "UTF-8",
+    "HP-KANA8",
+    "HP-ROMAN8",
+    "HP-HEBREW8",
+    "GB2312",
+    "ISO-8859-8",
+    "HP-TURKISH8",
+    "HP-GREEK8",
+    "HP-ARABIC8",
+    "CP862",
+    "CP1253"
+  };
+#define stringpool ((const char *) &stringpool_contents)
+
+static const struct mapping mappings[] =
+  {
+    {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 40 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str6, "cp1256"},
+#line 34 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, "cp1250"},
+#line 35 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str8, "cp1251"},
+#line 23 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, "cp850"},
+#line 49 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, "tis620"},
+#line 38 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, "cp1254"},
+#line 16 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, "iso88596"},
+#line 53 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, "eucTW"},
+#line 13 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, "iso88591"},
+#line 19 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, "iso88599"},
+#line 39 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str16, "cp1255"},
+#line 54 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, "big5"},
+#line 25 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str18, "cp855"},
+#line 41 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, "cp1257"},
+#line 52 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, "eucKR"},
+#line 26 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, "cp857"},
+#line 15 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, "iso88595"},
+#line 20 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, "iso885915"},
+#line 31 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str24, "cp866"},
+#line 17 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str25, "iso88597"},
+#line 27 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str26, "cp861"},
+#line 32 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str27, "cp869"},
+#line 33 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str28, "cp874"},
+#line 29 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str29, "cp864"},
+#line 36 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str30, "cp1252"},
+#line 21 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str31, "cp437"},
+#line 24 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str32, "cp852"},
+#line 22 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str33, "cp775"},
+#line 30 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str34, "cp865"},
+#line 51 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, "eucJP"},
+#line 14 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str36, "iso88592"},
+#line 55 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str37, "sjis"},
+#line 42 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str38, "cp1258"},
+#line 56 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str39, "utf8"},
+#line 48 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str40, "kana8"},
+#line 43 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str41, "roman8"},
+#line 46 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str42, "hebrew8"},
+#line 50 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str43, "hp15CN"},
+#line 18 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str44, "iso88598"},
+#line 47 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str45, "turkish8"},
+#line 45 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str46, "greek8"},
+#line 44 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str47, "arabic8"},
+#line 28 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str48, "cp862"},
+#line 37 "./iconv_open-hpux.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str49, "cp1253"}
+  };
+
+#ifdef __GNUC__
+__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct mapping *
+mapping_lookup (register const char *str, register unsigned int len)
+{
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = mapping_hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= 0)
+        {
+          register int o = mappings[key].standard_name;
+          if (o >= 0)
+            {
+              register const char *s = o + stringpool;
+
+              if (*str == *s && !strcmp (str + 1, s + 1))
+                return &mappings[key];
+            }
+        }
+    }
+  return 0;
+}
diff --git a/lib/iconv_open-irix.gperf b/lib/iconv_open-irix.gperf
new file mode 100644
index 0000000..3672a80
--- /dev/null
+++ b/lib/iconv_open-irix.gperf
@@ -0,0 +1,31 @@
+struct mapping { int standard_name; const char vendor_name[10 + 1]; };
+%struct-type
+%language=ANSI-C
+%define slot-name standard_name
+%define hash-function-name mapping_hash
+%define lookup-function-name mapping_lookup
+%readonly-tables
+%global-table
+%define word-array-name mappings
+%pic
+%%
+# On IRIX 6.5, look in /usr/lib/iconv and /usr/lib/international/encodings.
+ISO-8859-1, "ISO8859-1"
+ISO-8859-2, "ISO8859-2"
+ISO-8859-3, "ISO8859-3"
+ISO-8859-4, "ISO8859-4"
+ISO-8859-5, "ISO8859-5"
+ISO-8859-6, "ISO8859-6"
+ISO-8859-7, "ISO8859-7"
+ISO-8859-8, "ISO8859-8"
+ISO-8859-9, "ISO8859-9"
+ISO-8859-15, "ISO8859-15"
+KOI8-R, "KOI8"
+CP855, "DOS855"
+CP1251, "WIN1251"
+GB2312, "eucCN"
+EUC-JP, "eucJP"
+EUC-KR, "eucKR"
+EUC-TW, "eucTW"
+SHIFT_JIS, "sjis"
+TIS-620, "TIS620"
diff --git a/lib/iconv_open-irix.h b/lib/iconv_open-irix.h
new file mode 100644
index 0000000..520582e
--- /dev/null
+++ b/lib/iconv_open-irix.h
@@ -0,0 +1,199 @@
+/* ANSI-C code produced by gperf version 3.0.3 */
+/* Command-line: gperf -m 10 ./iconv_open-irix.gperf  */
+/* Computed positions: -k'1,$' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. 
Please report a bug to <address@hidden>."
+#endif
+
+#line 1 "./iconv_open-irix.gperf"
+struct mapping { int standard_name; const char vendor_name[10 + 1]; };
+
+#define TOTAL_KEYWORDS 19
+#define MIN_WORD_LENGTH 5
+#define MAX_WORD_LENGTH 11
+#define MIN_HASH_VALUE 5
+#define MAX_HASH_VALUE 23
+/* maximum key range = 19, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+mapping_hash (register const char *str, register unsigned int len)
+{
+  static const unsigned char asso_values[] =
+    {
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24,  8,  2,
+       5, 12, 11,  0, 10,  9,  8,  7, 24, 24,
+      24, 24, 24, 24, 24, 24, 24,  0, 24,  0,
+      24,  5, 24,  0, 24,  7, 24, 24, 24, 24,
+       7, 24,  1,  0,  8, 24, 24,  0, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+      24, 24, 24, 24, 24, 24
+    };
+  return len + asso_values[(unsigned char)str[len - 1]] + 
asso_values[(unsigned char)str[0]];
+}
+
+struct stringpool_t
+  {
+    char stringpool_str5[sizeof("CP855")];
+    char stringpool_str6[sizeof("EUC-TW")];
+    char stringpool_str7[sizeof("EUC-KR")];
+    char stringpool_str8[sizeof("CP1251")];
+    char stringpool_str9[sizeof("SHIFT_JIS")];
+    char stringpool_str10[sizeof("ISO-8859-5")];
+    char stringpool_str11[sizeof("ISO-8859-15")];
+    char stringpool_str12[sizeof("ISO-8859-1")];
+    char stringpool_str13[sizeof("EUC-JP")];
+    char stringpool_str14[sizeof("KOI8-R")];
+    char stringpool_str15[sizeof("ISO-8859-2")];
+    char stringpool_str16[sizeof("GB2312")];
+    char stringpool_str17[sizeof("ISO-8859-9")];
+    char stringpool_str18[sizeof("ISO-8859-8")];
+    char stringpool_str19[sizeof("ISO-8859-7")];
+    char stringpool_str20[sizeof("ISO-8859-6")];
+    char stringpool_str21[sizeof("ISO-8859-4")];
+    char stringpool_str22[sizeof("ISO-8859-3")];
+    char stringpool_str23[sizeof("TIS-620")];
+  };
+static const struct stringpool_t stringpool_contents =
+  {
+    "CP855",
+    "EUC-TW",
+    "EUC-KR",
+    "CP1251",
+    "SHIFT_JIS",
+    "ISO-8859-5",
+    "ISO-8859-15",
+    "ISO-8859-1",
+    "EUC-JP",
+    "KOI8-R",
+    "ISO-8859-2",
+    "GB2312",
+    "ISO-8859-9",
+    "ISO-8859-8",
+    "ISO-8859-7",
+    "ISO-8859-6",
+    "ISO-8859-4",
+    "ISO-8859-3",
+    "TIS-620"
+  };
+#define stringpool ((const char *) &stringpool_contents)
+
+static const struct mapping mappings[] =
+  {
+    {-1}, {-1}, {-1}, {-1}, {-1},
+#line 24 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str5, "DOS855"},
+#line 29 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str6, "eucTW"},
+#line 28 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, "eucKR"},
+#line 25 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str8, "WIN1251"},
+#line 30 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, "sjis"},
+#line 17 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, "ISO8859-5"},
+#line 22 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, "ISO8859-15"},
+#line 13 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, "ISO8859-1"},
+#line 27 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, "eucJP"},
+#line 23 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, "KOI8"},
+#line 14 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, "ISO8859-2"},
+#line 26 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str16, "eucCN"},
+#line 21 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, "ISO8859-9"},
+#line 20 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str18, "ISO8859-8"},
+#line 19 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, "ISO8859-7"},
+#line 18 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, "ISO8859-6"},
+#line 16 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, "ISO8859-4"},
+#line 15 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, "ISO8859-3"},
+#line 31 "./iconv_open-irix.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, "TIS620"}
+  };
+
+#ifdef __GNUC__
+__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct mapping *
+mapping_lookup (register const char *str, register unsigned int len)
+{
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = mapping_hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= 0)
+        {
+          register int o = mappings[key].standard_name;
+          if (o >= 0)
+            {
+              register const char *s = o + stringpool;
+
+              if (*str == *s && !strcmp (str + 1, s + 1))
+                return &mappings[key];
+            }
+        }
+    }
+  return 0;
+}
diff --git a/lib/iconv_open-osf.gperf b/lib/iconv_open-osf.gperf
new file mode 100644
index 0000000..f468ff6
--- /dev/null
+++ b/lib/iconv_open-osf.gperf
@@ -0,0 +1,50 @@
+struct mapping { int standard_name; const char vendor_name[10 + 1]; };
+%struct-type
+%language=ANSI-C
+%define slot-name standard_name
+%define hash-function-name mapping_hash
+%define lookup-function-name mapping_lookup
+%readonly-tables
+%global-table
+%define word-array-name mappings
+%pic
+%%
+# On OSF/1 5.1, look in /usr/lib/nls/loc/iconv.
+ISO-8859-1, "ISO8859-1"
+ISO-8859-2, "ISO8859-2"
+ISO-8859-3, "ISO8859-3"
+ISO-8859-4, "ISO8859-4"
+ISO-8859-5, "ISO8859-5"
+ISO-8859-6, "ISO8859-6"
+ISO-8859-7, "ISO8859-7"
+ISO-8859-8, "ISO8859-8"
+ISO-8859-9, "ISO8859-9"
+ISO-8859-15, "ISO8859-15"
+CP437, "cp437"
+CP775, "cp775"
+CP850, "cp850"
+CP852, "cp852"
+CP855, "cp855"
+CP857, "cp857"
+CP861, "cp861"
+CP862, "cp862"
+CP865, "cp865"
+CP866, "cp866"
+CP869, "cp869"
+CP874, "cp874"
+CP949, "KSC5601"
+CP1250, "cp1250"
+CP1251, "cp1251"
+CP1252, "cp1252"
+CP1253, "cp1253"
+CP1254, "cp1254"
+CP1255, "cp1255"
+CP1256, "cp1256"
+CP1257, "cp1257"
+CP1258, "cp1258"
+EUC-JP, "eucJP"
+EUC-KR, "eucKR"
+EUC-TW, "eucTW"
+BIG5, "big5"
+SHIFT_JIS, "SJIS"
+TIS-620, "TACTIS"
diff --git a/lib/iconv_open-osf.h b/lib/iconv_open-osf.h
new file mode 100644
index 0000000..85e4c0f
--- /dev/null
+++ b/lib/iconv_open-osf.h
@@ -0,0 +1,278 @@
+/* ANSI-C code produced by gperf version 3.0.3 */
+/* Command-line: gperf -m 10 ./iconv_open-osf.gperf  */
+/* Computed positions: -k'4,$' */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+      && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+      && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+      && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+      && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+      && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+      && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+      && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+      && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+      && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+      && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+      && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+      && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+      && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+      && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+      && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+      && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+      && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+      && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+      && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+      && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+      && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646.  */
+#error "gperf generated tables don't work with this execution character set. 
Please report a bug to <address@hidden>."
+#endif
+
+#line 1 "./iconv_open-osf.gperf"
+struct mapping { int standard_name; const char vendor_name[10 + 1]; };
+
+#define TOTAL_KEYWORDS 38
+#define MIN_WORD_LENGTH 4
+#define MAX_WORD_LENGTH 11
+#define MIN_HASH_VALUE 6
+#define MAX_HASH_VALUE 47
+/* maximum key range = 42, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+mapping_hash (register const char *str, register unsigned int len)
+{
+  static const unsigned char asso_values[] =
+    {
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48,  2, 29,
+      24, 34, 31,  0, 15, 14, 10, 13,  2, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48,  7, 48, 48, 48, 48, 48, 48,
+      11, 48,  2,  7, 48, 48, 48,  1, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+      48, 48, 48, 48, 48, 48, 48, 48, 48
+    };
+  return len + asso_values[(unsigned char)str[3]+3] + asso_values[(unsigned 
char)str[len - 1]];
+}
+
+struct stringpool_t
+  {
+    char stringpool_str6[sizeof("CP1255")];
+    char stringpool_str7[sizeof("CP775")];
+    char stringpool_str8[sizeof("CP1250")];
+    char stringpool_str9[sizeof("EUC-TW")];
+    char stringpool_str10[sizeof("EUC-KR")];
+    char stringpool_str11[sizeof("TIS-620")];
+    char stringpool_str12[sizeof("ISO-8859-5")];
+    char stringpool_str13[sizeof("ISO-8859-15")];
+    char stringpool_str14[sizeof("BIG5")];
+    char stringpool_str15[sizeof("CP855")];
+    char stringpool_str16[sizeof("CP1258")];
+    char stringpool_str17[sizeof("CP850")];
+    char stringpool_str18[sizeof("CP865")];
+    char stringpool_str19[sizeof("EUC-JP")];
+    char stringpool_str20[sizeof("CP1257")];
+    char stringpool_str21[sizeof("CP1256")];
+    char stringpool_str22[sizeof("ISO-8859-8")];
+    char stringpool_str23[sizeof("SHIFT_JIS")];
+    char stringpool_str25[sizeof("ISO-8859-9")];
+    char stringpool_str26[sizeof("ISO-8859-7")];
+    char stringpool_str27[sizeof("ISO-8859-6")];
+    char stringpool_str29[sizeof("CP857")];
+    char stringpool_str30[sizeof("CP1252")];
+    char stringpool_str31[sizeof("CP869")];
+    char stringpool_str32[sizeof("CP949")];
+    char stringpool_str33[sizeof("CP866")];
+    char stringpool_str34[sizeof("CP437")];
+    char stringpool_str35[sizeof("CP1251")];
+    char stringpool_str36[sizeof("ISO-8859-2")];
+    char stringpool_str37[sizeof("CP1254")];
+    char stringpool_str38[sizeof("CP874")];
+    char stringpool_str39[sizeof("CP852")];
+    char stringpool_str40[sizeof("CP1253")];
+    char stringpool_str41[sizeof("ISO-8859-1")];
+    char stringpool_str42[sizeof("CP862")];
+    char stringpool_str43[sizeof("ISO-8859-4")];
+    char stringpool_str46[sizeof("ISO-8859-3")];
+    char stringpool_str47[sizeof("CP861")];
+  };
+static const struct stringpool_t stringpool_contents =
+  {
+    "CP1255",
+    "CP775",
+    "CP1250",
+    "EUC-TW",
+    "EUC-KR",
+    "TIS-620",
+    "ISO-8859-5",
+    "ISO-8859-15",
+    "BIG5",
+    "CP855",
+    "CP1258",
+    "CP850",
+    "CP865",
+    "EUC-JP",
+    "CP1257",
+    "CP1256",
+    "ISO-8859-8",
+    "SHIFT_JIS",
+    "ISO-8859-9",
+    "ISO-8859-7",
+    "ISO-8859-6",
+    "CP857",
+    "CP1252",
+    "CP869",
+    "CP949",
+    "CP866",
+    "CP437",
+    "CP1251",
+    "ISO-8859-2",
+    "CP1254",
+    "CP874",
+    "CP852",
+    "CP1253",
+    "ISO-8859-1",
+    "CP862",
+    "ISO-8859-4",
+    "ISO-8859-3",
+    "CP861"
+  };
+#define stringpool ((const char *) &stringpool_contents)
+
+static const struct mapping mappings[] =
+  {
+    {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#line 41 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str6, "cp1255"},
+#line 24 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str7, "cp775"},
+#line 36 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str8, "cp1250"},
+#line 47 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str9, "eucTW"},
+#line 46 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str10, "eucKR"},
+#line 50 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, "TACTIS"},
+#line 17 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str12, "ISO8859-5"},
+#line 22 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str13, "ISO8859-15"},
+#line 48 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str14, "big5"},
+#line 27 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str15, "cp855"},
+#line 44 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str16, "cp1258"},
+#line 25 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str17, "cp850"},
+#line 31 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str18, "cp865"},
+#line 45 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str19, "eucJP"},
+#line 43 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str20, "cp1257"},
+#line 42 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str21, "cp1256"},
+#line 20 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str22, "ISO8859-8"},
+#line 49 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str23, "SJIS"},
+    {-1},
+#line 21 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str25, "ISO8859-9"},
+#line 19 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str26, "ISO8859-7"},
+#line 18 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str27, "ISO8859-6"},
+    {-1},
+#line 28 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str29, "cp857"},
+#line 38 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str30, "cp1252"},
+#line 33 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str31, "cp869"},
+#line 35 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str32, "KSC5601"},
+#line 32 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str33, "cp866"},
+#line 23 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str34, "cp437"},
+#line 37 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, "cp1251"},
+#line 14 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str36, "ISO8859-2"},
+#line 40 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str37, "cp1254"},
+#line 34 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str38, "cp874"},
+#line 26 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str39, "cp852"},
+#line 39 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str40, "cp1253"},
+#line 13 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str41, "ISO8859-1"},
+#line 30 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str42, "cp862"},
+#line 16 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str43, "ISO8859-4"},
+    {-1}, {-1},
+#line 15 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str46, "ISO8859-3"},
+#line 29 "./iconv_open-osf.gperf"
+    {(int)(long)&((struct stringpool_t *)0)->stringpool_str47, "cp861"}
+  };
+
+#ifdef __GNUC__
+__inline
+#ifdef __GNUC_STDC_INLINE__
+__attribute__ ((__gnu_inline__))
+#endif
+#endif
+const struct mapping *
+mapping_lookup (register const char *str, register unsigned int len)
+{
+  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+    {
+      register int key = mapping_hash (str, len);
+
+      if (key <= MAX_HASH_VALUE && key >= 0)
+        {
+          register int o = mappings[key].standard_name;
+          if (o >= 0)
+            {
+              register const char *s = o + stringpool;
+
+              if (*str == *s && !strcmp (str + 1, s + 1))
+                return &mappings[key];
+            }
+        }
+    }
+  return 0;
+}
diff --git a/lib/iconv_open.c b/lib/iconv_open.c
new file mode 100644
index 0000000..3d873ac
--- /dev/null
+++ b/lib/iconv_open.c
@@ -0,0 +1,172 @@
+/* Character set conversion.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License 
along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <iconv.h>
+
+#include <errno.h>
+#include <string.h>
+#include "c-ctype.h"
+#include "c-strcase.h"
+
+#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
+
+/* Namespace cleanliness.  */
+#define mapping_lookup rpl_iconv_open_mapping_lookup
+
+/* The macro ICONV_FLAVOR is defined to one of these or undefined.  */
+
+#define ICONV_FLAVOR_AIX "iconv_open-aix.h"
+#define ICONV_FLAVOR_HPUX "iconv_open-hpux.h"
+#define ICONV_FLAVOR_IRIX "iconv_open-irix.h"
+#define ICONV_FLAVOR_OSF "iconv_open-osf.h"
+
+#ifdef ICONV_FLAVOR
+# include ICONV_FLAVOR
+#endif
+
+iconv_t
+rpl_iconv_open (const char *tocode, const char *fromcode)
+#undef iconv_open
+{
+  char fromcode_upper[32];
+  char tocode_upper[32];
+  char *fromcode_upper_end;
+  char *tocode_upper_end;
+
+#if REPLACE_ICONV_UTF
+  /* Special handling of conversion between UTF-8 and UTF-{16,32}{BE,LE}.
+     Do this here, before calling the real iconv_open(), because  OSF/1 5.1
+     iconv() to these encoding inserts a BOM, which is wrong.
+     We do not need to handle conversion between arbitrary encodings and
+     UTF-{16,32}{BE,LE}, because the 'striconveh' module implements two-step
+     conversion throough UTF-8.
+     The _ICONV_* constants are chosen to be disjoint from any iconv_t
+     returned by the system's iconv_open() functions.  Recall that iconv_t
+     is a scalar type.  */
+  if (c_toupper (fromcode[0]) == 'U'
+      && c_toupper (fromcode[1]) == 'T'
+      && c_toupper (fromcode[2]) == 'F'
+      && fromcode[3] == '-')
+    {
+      if (c_toupper (tocode[0]) == 'U'
+         && c_toupper (tocode[1]) == 'T'
+         && c_toupper (tocode[2]) == 'F'
+         && tocode[3] == '-')
+       {
+         if (strcmp (fromcode + 4, "8") == 0)
+           {
+             if (c_strcasecmp (tocode + 4, "16BE") == 0)
+               return _ICONV_UTF8_UTF16BE;
+             if (c_strcasecmp (tocode + 4, "16LE") == 0)
+               return _ICONV_UTF8_UTF16LE;
+             if (c_strcasecmp (tocode + 4, "32BE") == 0)
+               return _ICONV_UTF8_UTF32BE;
+             if (c_strcasecmp (tocode + 4, "32LE") == 0)
+               return _ICONV_UTF8_UTF32LE;
+           }
+         else if (strcmp (tocode + 4, "8") == 0)
+           {
+             if (c_strcasecmp (fromcode + 4, "16BE") == 0)
+               return _ICONV_UTF16BE_UTF8;
+             if (c_strcasecmp (fromcode + 4, "16LE") == 0)
+               return _ICONV_UTF16LE_UTF8;
+             if (c_strcasecmp (fromcode + 4, "32BE") == 0)
+               return _ICONV_UTF32BE_UTF8;
+             if (c_strcasecmp (fromcode + 4, "32LE") == 0)
+               return _ICONV_UTF32LE_UTF8;
+           }
+       }
+    }
+#endif
+
+  /* Do *not* add special support for 8-bit encodings like ASCII or ISO-8859-1
+     here.  This would lead to programs that work in some locales (such as the
+     "C" or "en_US" locales) but do not work in East Asian locales.  It is
+     better if programmers make their programs depend on GNU libiconv (except
+     on glibc systems), e.g. by using the AM_ICONV macro and documenting the
+     dependency in an INSTALL or DEPENDENCIES file.  */
+
+  /* Try with the original names first.
+     This covers the case when fromcode or tocode is a lowercase encoding name
+     that is understood by the system's iconv_open but not listed in our
+     mappings table.  */
+  {
+    iconv_t cd = iconv_open (tocode, fromcode);
+    if (cd != (iconv_t)(-1))
+      return cd;
+  }
+
+  /* Convert the encodings to upper case, because
+       1. in the arguments of iconv_open() on AIX, HP-UX, and OSF/1 the case
+         matters,
+       2. it makes searching in the table faster.  */
+  {
+    const char *p = fromcode;
+    char *q = fromcode_upper;
+    while ((*q = c_toupper (*p)) != '\0')
+      {
+       p++;
+       q++;
+       if (q == &fromcode_upper[SIZEOF (fromcode_upper)])
+         {
+           errno = EINVAL;
+           return (iconv_t)(-1);
+         }
+      }
+    fromcode_upper_end = q;
+  }
+
+  {
+    const char *p = tocode;
+    char *q = tocode_upper;
+    while ((*q = c_toupper (*p)) != '\0')
+      {
+       p++;
+       q++;
+       if (q == &tocode_upper[SIZEOF (tocode_upper)])
+         {
+           errno = EINVAL;
+           return (iconv_t)(-1);
+         }
+      }
+    tocode_upper_end = q;
+  }
+
+#ifdef ICONV_FLAVOR
+  /* Apply the mappings.  */
+  {
+    const struct mapping *m =
+      mapping_lookup (fromcode_upper, fromcode_upper_end - fromcode_upper);
+
+    fromcode = (m != NULL ? m->vendor_name : fromcode_upper);
+  }
+  {
+    const struct mapping *m =
+      mapping_lookup (tocode_upper, tocode_upper_end - tocode_upper);
+
+    tocode = (m != NULL ? m->vendor_name : tocode_upper);
+  }
+#else
+  fromcode = fromcode_upper;
+  tocode = tocode_upper;
+#endif
+
+  return iconv_open (tocode, fromcode);
+}
diff --git a/lib/iconveh.h b/lib/iconveh.h
new file mode 100644
index 0000000..06cda52
--- /dev/null
+++ b/lib/iconveh.h
@@ -0,0 +1,41 @@
+/* Character set conversion handler type.
+   Copyright (C) 2001-2007, 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ICONVEH_H
+#define _ICONVEH_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Handling of unconvertible characters.  */
+enum iconv_ilseq_handler
+{
+  iconveh_error,               /* return and set errno = EILSEQ */
+  iconveh_question_mark,       /* use one '?' per unconvertible character */
+  iconveh_escape_sequence      /* use escape sequence \uxxxx or \Uxxxxxxxx */
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _ICONVEH_H */
diff --git a/lib/ref-add.sed b/lib/ref-add.sed
new file mode 100644
index 0000000..ebee41e
--- /dev/null
+++ b/lib/ref-add.sed
@@ -0,0 +1,10 @@
+/^# Packages using this file: / {
+  s/# Packages using this file://
+  ta
+  :a
+  s/ guile / guile /
+  tb
+  s/ $/ guile /
+  :b
+  s/^/# Packages using this file:/
+}
diff --git a/lib/ref-del.sed b/lib/ref-del.sed
new file mode 100644
index 0000000..26fed67
--- /dev/null
+++ b/lib/ref-del.sed
@@ -0,0 +1,5 @@
+/^# Packages using this file: / {
+  s/# Packages using this file://
+  s/ guile / /
+  s/^/# Packages using this file:/
+}
diff --git a/lib/stdint.in.h b/lib/stdint.in.h
new file mode 100644
index 0000000..11a2117
--- /dev/null
+++ b/lib/stdint.in.h
@@ -0,0 +1,567 @@
+/* Copyright (C) 2001-2002, 2004-2009 Free Software Foundation, Inc.
+   Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood.
+   This file is part of gnulib.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/*
+ * ISO C 99 <stdint.h> for platforms that lack it.
+ * <http://www.opengroup.org/susv3xbd/stdint.h.html>
+ */
+
+#ifndef _GL_STDINT_H
+
+/* When including a system file that in turn includes <inttypes.h>,
+   use the system <inttypes.h>, not our substitute.  This avoids
+   problems with (for example) VMS, whose <sys/bitypes.h> includes
+   <inttypes.h>.  */
+#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
+
+/* Get those types that are already defined in other system include
+   files, so that we can "#define int8_t signed char" below without
+   worrying about a later system include file containing a "typedef
+   signed char int8_t;" that will get messed up by our macro.  Our
+   macros should all be consistent with the system versions, except
+   for the "fast" types and macros, which we recommend against using
+   in public interfaces due to compiler differences.  */
+
+#if @HAVE_STDINT_H@
+# if defined __sgi && ! defined __c99
+   /* Bypass IRIX's <stdint.h> if in C89 mode, since it merely annoys users
+      with "This header file is to be used only for c99 mode compilations"
+      diagnostics.  */
+#  define __STDINT_H__
+# endif
+  /* Other systems may have an incomplete or buggy <stdint.h>.
+     Include it before <inttypes.h>, since any "#include <stdint.h>"
+     in <inttypes.h> would reinclude us, skipping our contents because
+     _GL_STDINT_H is defined.
+     The include_next requires a split double-inclusion guard.  */
+# if __GNUC__ >= 3
address@hidden@
+# endif
+# @INCLUDE_NEXT@ @NEXT_STDINT_H@
+#endif
+
+#if ! defined _GL_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H
+#define _GL_STDINT_H
+
+/* <sys/types.h> defines some of the stdint.h types as well, on glibc,
+   IRIX 6.5, and OpenBSD 3.8 (via <machine/types.h>).
+   AIX 5.2 <sys/types.h> isn't needed and causes troubles.
+   MacOS X 10.4.6 <sys/types.h> includes <stdint.h> (which is us), but
+   relies on the system <stdint.h> definitions, so include
+   <sys/types.h> after @address@hidden  */
+#if @HAVE_SYS_TYPES_H@ && ! defined _AIX
+# include <sys/types.h>
+#endif
+
+/* Get LONG_MIN, LONG_MAX, ULONG_MAX.  */
+#include <limits.h>
+
+#if @HAVE_INTTYPES_H@
+  /* In OpenBSD 3.8, <inttypes.h> includes <machine/types.h>, which defines
+     int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__.
+     <inttypes.h> also defines intptr_t and uintptr_t.  */
+# include <inttypes.h>
+#elif @HAVE_SYS_INTTYPES_H@
+  /* Solaris 7 <sys/inttypes.h> has the types except the *_fast*_t types, and
+     the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX.  */
+# include <sys/inttypes.h>
+#endif
+
+#if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__
+  /* Linux libc4 >= 4.6.7 and libc5 have a <sys/bitypes.h> that defines
+     int{8,16,32,64}_t and __BIT_TYPES_DEFINED__.  In libc5 >= 5.2.2 it is
+     included by <sys/types.h>.  */
+# include <sys/bitypes.h>
+#endif
+
+#undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
+
+/* Minimum and maximum values for a integer type under the usual assumption.
+   Return an unspecified value if BITS == 0, adding a check to pacify
+   picky compilers.  */
+
+#define _STDINT_MIN(signed, bits, zero) \
+  ((signed) ? (- ((zero) + 1) << ((bits) ? (bits) - 1 : 0)) : (zero))
+
+#define _STDINT_MAX(signed, bits, zero) \
+  ((signed) \
+   ? ~ _STDINT_MIN (signed, bits, zero) \
+   : /* The expression for the unsigned case.  The subtraction of (signed) \
+       is a nop in the unsigned case and avoids "signed integer overflow" \
+       warnings in the signed case.  */ \
+     ((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1)
+
+/* 7.18.1.1. Exact-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+   types have 8, 16, 32, optionally 64 bits.  */
+
+#undef int8_t
+#undef uint8_t
+typedef signed char gl_int8_t;
+typedef unsigned char gl_uint8_t;
+#define int8_t gl_int8_t
+#define uint8_t gl_uint8_t
+
+#undef int16_t
+#undef uint16_t
+typedef short int gl_int16_t;
+typedef unsigned short int gl_uint16_t;
+#define int16_t gl_int16_t
+#define uint16_t gl_uint16_t
+
+#undef int32_t
+#undef uint32_t
+typedef int gl_int32_t;
+typedef unsigned int gl_uint32_t;
+#define int32_t gl_int32_t
+#define uint32_t gl_uint32_t
+
+/* Do not undefine int64_t if gnulib is not being used with 64-bit
+   types, since otherwise it breaks platforms like Tandem/NSK.  */
+#if LONG_MAX >> 31 >> 31 == 1
+# undef int64_t
+typedef long int gl_int64_t;
+# define int64_t gl_int64_t
+# define GL_INT64_T
+#elif defined _MSC_VER
+# undef int64_t
+typedef __int64 gl_int64_t;
+# define int64_t gl_int64_t
+# define GL_INT64_T
+#elif @HAVE_LONG_LONG_INT@
+# undef int64_t
+typedef long long int gl_int64_t;
+# define int64_t gl_int64_t
+# define GL_INT64_T
+#endif
+
+#if ULONG_MAX >> 31 >> 31 >> 1 == 1
+# undef uint64_t
+typedef unsigned long int gl_uint64_t;
+# define uint64_t gl_uint64_t
+# define GL_UINT64_T
+#elif defined _MSC_VER
+# undef uint64_t
+typedef unsigned __int64 gl_uint64_t;
+# define uint64_t gl_uint64_t
+# define GL_UINT64_T
+#elif @HAVE_UNSIGNED_LONG_LONG_INT@
+# undef uint64_t
+typedef unsigned long long int gl_uint64_t;
+# define uint64_t gl_uint64_t
+# define GL_UINT64_T
+#endif
+
+/* Avoid collision with Solaris 2.5.1 <pthread.h> etc.  */
+#define _UINT8_T
+#define _UINT32_T
+#define _UINT64_T
+
+
+/* 7.18.1.2. Minimum-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+   types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
+   are the same as the corresponding N_t types.  */
+
+#undef int_least8_t
+#undef uint_least8_t
+#undef int_least16_t
+#undef uint_least16_t
+#undef int_least32_t
+#undef uint_least32_t
+#undef int_least64_t
+#undef uint_least64_t
+#define int_least8_t int8_t
+#define uint_least8_t uint8_t
+#define int_least16_t int16_t
+#define uint_least16_t uint16_t
+#define int_least32_t int32_t
+#define uint_least32_t uint32_t
+#ifdef GL_INT64_T
+# define int_least64_t int64_t
+#endif
+#ifdef GL_UINT64_T
+# define uint_least64_t uint64_t
+#endif
+
+/* 7.18.1.3. Fastest minimum-width integer types */
+
+/* Note: Other <stdint.h> substitutes may define these types differently.
+   It is not recommended to use these types in public header files. */
+
+/* Here we assume a standard architecture where the hardware integer
+   types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
+   are taken from the same list of types.  Assume that 'long int'
+   is fast enough for all narrower integers.  */
+
+#undef int_fast8_t
+#undef uint_fast8_t
+#undef int_fast16_t
+#undef uint_fast16_t
+#undef int_fast32_t
+#undef uint_fast32_t
+#undef int_fast64_t
+#undef uint_fast64_t
+typedef long int gl_int_fast8_t;
+typedef unsigned long int gl_uint_fast8_t;
+typedef long int gl_int_fast16_t;
+typedef unsigned long int gl_uint_fast16_t;
+typedef long int gl_int_fast32_t;
+typedef unsigned long int gl_uint_fast32_t;
+#define int_fast8_t gl_int_fast8_t
+#define uint_fast8_t gl_uint_fast8_t
+#define int_fast16_t gl_int_fast16_t
+#define uint_fast16_t gl_uint_fast16_t
+#define int_fast32_t gl_int_fast32_t
+#define uint_fast32_t gl_uint_fast32_t
+#ifdef GL_INT64_T
+# define int_fast64_t int64_t
+#endif
+#ifdef GL_UINT64_T
+# define uint_fast64_t uint64_t
+#endif
+
+/* 7.18.1.4. Integer types capable of holding object pointers */
+
+#undef intptr_t
+#undef uintptr_t
+typedef long int gl_intptr_t;
+typedef unsigned long int gl_uintptr_t;
+#define intptr_t gl_intptr_t
+#define uintptr_t gl_uintptr_t
+
+/* 7.18.1.5. Greatest-width integer types */
+
+/* Note: These types are compiler dependent. It may be unwise to use them in
+   public header files. */
+
+#undef intmax_t
+#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+typedef long long int gl_intmax_t;
+# define intmax_t gl_intmax_t
+#elif defined GL_INT64_T
+# define intmax_t int64_t
+#else
+typedef long int gl_intmax_t;
+# define intmax_t gl_intmax_t
+#endif
+
+#undef uintmax_t
+#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+typedef unsigned long long int gl_uintmax_t;
+# define uintmax_t gl_uintmax_t
+#elif defined GL_UINT64_T
+# define uintmax_t uint64_t
+#else
+typedef unsigned long int gl_uintmax_t;
+# define uintmax_t gl_uintmax_t
+#endif
+
+/* Verify that intmax_t and uintmax_t have the same size.  Too much code
+   breaks if this is not the case.  If this check fails, the reason is likely
+   to be found in the autoconf macros.  */
+typedef int _verify_intmax_size[2 * (sizeof (intmax_t) == sizeof (uintmax_t)) 
- 1];
+
+/* 7.18.2. Limits of specified-width integer types */
+
+#if ! defined __cplusplus || defined __STDC_LIMIT_MACROS
+
+/* 7.18.2.1. Limits of exact-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+   types have 8, 16, 32, optionally 64 bits.  */
+
+#undef INT8_MIN
+#undef INT8_MAX
+#undef UINT8_MAX
+#define INT8_MIN  (~ INT8_MAX)
+#define INT8_MAX  127
+#define UINT8_MAX  255
+
+#undef INT16_MIN
+#undef INT16_MAX
+#undef UINT16_MAX
+#define INT16_MIN  (~ INT16_MAX)
+#define INT16_MAX  32767
+#define UINT16_MAX  65535
+
+#undef INT32_MIN
+#undef INT32_MAX
+#undef UINT32_MAX
+#define INT32_MIN  (~ INT32_MAX)
+#define INT32_MAX  2147483647
+#define UINT32_MAX  4294967295U
+
+#undef INT64_MIN
+#undef INT64_MAX
+#ifdef GL_INT64_T
+/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0
+   evaluates the latter incorrectly in preprocessor expressions.  */
+# define INT64_MIN  (- INTMAX_C (1) << 63)
+# define INT64_MAX  INTMAX_C (9223372036854775807)
+#endif
+
+#undef UINT64_MAX
+#ifdef GL_UINT64_T
+# define UINT64_MAX  UINTMAX_C (18446744073709551615)
+#endif
+
+/* 7.18.2.2. Limits of minimum-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+   types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types
+   are the same as the corresponding N_t types.  */
+
+#undef INT_LEAST8_MIN
+#undef INT_LEAST8_MAX
+#undef UINT_LEAST8_MAX
+#define INT_LEAST8_MIN  INT8_MIN
+#define INT_LEAST8_MAX  INT8_MAX
+#define UINT_LEAST8_MAX  UINT8_MAX
+
+#undef INT_LEAST16_MIN
+#undef INT_LEAST16_MAX
+#undef UINT_LEAST16_MAX
+#define INT_LEAST16_MIN  INT16_MIN
+#define INT_LEAST16_MAX  INT16_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+
+#undef INT_LEAST32_MIN
+#undef INT_LEAST32_MAX
+#undef UINT_LEAST32_MAX
+#define INT_LEAST32_MIN  INT32_MIN
+#define INT_LEAST32_MAX  INT32_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+
+#undef INT_LEAST64_MIN
+#undef INT_LEAST64_MAX
+#ifdef GL_INT64_T
+# define INT_LEAST64_MIN  INT64_MIN
+# define INT_LEAST64_MAX  INT64_MAX
+#endif
+
+#undef UINT_LEAST64_MAX
+#ifdef GL_UINT64_T
+# define UINT_LEAST64_MAX  UINT64_MAX
+#endif
+
+/* 7.18.2.3. Limits of fastest minimum-width integer types */
+
+/* Here we assume a standard architecture where the hardware integer
+   types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types
+   are taken from the same list of types.  */
+
+#undef INT_FAST8_MIN
+#undef INT_FAST8_MAX
+#undef UINT_FAST8_MAX
+#define INT_FAST8_MIN  LONG_MIN
+#define INT_FAST8_MAX  LONG_MAX
+#define UINT_FAST8_MAX  ULONG_MAX
+
+#undef INT_FAST16_MIN
+#undef INT_FAST16_MAX
+#undef UINT_FAST16_MAX
+#define INT_FAST16_MIN  LONG_MIN
+#define INT_FAST16_MAX  LONG_MAX
+#define UINT_FAST16_MAX  ULONG_MAX
+
+#undef INT_FAST32_MIN
+#undef INT_FAST32_MAX
+#undef UINT_FAST32_MAX
+#define INT_FAST32_MIN  LONG_MIN
+#define INT_FAST32_MAX  LONG_MAX
+#define UINT_FAST32_MAX  ULONG_MAX
+
+#undef INT_FAST64_MIN
+#undef INT_FAST64_MAX
+#ifdef GL_INT64_T
+# define INT_FAST64_MIN  INT64_MIN
+# define INT_FAST64_MAX  INT64_MAX
+#endif
+
+#undef UINT_FAST64_MAX
+#ifdef GL_UINT64_T
+# define UINT_FAST64_MAX  UINT64_MAX
+#endif
+
+/* 7.18.2.4. Limits of integer types capable of holding object pointers */
+
+#undef INTPTR_MIN
+#undef INTPTR_MAX
+#undef UINTPTR_MAX
+#define INTPTR_MIN  LONG_MIN
+#define INTPTR_MAX  LONG_MAX
+#define UINTPTR_MAX  ULONG_MAX
+
+/* 7.18.2.5. Limits of greatest-width integer types */
+
+#undef INTMAX_MIN
+#undef INTMAX_MAX
+#ifdef INT64_MAX
+# define INTMAX_MIN  INT64_MIN
+# define INTMAX_MAX  INT64_MAX
+#else
+# define INTMAX_MIN  INT32_MIN
+# define INTMAX_MAX  INT32_MAX
+#endif
+
+#undef UINTMAX_MAX
+#ifdef UINT64_MAX
+# define UINTMAX_MAX  UINT64_MAX
+#else
+# define UINTMAX_MAX  UINT32_MAX
+#endif
+
+/* 7.18.3. Limits of other integer types */
+
+/* ptrdiff_t limits */
+#undef PTRDIFF_MIN
+#undef PTRDIFF_MAX
+#if @APPLE_UNIVERSAL_BUILD@
+# ifdef _LP64
+#  define PTRDIFF_MIN  _STDINT_MIN (1, 64, 0l)
+#  define PTRDIFF_MAX  _STDINT_MAX (1, 64, 0l)
+# else
+#  define PTRDIFF_MIN  _STDINT_MIN (1, 32, 0)
+#  define PTRDIFF_MAX  _STDINT_MAX (1, 32, 0)
+# endif
+#else
+# define PTRDIFF_MIN  \
+    _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, address@hidden@)
+# define PTRDIFF_MAX  \
+    _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, address@hidden@)
+#endif
+
+/* sig_atomic_t limits */
+#undef SIG_ATOMIC_MIN
+#undef SIG_ATOMIC_MAX
+#define SIG_ATOMIC_MIN  \
+   _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
+               address@hidden@)
+#define SIG_ATOMIC_MAX  \
+   _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \
+               address@hidden@)
+
+
+/* size_t limit */
+#undef SIZE_MAX
+#if @APPLE_UNIVERSAL_BUILD@
+# ifdef _LP64
+#  define SIZE_MAX  _STDINT_MAX (0, 64, 0ul)
+# else
+#  define SIZE_MAX  _STDINT_MAX (0, 32, 0ul)
+# endif
+#else
+# define SIZE_MAX  _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, address@hidden@)
+#endif
+
+/* wchar_t limits */
+/* Get WCHAR_MIN, WCHAR_MAX.
+   This include is not on the top, above, because on OSF/1 4.0 we have a 
sequence of nested
+   includes <wchar.h> -> <stdio.h> -> <getopt.h> -> <stdlib.h>, and the latter 
includes
+   <stdint.h> and assumes its types are already defined.  */
+#if ! (defined WCHAR_MIN && defined WCHAR_MAX)
+# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
+# include <wchar.h>
+# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
+#endif
+#undef WCHAR_MIN
+#undef WCHAR_MAX
+#define WCHAR_MIN  \
+   _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, address@hidden@)
+#define WCHAR_MAX  \
+   _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, address@hidden@)
+
+/* wint_t limits */
+#undef WINT_MIN
+#undef WINT_MAX
+#define WINT_MIN  \
+   _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, address@hidden@)
+#define WINT_MAX  \
+   _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, address@hidden@)
+
+#endif /* !defined __cplusplus || defined __STDC_LIMIT_MACROS */
+
+/* 7.18.4. Macros for integer constants */
+
+#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS
+
+/* 7.18.4.1. Macros for minimum-width integer constants */
+/* According to ISO C 99 Technical Corrigendum 1 */
+
+/* Here we assume a standard architecture where the hardware integer
+   types have 8, 16, 32, optionally 64 bits, and int is 32 bits.  */
+
+#undef INT8_C
+#undef UINT8_C
+#define INT8_C(x) x
+#define UINT8_C(x) x
+
+#undef INT16_C
+#undef UINT16_C
+#define INT16_C(x) x
+#define UINT16_C(x) x
+
+#undef INT32_C
+#undef UINT32_C
+#define INT32_C(x) x
+#define UINT32_C(x) x ## U
+
+#undef INT64_C
+#undef UINT64_C
+#if LONG_MAX >> 31 >> 31 == 1
+# define INT64_C(x) x##L
+#elif defined _MSC_VER
+# define INT64_C(x) x##i64
+#elif @HAVE_LONG_LONG_INT@
+# define INT64_C(x) x##LL
+#endif
+#if ULONG_MAX >> 31 >> 31 >> 1 == 1
+# define UINT64_C(x) x##UL
+#elif defined _MSC_VER
+# define UINT64_C(x) x##ui64
+#elif @HAVE_UNSIGNED_LONG_LONG_INT@
+# define UINT64_C(x) x##ULL
+#endif
+
+/* 7.18.4.2. Macros for greatest-width integer constants */
+
+#undef INTMAX_C
+#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+# define INTMAX_C(x)   x##LL
+#elif defined GL_INT64_T
+# define INTMAX_C(x)   INT64_C(x)
+#else
+# define INTMAX_C(x)   x##L
+#endif
+
+#undef UINTMAX_C
+#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+# define UINTMAX_C(x)  x##ULL
+#elif defined GL_UINT64_T
+# define UINTMAX_C(x)  UINT64_C(x)
+#else
+# define UINTMAX_C(x)  x##UL
+#endif
+
+#endif /* !defined __cplusplus || defined __STDC_CONSTANT_MACROS */
+
+#endif /* _GL_STDINT_H */
+#endif /* !defined _GL_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */
diff --git a/lib/striconveh.c b/lib/striconveh.c
new file mode 100644
index 0000000..b39a01f
--- /dev/null
+++ b/lib/striconveh.c
@@ -0,0 +1,1251 @@
+/* Character set conversion with error handling.
+   Copyright (C) 2001-2008 Free Software Foundation, Inc.
+   Written by Bruno Haible and Simon Josefsson.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "striconveh.h"
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if HAVE_ICONV
+# include <iconv.h>
+# include "unistr.h"
+#endif
+
+#include "c-strcase.h"
+#include "c-strcaseeq.h"
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+
+#if HAVE_ICONV
+
+/* The caller must provide CD, CD1, CD2, not just CD, because when a conversion
+   error occurs, we may have to determine the Unicode representation of the
+   inconvertible character.  */
+
+/* iconv_carefully is like iconv, except that it stops as soon as it encounters
+   a conversion error, and it returns in *INCREMENTED a boolean telling whether
+   it has incremented the input pointers past the error location.  */
+# if !defined _LIBICONV_VERSION && !defined __GLIBC__
+/* Irix iconv() inserts a NUL byte if it cannot convert.
+   NetBSD iconv() inserts a question mark if it cannot convert.
+   Only GNU libiconv and GNU libc are known to prefer to fail rather
+   than doing a lossy conversion.  */
+static size_t
+iconv_carefully (iconv_t cd,
+                const char **inbuf, size_t *inbytesleft,
+                char **outbuf, size_t *outbytesleft,
+                bool *incremented)
+{
+  const char *inptr = *inbuf;
+  const char *inptr_end = inptr + *inbytesleft;
+  char *outptr = *outbuf;
+  size_t outsize = *outbytesleft;
+  const char *inptr_before;
+  size_t res;
+
+  do
+    {
+      size_t insize;
+
+      inptr_before = inptr;
+      res = (size_t)(-1);
+
+      for (insize = 1; inptr + insize <= inptr_end; insize++)
+       {
+         res = iconv (cd,
+                      (ICONV_CONST char **) &inptr, &insize,
+                      &outptr, &outsize);
+         if (!(res == (size_t)(-1) && errno == EINVAL))
+           break;
+         /* iconv can eat up a shift sequence but give EINVAL while attempting
+            to convert the first character.  E.g. libiconv does this.  */
+         if (inptr > inptr_before)
+           {
+             res = 0;
+             break;
+           }
+       }
+
+      if (res == 0)
+       {
+         *outbuf = outptr;
+         *outbytesleft = outsize;
+       }
+    }
+  while (res == 0 && inptr < inptr_end);
+
+  *inbuf = inptr;
+  *inbytesleft = inptr_end - inptr;
+  if (res != (size_t)(-1) && res > 0)
+    {
+      /* iconv() has already incremented INPTR.  We cannot go back to a
+        previous INPTR, otherwise the state inside CD would become invalid,
+        if FROM_CODESET is a stateful encoding.  So, tell the caller that
+        *INBUF has already been incremented.  */
+      *incremented = (inptr > inptr_before);
+      errno = EILSEQ;
+      return (size_t)(-1);
+    }
+  else
+    {
+      *incremented = false;
+      return res;
+    }
+}
+# else
+#  define iconv_carefully(cd, inbuf, inbytesleft, outbuf, outbytesleft, 
incremented) \
+     (*(incremented) = false, \
+      iconv (cd, (ICONV_CONST char **) (inbuf), inbytesleft, outbuf, 
outbytesleft))
+# endif
+
+/* iconv_carefully_1 is like iconv_carefully, except that it stops after
+   converting one character or one shift sequence.  */
+static size_t
+iconv_carefully_1 (iconv_t cd,
+                  const char **inbuf, size_t *inbytesleft,
+                  char **outbuf, size_t *outbytesleft,
+                  bool *incremented)
+{
+  const char *inptr_before = *inbuf;
+  const char *inptr = inptr_before;
+  const char *inptr_end = inptr_before + *inbytesleft;
+  char *outptr = *outbuf;
+  size_t outsize = *outbytesleft;
+  size_t res = (size_t)(-1);
+  size_t insize;
+
+  for (insize = 1; inptr_before + insize <= inptr_end; insize++)
+    {
+      inptr = inptr_before;
+      res = iconv (cd,
+                  (ICONV_CONST char **) &inptr, &insize,
+                  &outptr, &outsize);
+      if (!(res == (size_t)(-1) && errno == EINVAL))
+       break;
+      /* iconv can eat up a shift sequence but give EINVAL while attempting
+        to convert the first character.  E.g. libiconv does this.  */
+      if (inptr > inptr_before)
+       {
+         res = 0;
+         break;
+       }
+    }
+
+  *inbuf = inptr;
+  *inbytesleft = inptr_end - inptr;
+# if !defined _LIBICONV_VERSION && !defined __GLIBC__
+  /* Irix iconv() inserts a NUL byte if it cannot convert.
+     NetBSD iconv() inserts a question mark if it cannot convert.
+     Only GNU libiconv and GNU libc are known to prefer to fail rather
+     than doing a lossy conversion.  */
+  if (res != (size_t)(-1) && res > 0)
+    {
+      /* iconv() has already incremented INPTR.  We cannot go back to a
+        previous INPTR, otherwise the state inside CD would become invalid,
+        if FROM_CODESET is a stateful encoding.  So, tell the caller that
+        *INBUF has already been incremented.  */
+      *incremented = (inptr > inptr_before);
+      errno = EILSEQ;
+      return (size_t)(-1);
+    }
+# endif
+
+  if (res != (size_t)(-1))
+    {
+      *outbuf = outptr;
+      *outbytesleft = outsize;
+    }
+  *incremented = false;
+  return res;
+}
+
+/* utf8conv_carefully is like iconv, except that
+     - it converts from UTF-8 to UTF-8,
+     - it stops as soon as it encounters a conversion error, and it returns
+       in *INCREMENTED a boolean telling whether it has incremented the input
+       pointers past the error location,
+     - if one_character_only is true, it stops after converting one
+       character.  */
+static size_t
+utf8conv_carefully (bool one_character_only,
+                   const char **inbuf, size_t *inbytesleft,
+                   char **outbuf, size_t *outbytesleft,
+                   bool *incremented)
+{
+  const char *inptr = *inbuf;
+  size_t insize = *inbytesleft;
+  char *outptr = *outbuf;
+  size_t outsize = *outbytesleft;
+  size_t res;
+
+  res = 0;
+  do
+    {
+      ucs4_t uc;
+      int n;
+      int m;
+
+      n = u8_mbtoucr (&uc, (const uint8_t *) inptr, insize);
+      if (n < 0)
+       {
+         errno = (n == -2 ? EINVAL : EILSEQ);
+         n = u8_mbtouc (&uc, (const uint8_t *) inptr, insize);
+         inptr += n;
+         insize -= n;
+         res = (size_t)(-1);
+         *incremented = true;
+         break;
+       }
+      if (outsize == 0)
+       {
+         errno = E2BIG;
+         res = (size_t)(-1);
+         *incremented = false;
+         break;
+       }
+      m = u8_uctomb ((uint8_t *) outptr, uc, outsize);
+      if (m == -2)
+       {
+         errno = E2BIG;
+         res = (size_t)(-1);
+         *incremented = false;
+         break;
+       }
+      inptr += n;
+      insize -= n;
+      if (m == -1)
+       {
+         errno = EILSEQ;
+         res = (size_t)(-1);
+         *incremented = true;
+         break;
+       }
+      outptr += m;
+      outsize -= m;
+    }
+  while (!one_character_only && insize > 0);
+
+  *inbuf = inptr;
+  *inbytesleft = insize;
+  *outbuf = outptr;
+  *outbytesleft = outsize;
+  return res;
+}
+
+static int
+mem_cd_iconveh_internal (const char *src, size_t srclen,
+                        iconv_t cd, iconv_t cd1, iconv_t cd2,
+                        enum iconv_ilseq_handler handler,
+                        size_t extra_alloc,
+                        size_t *offsets,
+                        char **resultp, size_t *lengthp)
+{
+  /* When a conversion error occurs, we cannot start using CD1 and CD2 at
+     this point: FROM_CODESET may be a stateful encoding like ISO-2022-KR.
+     Instead, we have to start afresh from the beginning of SRC.  */
+  /* Use a temporary buffer, so that for small strings, a single malloc()
+     call will be sufficient.  */
+# define tmpbufsize 4096
+  /* The alignment is needed when converting e.g. to glibc's WCHAR_T or
+     libiconv's UCS-4-INTERNAL encoding.  */
+  union { unsigned int align; char buf[tmpbufsize]; } tmp;
+# define tmpbuf tmp.buf
+
+  char *initial_result;
+  char *result;
+  size_t allocated;
+  size_t length;
+  size_t last_length = (size_t)(-1); /* only needed if offsets != NULL */
+
+  if (*resultp != NULL && *lengthp >= sizeof (tmpbuf))
+    {
+      initial_result = *resultp;
+      allocated = *lengthp;
+    }
+  else
+    {
+      initial_result = tmpbuf;
+      allocated = sizeof (tmpbuf);
+    }
+  result = initial_result;
+
+  /* Test whether a direct conversion is possible at all.  */
+  if (cd == (iconv_t)(-1))
+    goto indirectly;
+
+  if (offsets != NULL)
+    {
+      size_t i;
+
+      for (i = 0; i < srclen; i++)
+       offsets[i] = (size_t)(-1);
+
+      last_length = (size_t)(-1);
+    }
+  length = 0;
+
+  /* First, try a direct conversion, and see whether a conversion error
+     occurs at all.  */
+  {
+    const char *inptr = src;
+    size_t insize = srclen;
+
+    /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug.  */
+# if defined _LIBICONV_VERSION \
+     || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun)
+    /* Set to the initial state.  */
+    iconv (cd, NULL, NULL, NULL, NULL);
+# endif
+
+    while (insize > 0)
+      {
+       char *outptr = result + length;
+       size_t outsize = allocated - extra_alloc - length;
+       bool incremented;
+       size_t res;
+       bool grow;
+
+       if (offsets != NULL)
+         {
+           if (length != last_length) /* ensure that offset[] be increasing */
+             {
+               offsets[inptr - src] = length;
+               last_length = length;
+             }
+           res = iconv_carefully_1 (cd,
+                                    &inptr, &insize,
+                                    &outptr, &outsize,
+                                    &incremented);
+         }
+       else
+         /* Use iconv_carefully instead of iconv here, because:
+            - If TO_CODESET is UTF-8, we can do the error handling in this
+              loop, no need for a second loop,
+            - With iconv() implementations other than GNU libiconv and GNU
+              libc, if we use iconv() in a big swoop, checking for an E2BIG
+              return, we lose the number of irreversible conversions.  */
+         res = iconv_carefully (cd,
+                                &inptr, &insize,
+                                &outptr, &outsize,
+                                &incremented);
+
+       length = outptr - result;
+       grow = (length + extra_alloc > allocated / 2);
+       if (res == (size_t)(-1))
+         {
+           if (errno == E2BIG)
+             grow = true;
+           else if (errno == EINVAL)
+             break;
+           else if (errno == EILSEQ && handler != iconveh_error)
+             {
+               if (cd2 == (iconv_t)(-1))
+                 {
+                   /* TO_CODESET is UTF-8.  */
+                   /* Error handling can produce up to 1 byte of output.  */
+                   if (length + 1 + extra_alloc > allocated)
+                     {
+                       char *memory;
+
+                       allocated = 2 * allocated;
+                       if (length + 1 + extra_alloc > allocated)
+                         abort ();
+                       if (result == initial_result)
+                         memory = (char *) malloc (allocated);
+                       else
+                         memory = (char *) realloc (result, allocated);
+                       if (memory == NULL)
+                         {
+                           if (result != initial_result)
+                             free (result);
+                           errno = ENOMEM;
+                           return -1;
+                         }
+                       if (result == initial_result)
+                         memcpy (memory, initial_result, length);
+                       result = memory;
+                       grow = false;
+                     }
+                   /* The input is invalid in FROM_CODESET.  Eat up one byte
+                      and emit a question mark.  */
+                   if (!incremented)
+                     {
+                       if (insize == 0)
+                         abort ();
+                       inptr++;
+                       insize--;
+                     }
+                   result[length] = '?';
+                   length++;
+                 }
+               else
+                 goto indirectly;
+             }
+           else
+             {
+               if (result != initial_result)
+                 {
+                   int saved_errno = errno;
+                   free (result);
+                   errno = saved_errno;
+                 }
+               return -1;
+             }
+         }
+       if (insize == 0)
+         break;
+       if (grow)
+         {
+           char *memory;
+
+           allocated = 2 * allocated;
+           if (result == initial_result)
+             memory = (char *) malloc (allocated);
+           else
+             memory = (char *) realloc (result, allocated);
+           if (memory == NULL)
+             {
+               if (result != initial_result)
+                 free (result);
+               errno = ENOMEM;
+               return -1;
+             }
+           if (result == initial_result)
+             memcpy (memory, initial_result, length);
+           result = memory;
+         }
+      }
+  }
+
+  /* Now get the conversion state back to the initial state.
+     But avoid glibc-2.1 bug and Solaris 2.7 bug.  */
+#if defined _LIBICONV_VERSION \
+    || !((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) || defined __sun)
+  for (;;)
+    {
+      char *outptr = result + length;
+      size_t outsize = allocated - extra_alloc - length;
+      size_t res;
+
+      res = iconv (cd, NULL, NULL, &outptr, &outsize);
+      length = outptr - result;
+      if (res == (size_t)(-1))
+       {
+         if (errno == E2BIG)
+           {
+             char *memory;
+
+             allocated = 2 * allocated;
+             if (result == initial_result)
+               memory = (char *) malloc (allocated);
+             else
+               memory = (char *) realloc (result, allocated);
+             if (memory == NULL)
+               {
+                 if (result != initial_result)
+                   free (result);
+                 errno = ENOMEM;
+                 return -1;
+               }
+             if (result == initial_result)
+               memcpy (memory, initial_result, length);
+             result = memory;
+           }
+         else
+           {
+             if (result != initial_result)
+               {
+                 int saved_errno = errno;
+                 free (result);
+                 errno = saved_errno;
+               }
+             return -1;
+           }
+       }
+      else
+       break;
+    }
+#endif
+
+  /* The direct conversion succeeded.  */
+  goto done;
+
+ indirectly:
+  /* The direct conversion failed.
+     Use a conversion through UTF-8.  */
+  if (offsets != NULL)
+    {
+      size_t i;
+
+      for (i = 0; i < srclen; i++)
+       offsets[i] = (size_t)(-1);
+
+      last_length = (size_t)(-1);
+    }
+  length = 0;
+  {
+    const bool slowly = (offsets != NULL || handler == iconveh_error);
+# define utf8bufsize 4096 /* may also be smaller or larger than tmpbufsize */
+    char utf8buf[utf8bufsize + 1];
+    size_t utf8len = 0;
+    const char *in1ptr = src;
+    size_t in1size = srclen;
+    bool do_final_flush1 = true;
+    bool do_final_flush2 = true;
+
+    /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug.  */
+# if defined _LIBICONV_VERSION \
+     || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun)
+    /* Set to the initial state.  */
+    if (cd1 != (iconv_t)(-1))
+      iconv (cd1, NULL, NULL, NULL, NULL);
+    if (cd2 != (iconv_t)(-1))
+      iconv (cd2, NULL, NULL, NULL, NULL);
+# endif
+
+    while (in1size > 0 || do_final_flush1 || utf8len > 0 || do_final_flush2)
+      {
+       char *out1ptr = utf8buf + utf8len;
+       size_t out1size = utf8bufsize - utf8len;
+       bool incremented1;
+       size_t res1;
+       int errno1;
+
+       /* Conversion step 1: from FROM_CODESET to UTF-8.  */
+       if (in1size > 0)
+         {
+           if (offsets != NULL
+               && length != last_length) /* ensure that offset[] be increasing 
*/
+             {
+               offsets[in1ptr - src] = length;
+               last_length = length;
+             }
+           if (cd1 != (iconv_t)(-1))
+             {
+               if (slowly)
+                 res1 = iconv_carefully_1 (cd1,
+                                           &in1ptr, &in1size,
+                                           &out1ptr, &out1size,
+                                           &incremented1);
+               else
+                 res1 = iconv_carefully (cd1,
+                                         &in1ptr, &in1size,
+                                         &out1ptr, &out1size,
+                                         &incremented1);
+             }
+           else
+             {
+               /* FROM_CODESET is UTF-8.  */
+               res1 = utf8conv_carefully (slowly,
+                                          &in1ptr, &in1size,
+                                          &out1ptr, &out1size,
+                                          &incremented1);
+             }
+         }
+       else if (do_final_flush1)
+         {
+           /* Now get the conversion state of CD1 back to the initial state.
+              But avoid glibc-2.1 bug and Solaris 2.7 bug.  */
+# if defined _LIBICONV_VERSION \
+     || !((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) || defined __sun)
+           if (cd1 != (iconv_t)(-1))
+             res1 = iconv (cd1, NULL, NULL, &out1ptr, &out1size);
+           else
+# endif
+             res1 = 0;
+           do_final_flush1 = false;
+           incremented1 = true;
+         }
+       else
+         {
+           res1 = 0;
+           incremented1 = true;
+         }
+       if (res1 == (size_t)(-1)
+           && !(errno == E2BIG || errno == EINVAL || errno == EILSEQ))
+         {
+           if (result != initial_result)
+             {
+               int saved_errno = errno;
+               free (result);
+               errno = saved_errno;
+             }
+           return -1;
+         }
+       if (res1 == (size_t)(-1)
+           && errno == EILSEQ && handler != iconveh_error)
+         {
+           /* The input is invalid in FROM_CODESET.  Eat up one byte and
+              emit a question mark.  Room for the question mark was allocated
+              at the end of utf8buf.  */
+           if (!incremented1)
+             {
+               if (in1size == 0)
+                 abort ();
+               in1ptr++;
+               in1size--;
+             }
+           utf8buf[utf8len++] = '?';
+         }
+       errno1 = errno;
+       utf8len = out1ptr - utf8buf;
+
+       if (offsets != NULL
+           || in1size == 0
+           || utf8len > utf8bufsize / 2
+           || (res1 == (size_t)(-1) && errno1 == E2BIG))
+         {
+           /* Conversion step 2: from UTF-8 to TO_CODESET.  */
+           const char *in2ptr = utf8buf;
+           size_t in2size = utf8len;
+
+           while (in2size > 0
+                  || (in1size == 0 && !do_final_flush1 && do_final_flush2))
+             {
+               char *out2ptr = result + length;
+               size_t out2size = allocated - extra_alloc - length;
+               bool incremented2;
+               size_t res2;
+               bool grow;
+
+               if (in2size > 0)
+                 {
+                   if (cd2 != (iconv_t)(-1))
+                     res2 = iconv_carefully (cd2,
+                                             &in2ptr, &in2size,
+                                             &out2ptr, &out2size,
+                                             &incremented2);
+                   else
+                     /* TO_CODESET is UTF-8.  */
+                     res2 = utf8conv_carefully (false,
+                                                &in2ptr, &in2size,
+                                                &out2ptr, &out2size,
+                                                &incremented2);
+                 }
+               else /* in1size == 0 && !do_final_flush1
+                       && in2size == 0 && do_final_flush2 */
+                 {
+                   /* Now get the conversion state of CD1 back to the initial
+                      state.  But avoid glibc-2.1 bug and Solaris 2.7 bug.  */
+# if defined _LIBICONV_VERSION \
+     || !((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) || defined __sun)
+                   if (cd2 != (iconv_t)(-1))
+                     res2 = iconv (cd2, NULL, NULL, &out2ptr, &out2size);
+                   else
+# endif
+                     res2 = 0;
+                   do_final_flush2 = false;
+                   incremented2 = true;
+                 }
+
+               length = out2ptr - result;
+               grow = (length + extra_alloc > allocated / 2);
+               if (res2 == (size_t)(-1))
+                 {
+                   if (errno == E2BIG)
+                     grow = true;
+                   else if (errno == EINVAL)
+                     break;
+                   else if (errno == EILSEQ && handler != iconveh_error)
+                     {
+                       /* Error handling can produce up to 10 bytes of ASCII
+                          output.  But TO_CODESET may be UCS-2, UTF-16 or
+                          UCS-4, so use CD2 here as well.  */
+                       char scratchbuf[10];
+                       size_t scratchlen;
+                       ucs4_t uc;
+                       const char *inptr;
+                       size_t insize;
+                       size_t res;
+
+                       if (incremented2)
+                         {
+                           if (u8_prev (&uc, (const uint8_t *) in2ptr,
+                                        (const uint8_t *) utf8buf)
+                               == NULL)
+                             abort ();
+                         }
+                       else
+                         {
+                           int n;
+                           if (in2size == 0)
+                             abort ();
+                           n = u8_mbtouc_unsafe (&uc, (const uint8_t *) in2ptr,
+                                                 in2size);
+                           in2ptr += n;
+                           in2size -= n;
+                         }
+
+                       if (handler == iconveh_escape_sequence)
+                         {
+                           static char hex[16] = "0123456789ABCDEF";
+                           scratchlen = 0;
+                           scratchbuf[scratchlen++] = '\\';
+                           if (uc < 0x10000)
+                             scratchbuf[scratchlen++] = 'u';
+                           else
+                             {
+                               scratchbuf[scratchlen++] = 'U';
+                               scratchbuf[scratchlen++] = hex[(uc>>28) & 15];
+                               scratchbuf[scratchlen++] = hex[(uc>>24) & 15];
+                               scratchbuf[scratchlen++] = hex[(uc>>20) & 15];
+                               scratchbuf[scratchlen++] = hex[(uc>>16) & 15];
+                             }
+                           scratchbuf[scratchlen++] = hex[(uc>>12) & 15];
+                           scratchbuf[scratchlen++] = hex[(uc>>8) & 15];
+                           scratchbuf[scratchlen++] = hex[(uc>>4) & 15];
+                           scratchbuf[scratchlen++] = hex[uc & 15];
+                         }
+                       else
+                         {
+                           scratchbuf[0] = '?';
+                           scratchlen = 1;
+                         }
+
+                       inptr = scratchbuf;
+                       insize = scratchlen;
+                       if (cd2 != (iconv_t)(-1))
+                         res = iconv (cd2,
+                                      (ICONV_CONST char **) &inptr, &insize,
+                                      &out2ptr, &out2size);
+                       else
+                         {
+                           /* TO_CODESET is UTF-8.  */
+                           if (out2size >= insize)
+                             {
+                               memcpy (out2ptr, inptr, insize);
+                               out2ptr += insize;
+                               out2size -= insize;
+                               inptr += insize;
+                               insize = 0;
+                               res = 0;
+                             }
+                           else
+                             {
+                               errno = E2BIG;
+                               res = (size_t)(-1);
+                             }
+                         }
+                       length = out2ptr - result;
+                       if (res == (size_t)(-1) && errno == E2BIG)
+                         {
+                           char *memory;
+
+                           allocated = 2 * allocated;
+                           if (length + 1 + extra_alloc > allocated)
+                             abort ();
+                           if (result == initial_result)
+                             memory = (char *) malloc (allocated);
+                           else
+                             memory = (char *) realloc (result, allocated);
+                           if (memory == NULL)
+                             {
+                               if (result != initial_result)
+                                 free (result);
+                               errno = ENOMEM;
+                               return -1;
+                             }
+                           if (result == initial_result)
+                             memcpy (memory, initial_result, length);
+                           result = memory;
+                           grow = false;
+
+                           out2ptr = result + length;
+                           out2size = allocated - extra_alloc - length;
+                           if (cd2 != (iconv_t)(-1))
+                             res = iconv (cd2,
+                                          (ICONV_CONST char **) &inptr,
+                                          &insize,
+                                          &out2ptr, &out2size);
+                           else
+                             {
+                               /* TO_CODESET is UTF-8.  */
+                               if (!(out2size >= insize))
+                                 abort ();
+                               memcpy (out2ptr, inptr, insize);
+                               out2ptr += insize;
+                               out2size -= insize;
+                               inptr += insize;
+                               insize = 0;
+                               res = 0;
+                             }
+                           length = out2ptr - result;
+                         }
+# if !defined _LIBICONV_VERSION && !defined __GLIBC__
+                       /* Irix iconv() inserts a NUL byte if it cannot convert.
+                          NetBSD iconv() inserts a question mark if it cannot
+                          convert.
+                          Only GNU libiconv and GNU libc are known to prefer
+                          to fail rather than doing a lossy conversion.  */
+                       if (res != (size_t)(-1) && res > 0)
+                         {
+                           errno = EILSEQ;
+                           res = (size_t)(-1);
+                         }
+# endif
+                       if (res == (size_t)(-1))
+                         {
+                           /* Failure converting the ASCII replacement.  */
+                           if (result != initial_result)
+                             {
+                               int saved_errno = errno;
+                               free (result);
+                               errno = saved_errno;
+                             }
+                           return -1;
+                         }
+                     }
+                   else
+                     {
+                       if (result != initial_result)
+                         {
+                           int saved_errno = errno;
+                           free (result);
+                           errno = saved_errno;
+                         }
+                       return -1;
+                     }
+                 }
+               if (!(in2size > 0
+                     || (in1size == 0 && !do_final_flush1 && do_final_flush2)))
+                 break;
+               if (grow)
+                 {
+                   char *memory;
+
+                   allocated = 2 * allocated;
+                   if (result == initial_result)
+                     memory = (char *) malloc (allocated);
+                   else
+                     memory = (char *) realloc (result, allocated);
+                   if (memory == NULL)
+                     {
+                       if (result != initial_result)
+                         free (result);
+                       errno = ENOMEM;
+                       return -1;
+                     }
+                   if (result == initial_result)
+                     memcpy (memory, initial_result, length);
+                   result = memory;
+                 }
+             }
+
+           /* Move the remaining bytes to the beginning of utf8buf.  */
+           if (in2size > 0)
+             memmove (utf8buf, in2ptr, in2size);
+           utf8len = in2size;
+         }
+
+       if (res1 == (size_t)(-1))
+         {
+           if (errno1 == EINVAL)
+             in1size = 0;
+           else if (errno1 == EILSEQ)
+             {
+               if (result != initial_result)
+                 free (result);
+               errno = errno1;
+               return -1;
+             }
+         }
+      }
+# undef utf8bufsize
+  }
+
+ done:
+  /* Now the final memory allocation.  */
+  if (result == tmpbuf)
+    {
+      size_t memsize = length + extra_alloc;
+      char *memory;
+
+      memory = (char *) malloc (memsize > 0 ? memsize : 1);
+      if (memory != NULL)
+       {
+         memcpy (memory, tmpbuf, length);
+         result = memory;
+       }
+      else
+       {
+         errno = ENOMEM;
+         return -1;
+        }
+    }
+  else if (result != *resultp && length + extra_alloc < allocated)
+    {
+      /* Shrink the allocated memory if possible.  */
+      size_t memsize = length + extra_alloc;
+      char *memory;
+
+      memory = (char *) realloc (result, memsize > 0 ? memsize : 1);
+      if (memory != NULL)
+       result = memory;
+    }
+  *resultp = result;
+  *lengthp = length;
+  return 0;
+# undef tmpbuf
+# undef tmpbufsize
+}
+
+int
+mem_cd_iconveh (const char *src, size_t srclen,
+               iconv_t cd, iconv_t cd1, iconv_t cd2,
+               enum iconv_ilseq_handler handler,
+               size_t *offsets,
+               char **resultp, size_t *lengthp)
+{
+  return mem_cd_iconveh_internal (src, srclen, cd, cd1, cd2, handler, 0,
+                                 offsets, resultp, lengthp);
+}
+
+char *
+str_cd_iconveh (const char *src,
+               iconv_t cd, iconv_t cd1, iconv_t cd2,
+               enum iconv_ilseq_handler handler)
+{
+  /* For most encodings, a trailing NUL byte in the input will be converted
+     to a trailing NUL byte in the output.  But not for UTF-7.  So that this
+     function is usable for UTF-7, we have to exclude the NUL byte from the
+     conversion and add it by hand afterwards.  */
+  char *result = NULL;
+  size_t length = 0;
+  int retval = mem_cd_iconveh_internal (src, strlen (src),
+                                       cd, cd1, cd2, handler, 1, NULL,
+                                       &result, &length);
+
+  if (retval < 0)
+    {
+      if (result != NULL)
+       {
+         int saved_errno = errno;
+         free (result);
+         errno = saved_errno;
+       }
+      return NULL;
+    }
+
+  /* Add the terminating NUL byte.  */
+  result[length] = '\0';
+
+  return result;
+}
+
+#endif
+
+int
+mem_iconveh (const char *src, size_t srclen,
+            const char *from_codeset, const char *to_codeset,
+            enum iconv_ilseq_handler handler,
+            size_t *offsets,
+            char **resultp, size_t *lengthp)
+{
+  if (srclen == 0)
+    {
+      /* Nothing to convert.  */
+      *lengthp = 0;
+      return 0;
+    }
+  else if (offsets == NULL && c_strcasecmp (from_codeset, to_codeset) == 0)
+    {
+      char *result;
+
+      if (*resultp != NULL && *lengthp >= srclen)
+       result = *resultp;
+      else
+       {
+         result = (char *) malloc (srclen);
+         if (result == NULL)
+           {
+             errno = ENOMEM;
+             return -1;
+           }
+       }
+      memcpy (result, src, srclen);
+      *resultp = result;
+      *lengthp = srclen;
+      return 0;
+    }
+  else
+    {
+#if HAVE_ICONV
+      iconv_t cd;
+      iconv_t cd1;
+      iconv_t cd2;
+      char *result;
+      size_t length;
+      int retval;
+
+      /* Avoid glibc-2.1 bug with EUC-KR.  */
+# if (__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) && !defined 
_LIBICONV_VERSION
+      if (c_strcasecmp (from_codeset, "EUC-KR") == 0
+         || c_strcasecmp (to_codeset, "EUC-KR") == 0)
+       {
+         errno = EINVAL;
+         return -1;
+       }
+# endif
+
+      cd = iconv_open (to_codeset, from_codeset);
+
+      if (STRCASEEQ (from_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0))
+       cd1 = (iconv_t)(-1);
+      else
+       {
+         cd1 = iconv_open ("UTF-8", from_codeset);
+         if (cd1 == (iconv_t)(-1))
+           {
+             int saved_errno = errno;
+             if (cd != (iconv_t)(-1))
+               iconv_close (cd);
+             errno = saved_errno;
+             return -1;
+           }
+       }
+
+      if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)
+# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 || 
_LIBICONV_VERSION >= 0x0105
+         || c_strcasecmp (to_codeset, "UTF-8//TRANSLIT") == 0
+# endif
+        )
+       cd2 = (iconv_t)(-1);
+      else
+       {
+         cd2 = iconv_open (to_codeset, "UTF-8");
+         if (cd2 == (iconv_t)(-1))
+           {
+             int saved_errno = errno;
+             if (cd1 != (iconv_t)(-1))
+               iconv_close (cd1);
+             if (cd != (iconv_t)(-1))
+               iconv_close (cd);
+             errno = saved_errno;
+             return -1;
+           }
+       }
+
+      result = *resultp;
+      length = *lengthp;
+      retval = mem_cd_iconveh (src, srclen, cd, cd1, cd2, handler, offsets,
+                              &result, &length);
+
+      if (retval < 0)
+       {
+         /* Close cd, cd1, cd2, but preserve the errno from str_cd_iconv.  */
+         int saved_errno = errno;
+         if (cd2 != (iconv_t)(-1))
+           iconv_close (cd2);
+         if (cd1 != (iconv_t)(-1))
+           iconv_close (cd1);
+         if (cd != (iconv_t)(-1))
+           iconv_close (cd);
+         errno = saved_errno;
+       }
+      else
+       {
+         if (cd2 != (iconv_t)(-1) && iconv_close (cd2) < 0)
+           {
+             /* Return -1, but free the allocated memory, and while doing
+                that, preserve the errno from iconv_close.  */
+             int saved_errno = errno;
+             if (cd1 != (iconv_t)(-1))
+               iconv_close (cd1);
+             if (cd != (iconv_t)(-1))
+               iconv_close (cd);
+             if (result != *resultp && result != NULL)
+               free (result);
+             errno = saved_errno;
+             return -1;
+           }
+         if (cd1 != (iconv_t)(-1) && iconv_close (cd1) < 0)
+           {
+             /* Return -1, but free the allocated memory, and while doing
+                that, preserve the errno from iconv_close.  */
+             int saved_errno = errno;
+             if (cd != (iconv_t)(-1))
+               iconv_close (cd);
+             if (result != *resultp && result != NULL)
+               free (result);
+             errno = saved_errno;
+             return -1;
+           }
+         if (cd != (iconv_t)(-1) && iconv_close (cd) < 0)
+           {
+             /* Return -1, but free the allocated memory, and while doing
+                that, preserve the errno from iconv_close.  */
+             int saved_errno = errno;
+             if (result != *resultp && result != NULL)
+               free (result);
+             errno = saved_errno;
+             return -1;
+           }
+         *resultp = result;
+         *lengthp = length;
+       }
+      return retval;
+#else
+      /* This is a different error code than if iconv_open existed but didn't
+        support from_codeset and to_codeset, so that the caller can emit
+        an error message such as
+          "iconv() is not supported. Installing GNU libiconv and
+           then reinstalling this package would fix this."  */
+      errno = ENOSYS;
+      return -1;
+#endif
+    }
+}
+
+char *
+str_iconveh (const char *src,
+            const char *from_codeset, const char *to_codeset,
+            enum iconv_ilseq_handler handler)
+{
+  if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0)
+    {
+      char *result = strdup (src);
+
+      if (result == NULL)
+       errno = ENOMEM;
+      return result;
+    }
+  else
+    {
+#if HAVE_ICONV
+      iconv_t cd;
+      iconv_t cd1;
+      iconv_t cd2;
+      char *result;
+
+      /* Avoid glibc-2.1 bug with EUC-KR.  */
+# if (__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) && !defined 
_LIBICONV_VERSION
+      if (c_strcasecmp (from_codeset, "EUC-KR") == 0
+         || c_strcasecmp (to_codeset, "EUC-KR") == 0)
+       {
+         errno = EINVAL;
+         return NULL;
+       }
+# endif
+
+      cd = iconv_open (to_codeset, from_codeset);
+
+      if (STRCASEEQ (from_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0))
+       cd1 = (iconv_t)(-1);
+      else
+       {
+         cd1 = iconv_open ("UTF-8", from_codeset);
+         if (cd1 == (iconv_t)(-1))
+           {
+             int saved_errno = errno;
+             if (cd != (iconv_t)(-1))
+               iconv_close (cd);
+             errno = saved_errno;
+             return NULL;
+           }
+       }
+
+      if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)
+# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 || 
_LIBICONV_VERSION >= 0x0105
+         || c_strcasecmp (to_codeset, "UTF-8//TRANSLIT") == 0
+# endif
+        )
+       cd2 = (iconv_t)(-1);
+      else
+       {
+         cd2 = iconv_open (to_codeset, "UTF-8");
+         if (cd2 == (iconv_t)(-1))
+           {
+             int saved_errno = errno;
+             if (cd1 != (iconv_t)(-1))
+               iconv_close (cd1);
+             if (cd != (iconv_t)(-1))
+               iconv_close (cd);
+             errno = saved_errno;
+             return NULL;
+           }
+       }
+
+      result = str_cd_iconveh (src, cd, cd1, cd2, handler);
+
+      if (result == NULL)
+       {
+         /* Close cd, cd1, cd2, but preserve the errno from str_cd_iconv.  */
+         int saved_errno = errno;
+         if (cd2 != (iconv_t)(-1))
+           iconv_close (cd2);
+         if (cd1 != (iconv_t)(-1))
+           iconv_close (cd1);
+         if (cd != (iconv_t)(-1))
+           iconv_close (cd);
+         errno = saved_errno;
+       }
+      else
+       {
+         if (cd2 != (iconv_t)(-1) && iconv_close (cd2) < 0)
+           {
+             /* Return NULL, but free the allocated memory, and while doing
+                that, preserve the errno from iconv_close.  */
+             int saved_errno = errno;
+             if (cd1 != (iconv_t)(-1))
+               iconv_close (cd1);
+             if (cd != (iconv_t)(-1))
+               iconv_close (cd);
+             free (result);
+             errno = saved_errno;
+             return NULL;
+           }
+         if (cd1 != (iconv_t)(-1) && iconv_close (cd1) < 0)
+           {
+             /* Return NULL, but free the allocated memory, and while doing
+                that, preserve the errno from iconv_close.  */
+             int saved_errno = errno;
+             if (cd != (iconv_t)(-1))
+               iconv_close (cd);
+             free (result);
+             errno = saved_errno;
+             return NULL;
+           }
+         if (cd != (iconv_t)(-1) && iconv_close (cd) < 0)
+           {
+             /* Return NULL, but free the allocated memory, and while doing
+                that, preserve the errno from iconv_close.  */
+             int saved_errno = errno;
+             free (result);
+             errno = saved_errno;
+             return NULL;
+           }
+       }
+      return result;
+#else
+      /* This is a different error code than if iconv_open existed but didn't
+        support from_codeset and to_codeset, so that the caller can emit
+        an error message such as
+          "iconv() is not supported. Installing GNU libiconv and
+           then reinstalling this package would fix this."  */
+      errno = ENOSYS;
+      return NULL;
+#endif
+    }
+}
diff --git a/lib/striconveh.h b/lib/striconveh.h
new file mode 100644
index 0000000..98b4d0c
--- /dev/null
+++ b/lib/striconveh.h
@@ -0,0 +1,120 @@
+/* Character set conversion with error handling.
+   Copyright (C) 2001-2007, 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible and Simon Josefsson.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _STRICONVEH_H
+#define _STRICONVEH_H
+
+#include <stddef.h>
+#if HAVE_ICONV
+#include <iconv.h>
+#endif
+
+#include "iconveh.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if HAVE_ICONV
+
+/* Convert an entire string from one encoding to another, using iconv.
+   The original string is at [SRC,...,SRC+SRCLEN-1].
+   CD is the conversion descriptor from FROMCODE to TOCODE, or (iconv_t)(-1) if
+   the system does not support a direct conversion from FROMCODE to TOCODE.
+   CD1 is the conversion descriptor from FROM_CODESET to UTF-8 (or
+   (iconv_t)(-1) if FROM_CODESET is UTF-8).
+   CD2 is the conversion descriptor from UTF-8 to TO_CODESET (or (iconv_t)(-1)
+   if TO_CODESET is UTF-8).
+   If OFFSETS is not NULL, it should point to an array of SRCLEN integers; this
+   array is filled with offsets into the result, i.e. the character starting
+   at SRC[i] corresponds to the character starting at (*RESULTP)[OFFSETS[i]],
+   and other offsets are set to (size_t)(-1).
+   *RESULTP and *LENGTH should initially be a scratch buffer and its size,
+   or *RESULTP can initially be NULL.
+   May erase the contents of the memory at *RESULTP.
+   Return value: 0 if successful, otherwise -1 and errno set.
+   If successful: The resulting string is stored in *RESULTP and its length
+   in *LENGTHP.  *RESULTP is set to a freshly allocated memory block, or is
+   unchanged if no dynamic memory allocation was necessary.  */
+extern int
+       mem_cd_iconveh (const char *src, size_t srclen,
+                      iconv_t cd, iconv_t cd1, iconv_t cd2,
+                      enum iconv_ilseq_handler handler,
+                      size_t *offsets,
+                      char **resultp, size_t *lengthp);
+
+/* Convert an entire string from one encoding to another, using iconv.
+   The original string is the NUL-terminated string starting at SRC.
+   CD is the conversion descriptor from FROMCODE to TOCODE, or (iconv_t)(-1) if
+   the system does not support a direct conversion from FROMCODE to TOCODE.
+   Both the "from" and the "to" encoding must use a single NUL byte at the end
+   of the string (i.e. not UCS-2, UCS-4, UTF-16, UTF-32).
+   CD1 is the conversion descriptor from FROM_CODESET to UTF-8 (or
+   (iconv_t)(-1) if FROM_CODESET is UTF-8).
+   CD2 is the conversion descriptor from UTF-8 to TO_CODESET (or (iconv_t)(-1)
+   if TO_CODESET is UTF-8).
+   Allocate a malloced memory block for the result.
+   Return value: the freshly allocated resulting NUL-terminated string if
+   successful, otherwise NULL and errno set.  */
+extern char *
+       str_cd_iconveh (const char *src,
+                      iconv_t cd, iconv_t cd1, iconv_t cd2,
+                      enum iconv_ilseq_handler handler);
+
+#endif
+
+/* Convert an entire string from one encoding to another, using iconv.
+   The original string is at [SRC,...,SRC+SRCLEN-1].
+   If OFFSETS is not NULL, it should point to an array of SRCLEN integers; this
+   array is filled with offsets into the result, i.e. the character starting
+   at SRC[i] corresponds to the character starting at (*RESULTP)[OFFSETS[i]],
+   and other offsets are set to (size_t)(-1).
+   *RESULTP and *LENGTH should initially be a scratch buffer and its size,
+   or *RESULTP can initially be NULL.
+   May erase the contents of the memory at *RESULTP.
+   Return value: 0 if successful, otherwise -1 and errno set.
+   If successful: The resulting string is stored in *RESULTP and its length
+   in *LENGTHP.  *RESULTP is set to a freshly allocated memory block, or is
+   unchanged if no dynamic memory allocation was necessary.  */
+extern int
+       mem_iconveh (const char *src, size_t srclen,
+                   const char *from_codeset, const char *to_codeset,
+                   enum iconv_ilseq_handler handler,
+                   size_t *offsets,
+                   char **resultp, size_t *lengthp);
+
+/* Convert an entire string from one encoding to another, using iconv.
+   The original string is the NUL-terminated string starting at SRC.
+   Both the "from" and the "to" encoding must use a single NUL byte at the
+   end of the string (i.e. not UCS-2, UCS-4, UTF-16, UTF-32).
+   Allocate a malloced memory block for the result.
+   Return value: the freshly allocated resulting NUL-terminated string if
+   successful, otherwise NULL and errno set.  */
+extern char *
+       str_iconveh (const char *src,
+                   const char *from_codeset, const char *to_codeset,
+                   enum iconv_ilseq_handler handler);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _STRICONVEH_H */
diff --git a/lib/strings.h b/lib/strings.h
new file mode 100644
index 0000000..c5f2269
--- /dev/null
+++ b/lib/strings.h
@@ -0,0 +1,119 @@
+/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
+/* A substitute <strings.h>.
+
+   Copyright (C) 2007-2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GL_STRINGS_H
+
+#if __GNUC__ >= 3
+#pragma GCC system_header
+#endif
+
+/* The include_next requires a split double-inclusion guard.  */
+#include_next <strings.h>
+
+#ifndef _GL_STRINGS_H
+#define _GL_STRINGS_H
+
+
+/* The definition of GL_LINK_WARNING is copied here.  */
+/* GL_LINK_WARNING("literal string") arranges to emit the literal string as
+   a linker warning on most glibc systems.
+   We use a linker warning rather than a preprocessor warning, because
+   #warning cannot be used inside macros.  */
+#ifndef GL_LINK_WARNING
+  /* This works on platforms with GNU ld and ELF object format.
+     Testing __GLIBC__ is sufficient for asserting that GNU ld is in use.
+     Testing __ELF__ guarantees the ELF object format.
+     Testing __GNUC__ is necessary for the compound expression syntax.  */
+# if defined __GLIBC__ && defined __ELF__ && defined __GNUC__
+#  define GL_LINK_WARNING(message) \
+     GL_LINK_WARNING1 (__FILE__, __LINE__, message)
+#  define GL_LINK_WARNING1(file, line, message) \
+     GL_LINK_WARNING2 (file, line, message)  /* macroexpand file and line */
+#  define GL_LINK_WARNING2(file, line, message) \
+     GL_LINK_WARNING3 (file ":" #line ": warning: " message)
+#  define GL_LINK_WARNING3(message) \
+     ({ static const char warning[sizeof (message)]            \
+          __attribute__ ((__unused__,                          \
+                          __section__ (".gnu.warning"),                \
+                          __aligned__ (1)))                    \
+          = message "\n";                                      \
+        (void)0;                                               \
+     })
+# else
+#  define GL_LINK_WARNING(message) ((void) 0)
+# endif
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
+   greater than zero if S1 is lexicographically less than, equal to or greater
+   than S2.
+   Note: This function does not work in multibyte locales.  */
+#if ! 1
+extern int strcasecmp (char const *s1, char const *s2);
+#endif
+#if defined GNULIB_POSIXCHECK
+/* strcasecmp() does not work with multibyte strings:
+   POSIX says that it operates on "strings", and "string" in POSIX is defined
+   as a sequence of bytes, not of characters.   */
+# undef strcasecmp
+# define strcasecmp(a,b) \
+    (GL_LINK_WARNING ("strcasecmp cannot work correctly on character strings " 
\
+                      "in multibyte locales - " \
+                      "use mbscasecmp if you care about " \
+                      "internationalization, or use c_strcasecmp (from " \
+                      "gnulib module c-strcase) if you want a locale " \
+                      "independent function"), \
+     strcasecmp (a, b))
+#endif
+
+/* Compare no more than N bytes of strings S1 and S2, ignoring case,
+   returning less than, equal to or greater than zero if S1 is
+   lexicographically less than, equal to or greater than S2.
+   Note: This function cannot work correctly in multibyte locales.  */
+#if ! 1
+extern int strncasecmp (char const *s1, char const *s2, size_t n);
+#endif
+#if defined GNULIB_POSIXCHECK
+/* strncasecmp() does not work with multibyte strings:
+   POSIX says that it operates on "strings", and "string" in POSIX is defined
+   as a sequence of bytes, not of characters.  */
+# undef strncasecmp
+# define strncasecmp(a,b,n) \
+    (GL_LINK_WARNING ("strncasecmp cannot work correctly on character " \
+                      "strings in multibyte locales - " \
+                      "use mbsncasecmp or mbspcasecmp if you care about " \
+                      "internationalization, or use c_strncasecmp (from " \
+                      "gnulib module c-strcase) if you want a locale " \
+                      "independent function"), \
+     strncasecmp (a, b, n))
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GL_STRING_H */
+#endif /* _GL_STRING_H */
diff --git a/lib/time.h b/lib/time.h
new file mode 100644
index 0000000..1dcd80d
--- /dev/null
+++ b/lib/time.h
@@ -0,0 +1,119 @@
+/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
+/* A more-standard <time.h>.
+
+   Copyright (C) 2007-2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#if __GNUC__ >= 3
+#pragma GCC system_header
+#endif
+
+/* Don't get in the way of glibc when it includes time.h merely to
+   declare a few standard symbols, rather than to declare all the
+   symbols.  Also, Solaris 8 <time.h> eventually includes itself
+   recursively; if that is happening, just include the system <time.h>
+   without adding our own declarations.  */
+#if (defined __need_time_t || defined __need_clock_t \
+     || defined __need_timespec \
+     || defined _GL_TIME_H)
+
+# include_next <time.h>
+
+#else
+
+# define _GL_TIME_H
+
+# include_next <time.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3).
+   Or they define it with the wrong member names or define it in <sys/time.h>
+   (e.g., FreeBSD circa 1997).  */
+# if ! 1
+#  if 0
+#   include <sys/time.h>
+#  else
+#   undef timespec
+#   define timespec rpl_timespec
+struct timespec
+{
+  time_t tv_sec;
+  long int tv_nsec;
+};
+#  endif
+# endif
+
+/* Sleep for at least RQTP seconds unless interrupted,  If interrupted,
+   return -1 and store the remaining time into RMTP.  See
+   <http://www.opengroup.org/susv3xsh/nanosleep.html>.  */
+# if GNULIB_PORTCHECK
+#  define nanosleep rpl_nanosleep
+int nanosleep (struct timespec const *__rqtp, struct timespec *__rmtp);
+# endif
+
+/* Convert TIMER to RESULT, assuming local time and UTC respectively.  See
+   <http://www.opengroup.org/susv3xsh/localtime_r.html> and
+   <http://www.opengroup.org/susv3xsh/gmtime_r.html>.  */
+# if 0
+#  undef localtime_r
+#  define localtime_r rpl_localtime_r
+#  undef gmtime_r
+#  define gmtime_r rpl_gmtime_r
+struct tm *localtime_r (time_t const *restrict __timer,
+                       struct tm *restrict __result);
+struct tm *gmtime_r (time_t const *restrict __timer,
+                    struct tm *restrict __result);
+# endif
+
+/* Parse BUF as a time stamp, assuming FORMAT specifies its layout, and store
+   the resulting broken-down time into TM.  See
+   <http://www.opengroup.org/susv3xsh/strptime.html>.  */
+# if GNULIB_PORTCHECK
+#  undef strptime
+#  define strptime rpl_strptime
+char *strptime (char const *restrict __buf, char const *restrict __format,
+               struct tm *restrict __tm);
+# endif
+
+/* Convert TM to a time_t value, assuming UTC.  */
+# if GNULIB_PORTCHECK
+#  undef timegm
+#  define timegm rpl_timegm
+time_t timegm (struct tm *__tm);
+# endif
+
+/* Encourage applications to avoid unsafe functions that can overrun
+   buffers when given outlandish struct tm values.  Portable
+   applications should use strftime (or even sprintf) instead.  */
+# if GNULIB_PORTCHECK
+#  undef asctime
+#  define asctime eschew_asctime
+#  undef asctime_r
+#  define asctime_r eschew_asctime_r
+#  undef ctime
+#  define ctime eschew_ctime
+#  undef ctime_r
+#  define ctime_r eschew_ctime_r
+# endif
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/lib/unistd.h b/lib/unistd.h
new file mode 100644
index 0000000..413e29c
--- /dev/null
+++ b/lib/unistd.h
@@ -0,0 +1,607 @@
+/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
+/* Substitute for and wrapper around <unistd.h>.
+   Copyright (C) 2003-2009 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GL_UNISTD_H
+
+#if __GNUC__ >= 3
+#pragma GCC system_header
+#endif
+
+/* The include_next requires a split double-inclusion guard.  */
+#if 1
+# include_next <unistd.h>
+#endif
+
+#ifndef _GL_UNISTD_H
+#define _GL_UNISTD_H
+
+/* mingw doesn't define the SEEK_* or *_FILENO macros in <unistd.h>.  */
+#if !(defined SEEK_CUR && defined SEEK_END && defined SEEK_SET)
+# include <stdio.h>
+#endif
+
+/* mingw fails to declare _exit in <unistd.h>.  */
+/* mingw, BeOS, Haiku declare environ in <stdlib.h>, not in <unistd.h>.  */
+#include <stdlib.h>
+
+#if 1 && 0 && 0
+/* Get ssize_t.  */
+# include <sys/types.h>
+#endif
+
+#if 0
+/* Get all possible declarations of gethostname().  */
+# if 0
+#  include <winsock2.h>
+#  if !defined _GL_SYS_SOCKET_H
+#   undef socket
+#   define socket              socket_used_without_including_sys_socket_h
+#   undef connect
+#   define connect             connect_used_without_including_sys_socket_h
+#   undef accept
+#   define accept              accept_used_without_including_sys_socket_h
+#   undef bind
+#   define bind                        bind_used_without_including_sys_socket_h
+#   undef getpeername
+#   define getpeername         getpeername_used_without_including_sys_socket_h
+#   undef getsockname
+#   define getsockname         getsockname_used_without_including_sys_socket_h
+#   undef getsockopt
+#   define getsockopt          getsockopt_used_without_including_sys_socket_h
+#   undef listen
+#   define listen              listen_used_without_including_sys_socket_h
+#   undef recv
+#   define recv                        recv_used_without_including_sys_socket_h
+#   undef send
+#   define send                        send_used_without_including_sys_socket_h
+#   undef recvfrom
+#   define recvfrom            recvfrom_used_without_including_sys_socket_h
+#   undef sendto
+#   define sendto              sendto_used_without_including_sys_socket_h
+#   undef setsockopt
+#   define setsockopt          setsockopt_used_without_including_sys_socket_h
+#   undef shutdown
+#   define shutdown            shutdown_used_without_including_sys_socket_h
+#  endif
+#  if !defined _GL_SYS_SELECT_H
+#   undef select
+#   define select              select_used_without_including_sys_select_h
+#  endif
+# endif
+#endif
+
+/* The definition of GL_LINK_WARNING is copied here.  */
+/* GL_LINK_WARNING("literal string") arranges to emit the literal string as
+   a linker warning on most glibc systems.
+   We use a linker warning rather than a preprocessor warning, because
+   #warning cannot be used inside macros.  */
+#ifndef GL_LINK_WARNING
+  /* This works on platforms with GNU ld and ELF object format.
+     Testing __GLIBC__ is sufficient for asserting that GNU ld is in use.
+     Testing __ELF__ guarantees the ELF object format.
+     Testing __GNUC__ is necessary for the compound expression syntax.  */
+# if defined __GLIBC__ && defined __ELF__ && defined __GNUC__
+#  define GL_LINK_WARNING(message) \
+     GL_LINK_WARNING1 (__FILE__, __LINE__, message)
+#  define GL_LINK_WARNING1(file, line, message) \
+     GL_LINK_WARNING2 (file, line, message)  /* macroexpand file and line */
+#  define GL_LINK_WARNING2(file, line, message) \
+     GL_LINK_WARNING3 (file ":" #line ": warning: " message)
+#  define GL_LINK_WARNING3(message) \
+     ({ static const char warning[sizeof (message)]            \
+          __attribute__ ((__unused__,                          \
+                          __section__ (".gnu.warning"),                \
+                          __aligned__ (1)))                    \
+          = message "\n";                                      \
+        (void)0;                                               \
+     })
+# else
+#  define GL_LINK_WARNING(message) ((void) 0)
+# endif
+#endif
+
+
+/* OS/2 EMX lacks these macros.  */
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Declare overridden functions.  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#if 0
+# if 0
+#  ifndef REPLACE_CHOWN
+#   define REPLACE_CHOWN 1
+#  endif
+#  if REPLACE_CHOWN
+/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE
+   to GID (if GID is not -1).  Follow symbolic links.
+   Return 0 if successful, otherwise -1 and errno set.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/chown.html>.  */
+#   define chown rpl_chown
+extern int chown (const char *file, uid_t uid, gid_t gid);
+#  endif
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef chown
+# define chown(f,u,g) \
+    (GL_LINK_WARNING ("chown fails to follow symlinks on some systems and " \
+                      "doesn't treat a uid or gid of -1 on some systems - " \
+                      "use gnulib module chown for portability"), \
+     chown (f, u, g))
+#endif
+
+
+#if 0
+# if 0
+/* Automatically included by modules that need a replacement for close.  */
+#  undef close
+#  define close rpl_close
+extern int close (int);
+# endif
+#elif 0
+# undef close
+# define close close_used_without_requesting_gnulib_module_close
+#elif defined GNULIB_POSIXCHECK
+# undef close
+# define close(f) \
+    (GL_LINK_WARNING ("close does not portably work on sockets - " \
+                      "use gnulib module close for portability"), \
+     close (f))
+#endif
+
+
+#if 0
+# if !1
+/* Copy the file descriptor OLDFD into file descriptor NEWFD.  Do nothing if
+   NEWFD = OLDFD, otherwise close NEWFD first if it is open.
+   Return 0 if successful, otherwise -1 and errno set.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/dup2.html>.  */
+extern int dup2 (int oldfd, int newfd);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef dup2
+# define dup2(o,n) \
+    (GL_LINK_WARNING ("dup2 is unportable - " \
+                      "use gnulib module dup2 for portability"), \
+     dup2 (o, n))
+#endif
+
+
+#if 0
+# if !1
+/* Set of environment variables and values.  An array of strings of the form
+   "VARIABLE=VALUE", terminated with a NULL.  */
+#  if defined __APPLE__ && defined __MACH__
+#   include <crt_externs.h>
+#   define environ (*_NSGetEnviron ())
+#  else
+extern char **environ;
+#  endif
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef environ
+# define environ \
+    (GL_LINK_WARNING ("environ is unportable - " \
+                      "use gnulib module environ for portability"), \
+     environ)
+#endif
+
+
+#if 0
+# if !1
+/* Like access(), except that is uses the effective user id and group id of
+   the current process.  */
+extern int euidaccess (const char *filename, int mode);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef euidaccess
+# define euidaccess(f,m) \
+    (GL_LINK_WARNING ("euidaccess is unportable - " \
+                      "use gnulib module euidaccess for portability"), \
+     euidaccess (f, m))
+#endif
+
+
+#if 0
+# if 0
+
+/* Change the process' current working directory to the directory on which
+   the given file descriptor is open.
+   Return 0 if successful, otherwise -1 and errno set.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/fchdir.html>.  */
+extern int fchdir (int /*fd*/);
+
+#  define dup rpl_dup
+extern int dup (int);
+#  define dup2 rpl_dup2
+extern int dup2 (int, int);
+
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fchdir
+# define fchdir(f) \
+    (GL_LINK_WARNING ("fchdir is unportable - " \
+                      "use gnulib module fchdir for portability"), \
+     fchdir (f))
+#endif
+
+
+#if 0
+/* Synchronize changes to a file.
+   Return 0 if successful, otherwise -1 and errno set.
+   See POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/fsync.html>.  */
+# if !1
+extern int fsync (int fd);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef fsync
+# define fsync(fd) \
+    (GL_LINK_WARNING ("fsync is unportable - " \
+                      "use gnulib module fsync for portability"), \
+     fsync (fd))
+#endif
+
+
+#if 0
+# if !1
+/* Change the size of the file to which FD is opened to become equal to LENGTH.
+   Return 0 if successful, otherwise -1 and errno set.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/ftruncate.html>.  */
+extern int ftruncate (int fd, off_t length);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef ftruncate
+# define ftruncate(f,l) \
+    (GL_LINK_WARNING ("ftruncate is unportable - " \
+                      "use gnulib module ftruncate for portability"), \
+     ftruncate (f, l))
+#endif
+
+
+#if 0
+/* Include the headers that might declare getcwd so that they will not
+   cause confusion if included after this file.  */
+# include <stdlib.h>
+# if 0
+/* Get the name of the current working directory, and put it in SIZE bytes
+   of BUF.
+   Return BUF if successful, or NULL if the directory couldn't be determined
+   or SIZE was too small.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/getcwd.html>.
+   Additionally, the gnulib module 'getcwd' guarantees the following GNU
+   extension: If BUF is NULL, an array is allocated with 'malloc'; the array
+   is SIZE bytes long, unless SIZE == 0, in which case it is as big as
+   necessary.  */
+#  define getcwd rpl_getcwd
+extern char * getcwd (char *buf, size_t size);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getcwd
+# define getcwd(b,s) \
+    (GL_LINK_WARNING ("getcwd is unportable - " \
+                      "use gnulib module getcwd for portability"), \
+     getcwd (b, s))
+#endif
+
+
+#if 0
+/* Return the NIS domain name of the machine.
+   WARNING! The NIS domain name is unrelated to the fully qualified host name
+            of the machine.  It is also unrelated to email addresses.
+   WARNING! The NIS domain name is usually the empty string or "(none)" when
+            not using NIS.
+
+   Put up to LEN bytes of the NIS domain name into NAME.
+   Null terminate it if the name is shorter than LEN.
+   If the NIS domain name is longer than LEN, set errno = EINVAL and return -1.
+   Return 0 if successful, otherwise set errno and return -1.  */
+# if !1
+extern int getdomainname(char *name, size_t len);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getdomainname
+# define getdomainname(n,l) \
+    (GL_LINK_WARNING ("getdomainname is unportable - " \
+                      "use gnulib module getdomainname for portability"), \
+     getdomainname (n, l))
+#endif
+
+
+#if 0
+# if !1
+/* Return the maximum number of file descriptors in the current process.  */
+extern int getdtablesize (void);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getdtablesize
+# define getdtablesize() \
+    (GL_LINK_WARNING ("getdtablesize is unportable - " \
+                      "use gnulib module getdtablesize for portability"), \
+     getdtablesize ())
+#endif
+
+
+#if 0
+/* Return the standard host name of the machine.
+   WARNING! The host name may or may not be fully qualified.
+
+   Put up to LEN bytes of the host name into NAME.
+   Null terminate it if the name is shorter than LEN.
+   If the host name is longer than LEN, set errno = EINVAL and return -1.
+   Return 0 if successful, otherwise set errno and return -1.  */
+# if 0
+#  undef gethostname
+#  define gethostname rpl_gethostname
+# endif
+# if 0 || !1
+extern int gethostname(char *name, size_t len);
+# endif
+#elif 0
+# undef gethostname
+# define gethostname 
gethostname_used_without_requesting_gnulib_module_gethostname
+#elif defined GNULIB_POSIXCHECK
+# undef gethostname
+# define gethostname(n,l) \
+    (GL_LINK_WARNING ("gethostname is unportable - " \
+                      "use gnulib module gethostname for portability"), \
+     gethostname (n, l))
+#endif
+
+
+#if 0
+/* Copies the user's login name to NAME.
+   The array pointed to by NAME has room for SIZE bytes.
+
+   Returns 0 if successful.  Upon error, an error number is returned, or -1 in
+   the case that the login name cannot be found but no specific error is
+   provided (this case is hopefully rare but is left open by the POSIX spec).
+
+   See <http://www.opengroup.org/susv3xsh/getlogin.html>.
+ */
+# if !1
+#  include <stddef.h>
+extern int getlogin_r (char *name, size_t size);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getlogin_r
+# define getlogin_r(n,s) \
+    (GL_LINK_WARNING ("getlogin_r is unportable - " \
+                      "use gnulib module getlogin_r for portability"), \
+     getlogin_r (n, s))
+#endif
+
+
+#if 0
+# if 0
+#  define getpagesize rpl_getpagesize
+extern int getpagesize (void);
+# elif !1
+/* This is for POSIX systems.  */
+#  if !defined getpagesize && defined _SC_PAGESIZE
+#   if ! (defined __VMS && __VMS_VER < 70000000)
+#    define getpagesize() sysconf (_SC_PAGESIZE)
+#   endif
+#  endif
+/* This is for older VMS.  */
+#  if !defined getpagesize && defined __VMS
+#   ifdef __ALPHA
+#    define getpagesize() 8192
+#   else
+#    define getpagesize() 512
+#   endif
+#  endif
+/* This is for BeOS.  */
+#  if !defined getpagesize && 0
+#   include <OS.h>
+#   if defined B_PAGE_SIZE
+#    define getpagesize() B_PAGE_SIZE
+#   endif
+#  endif
+/* This is for AmigaOS4.0.  */
+#  if !defined getpagesize && defined __amigaos4__
+#   define getpagesize() 2048
+#  endif
+/* This is for older Unix systems.  */
+#  if !defined getpagesize && 0
+#   include <sys/param.h>
+#   ifdef EXEC_PAGESIZE
+#    define getpagesize() EXEC_PAGESIZE
+#   else
+#    ifdef NBPG
+#     ifndef CLSIZE
+#      define CLSIZE 1
+#     endif
+#     define getpagesize() (NBPG * CLSIZE)
+#    else
+#     ifdef NBPC
+#      define getpagesize() NBPC
+#     endif
+#    endif
+#   endif
+#  endif
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getpagesize
+# define getpagesize() \
+    (GL_LINK_WARNING ("getpagesize is unportable - " \
+                      "use gnulib module getpagesize for portability"), \
+     getpagesize ())
+#endif
+
+
+#if 0
+# if !1
+/* Return the next valid login shell on the system, or NULL when the end of
+   the list has been reached.  */
+extern char *getusershell (void);
+/* Rewind to pointer that is advanced at each getusershell() call.  */
+extern void setusershell (void);
+/* Free the pointer that is advanced at each getusershell() call and
+   associated resources.  */
+extern void endusershell (void);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getusershell
+# define getusershell() \
+    (GL_LINK_WARNING ("getusershell is unportable - " \
+                      "use gnulib module getusershell for portability"), \
+     getusershell ())
+# undef setusershell
+# define setusershell() \
+    (GL_LINK_WARNING ("setusershell is unportable - " \
+                      "use gnulib module getusershell for portability"), \
+     setusershell ())
+# undef endusershell
+# define endusershell() \
+    (GL_LINK_WARNING ("endusershell is unportable - " \
+                      "use gnulib module getusershell for portability"), \
+     endusershell ())
+#endif
+
+
+#if 0
+# if 0
+/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE
+   to GID (if GID is not -1).  Do not follow symbolic links.
+   Return 0 if successful, otherwise -1 and errno set.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/lchown.html>.  */
+#  define lchown rpl_lchown
+extern int lchown (char const *file, uid_t owner, gid_t group);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef lchown
+# define lchown(f,u,g) \
+    (GL_LINK_WARNING ("lchown is unportable to pre-POSIX.1-2001 " \
+                      "systems - use gnulib module lchown for portability"), \
+     lchown (f, u, g))
+#endif
+
+
+#if 0
+/* Create a new hard link for an existing file.
+   Return 0 if successful, otherwise -1 and errno set.
+   See POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/link.html>.  */
+# if !1
+extern int link (const char *path1, const char *path2);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef link
+# define link(path1,path2) \
+    (GL_LINK_WARNING ("link is unportable - " \
+                      "use gnulib module link for portability"), \
+     link (path1, path2))
+#endif
+
+
+#if 0
+# if 0
+/* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END.
+   Return the new offset if successful, otherwise -1 and errno set.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/lseek.html>.  */
+#  define lseek rpl_lseek
+   extern off_t lseek (int fd, off_t offset, int whence);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef lseek
+# define lseek(f,o,w) \
+    (GL_LINK_WARNING ("lseek does not fail with ESPIPE on pipes on some " \
+                      "systems - use gnulib module lseek for portability"), \
+     lseek (f, o, w))
+#endif
+
+
+#if 0
+/* Read the contents of the symbolic link FILE and place the first BUFSIZE
+   bytes of it into BUF.  Return the number of bytes placed into BUF if
+   successful, otherwise -1 and errno set.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/readlink.html>.  */
+# if !1
+#  include <stddef.h>
+extern int readlink (const char *file, char *buf, size_t bufsize);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef readlink
+# define readlink(f,b,s) \
+    (GL_LINK_WARNING ("readlink is unportable - " \
+                      "use gnulib module readlink for portability"), \
+     readlink (f, b, s))
+#endif
+
+
+#if 0
+/* Pause the execution of the current thread for N seconds.
+   Returns the number of seconds left to sleep.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/sleep.html>.  */
+# if !1
+extern unsigned int sleep (unsigned int n);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef sleep
+# define sleep(n) \
+    (GL_LINK_WARNING ("sleep is unportable - " \
+                      "use gnulib module sleep for portability"), \
+     sleep (n))
+#endif
+
+
+#if 1 && 0 && 0
+/* Write up to COUNT bytes starting at BUF to file descriptor FD.
+   See the POSIX:2001 specification
+   <http://www.opengroup.org/susv3xsh/write.html>.  */
+# undef write
+# define write rpl_write
+extern ssize_t write (int fd, const void *buf, size_t count);
+#endif
+
+
+#ifdef FCHDIR_REPLACEMENT
+/* gnulib internal function.  */
+extern void _gl_unregister_fd (int fd);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _GL_UNISTD_H */
+#endif /* _GL_UNISTD_H */
diff --git a/lib/unistr.h b/lib/unistr.h
new file mode 100644
index 0000000..83ff134
--- /dev/null
+++ b/lib/unistr.h
@@ -0,0 +1,681 @@
+/* Elementary Unicode string functions.
+   Copyright (C) 2001-2002, 2005-2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _UNISTR_H
+#define _UNISTR_H
+
+#include "unitypes.h"
+
+/* Get bool.  */
+#include <stdbool.h>
+
+/* Get size_t.  */
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Conventions:
+
+   All functions prefixed with u8_ operate on UTF-8 encoded strings.
+   Their unit is an uint8_t (1 byte).
+
+   All functions prefixed with u16_ operate on UTF-16 encoded strings.
+   Their unit is an uint16_t (a 2-byte word).
+
+   All functions prefixed with u32_ operate on UCS-4 encoded strings.
+   Their unit is an uint32_t (a 4-byte word).
+
+   All argument pairs (s, n) denote a Unicode string s[0..n-1] with exactly
+   n units.
+
+   All arguments starting with "str" and the arguments of functions starting
+   with u8_str/u16_str/u32_str denote a NUL terminated string, i.e. a string
+   which terminates at the first NUL unit.  This termination unit is
+   considered part of the string for all memory allocation purposes, but
+   is not considered part of the string for all other logical purposes.
+
+   Functions returning a string result take a (resultbuf, lengthp) argument
+   pair.  If resultbuf is not NULL and the result fits into *lengthp units,
+   it is put in resultbuf, and resultbuf is returned.  Otherwise, a freshly
+   allocated string is returned.  In both cases, *lengthp is set to the
+   length (number of units) of the returned string.  In case of error,
+   NULL is returned and errno is set.  */
+
+
+/* Elementary string checks.  */
+
+/* Check whether an UTF-8 string is well-formed.
+   Return NULL if valid, or a pointer to the first invalid unit otherwise.  */
+extern const uint8_t *
+       u8_check (const uint8_t *s, size_t n);
+
+/* Check whether an UTF-16 string is well-formed.
+   Return NULL if valid, or a pointer to the first invalid unit otherwise.  */
+extern const uint16_t *
+       u16_check (const uint16_t *s, size_t n);
+
+/* Check whether an UCS-4 string is well-formed.
+   Return NULL if valid, or a pointer to the first invalid unit otherwise.  */
+extern const uint32_t *
+       u32_check (const uint32_t *s, size_t n);
+
+
+/* Elementary string conversions.  */
+
+/* Convert an UTF-8 string to an UTF-16 string.  */
+extern uint16_t *
+       u8_to_u16 (const uint8_t *s, size_t n, uint16_t *resultbuf,
+                 size_t *lengthp);
+
+/* Convert an UTF-8 string to an UCS-4 string.  */
+extern uint32_t *
+       u8_to_u32 (const uint8_t *s, size_t n, uint32_t *resultbuf,
+                 size_t *lengthp);
+
+/* Convert an UTF-16 string to an UTF-8 string.  */
+extern uint8_t *
+       u16_to_u8 (const uint16_t *s, size_t n, uint8_t *resultbuf,
+                 size_t *lengthp);
+
+/* Convert an UTF-16 string to an UCS-4 string.  */
+extern uint32_t *
+       u16_to_u32 (const uint16_t *s, size_t n, uint32_t *resultbuf,
+                  size_t *lengthp);
+
+/* Convert an UCS-4 string to an UTF-8 string.  */
+extern uint8_t *
+       u32_to_u8 (const uint32_t *s, size_t n, uint8_t *resultbuf,
+                 size_t *lengthp);
+
+/* Convert an UCS-4 string to an UTF-16 string.  */
+extern uint16_t *
+       u32_to_u16 (const uint32_t *s, size_t n, uint16_t *resultbuf,
+                  size_t *lengthp);
+
+
+/* Elementary string functions.  */
+
+/* Return the length (number of units) of the first character in S, which is
+   no longer than N.  Return 0 if it is the NUL character.  Return -1 upon
+   failure.  */
+/* Similar to mblen(), except that s must not be NULL.  */
+extern int
+       u8_mblen (const uint8_t *s, size_t n);
+extern int
+       u16_mblen (const uint16_t *s, size_t n);
+extern int
+       u32_mblen (const uint32_t *s, size_t n);
+
+/* Return the length (number of units) of the first character in S, putting
+   its 'ucs4_t' representation in *PUC.  Upon failure, *PUC is set to 0xfffd,
+   and an appropriate number of units is returned.
+   The number of available units, N, must be > 0.  */
+/* Similar to mbtowc(), except that puc and s must not be NULL, n must be > 0,
+   and the NUL character is not treated specially.  */
+/* The variants with _safe suffix are safe, even if the library is compiled
+   without --enable-safety.  */
+
+#ifdef GNULIB_UNISTR_U8_MBTOUC_UNSAFE
+# if !HAVE_INLINE
+extern int
+       u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n);
+# else
+extern int
+       u8_mbtouc_unsafe_aux (ucs4_t *puc, const uint8_t *s, size_t n);
+static inline int
+u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+  uint8_t c = *s;
+
+  if (c < 0x80)
+    {
+      *puc = c;
+      return 1;
+    }
+  else
+    return u8_mbtouc_unsafe_aux (puc, s, n);
+}
+# endif
+#endif
+
+#ifdef GNULIB_UNISTR_U16_MBTOUC_UNSAFE
+# if !HAVE_INLINE
+extern int
+       u16_mbtouc_unsafe (ucs4_t *puc, const uint16_t *s, size_t n);
+# else
+extern int
+       u16_mbtouc_unsafe_aux (ucs4_t *puc, const uint16_t *s, size_t n);
+static inline int
+u16_mbtouc_unsafe (ucs4_t *puc, const uint16_t *s, size_t n)
+{
+  uint16_t c = *s;
+
+  if (c < 0xd800 || c >= 0xe000)
+    {
+      *puc = c;
+      return 1;
+    }
+  else
+    return u16_mbtouc_unsafe_aux (puc, s, n);
+}
+# endif
+#endif
+
+#ifdef GNULIB_UNISTR_U32_MBTOUC_UNSAFE
+# if !HAVE_INLINE
+extern int
+       u32_mbtouc_unsafe (ucs4_t *puc, const uint32_t *s, size_t n);
+# else
+static inline int
+u32_mbtouc_unsafe (ucs4_t *puc, const uint32_t *s, size_t n _UNUSED_PARAMETER_)
+{
+  uint32_t c = *s;
+
+#  if CONFIG_UNICODE_SAFETY
+  if (c < 0xd800 || (c >= 0xe000 && c < 0x110000))
+#  endif
+    *puc = c;
+#  if CONFIG_UNICODE_SAFETY
+  else
+    /* invalid multibyte character */
+    *puc = 0xfffd;
+#  endif
+  return 1;
+}
+# endif
+#endif
+
+#ifdef GNULIB_UNISTR_U8_MBTOUC
+# if !HAVE_INLINE
+extern int
+       u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n);
+# else
+extern int
+       u8_mbtouc_aux (ucs4_t *puc, const uint8_t *s, size_t n);
+static inline int
+u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+  uint8_t c = *s;
+
+  if (c < 0x80)
+    {
+      *puc = c;
+      return 1;
+    }
+  else
+    return u8_mbtouc_aux (puc, s, n);
+}
+# endif
+#endif
+
+#ifdef GNULIB_UNISTR_U16_MBTOUC
+# if !HAVE_INLINE
+extern int
+       u16_mbtouc (ucs4_t *puc, const uint16_t *s, size_t n);
+# else
+extern int
+       u16_mbtouc_aux (ucs4_t *puc, const uint16_t *s, size_t n);
+static inline int
+u16_mbtouc (ucs4_t *puc, const uint16_t *s, size_t n)
+{
+  uint16_t c = *s;
+
+  if (c < 0xd800 || c >= 0xe000)
+    {
+      *puc = c;
+      return 1;
+    }
+  else
+    return u16_mbtouc_aux (puc, s, n);
+}
+# endif
+#endif
+
+#ifdef GNULIB_UNISTR_U32_MBTOUC
+# if !HAVE_INLINE
+extern int
+       u32_mbtouc (ucs4_t *puc, const uint32_t *s, size_t n);
+# else
+static inline int
+u32_mbtouc (ucs4_t *puc, const uint32_t *s, size_t n _UNUSED_PARAMETER_)
+{
+  uint32_t c = *s;
+
+  if (c < 0xd800 || (c >= 0xe000 && c < 0x110000))
+    *puc = c;
+  else
+    /* invalid multibyte character */
+    *puc = 0xfffd;
+  return 1;
+}
+# endif
+#endif
+
+/* Return the length (number of units) of the first character in S, putting
+   its 'ucs4_t' representation in *PUC.  Upon failure, *PUC is set to 0xfffd,
+   and -1 is returned for an invalid sequence of units, -2 is returned for an
+   incomplete sequence of units.
+   The number of available units, N, must be > 0.  */
+/* Similar to u*_mbtouc(), except that the return value gives more details
+   about the failure, similar to mbrtowc().  */
+
+#ifdef GNULIB_UNISTR_U8_MBTOUCR
+extern int
+       u8_mbtoucr (ucs4_t *puc, const uint8_t *s, size_t n);
+#endif
+
+#ifdef GNULIB_UNISTR_U16_MBTOUCR
+extern int
+       u16_mbtoucr (ucs4_t *puc, const uint16_t *s, size_t n);
+#endif
+
+#ifdef GNULIB_UNISTR_U32_MBTOUCR
+extern int
+       u32_mbtoucr (ucs4_t *puc, const uint32_t *s, size_t n);
+#endif
+
+/* Put the multibyte character represented by UC in S, returning its
+   length.  Return -1 upon failure, -2 if the number of available units, N,
+   is too small.  The latter case cannot occur if N >= 6/2/1, respectively.  */
+/* Similar to wctomb(), except that s must not be NULL, and the argument n
+   must be specified.  */
+
+#ifdef GNULIB_UNISTR_U8_UCTOMB
+/* Auxiliary function, also used by u8_chr, u8_strchr, u8_strrchr.  */
+extern int
+       u8_uctomb_aux (uint8_t *s, ucs4_t uc, int n);
+# if !HAVE_INLINE
+extern int
+       u8_uctomb (uint8_t *s, ucs4_t uc, int n);
+# else
+static inline int
+u8_uctomb (uint8_t *s, ucs4_t uc, int n)
+{
+  if (uc < 0x80 && n > 0)
+    {
+      s[0] = uc;
+      return 1;
+    }
+  else
+    return u8_uctomb_aux (s, uc, n);
+}
+# endif
+#endif
+
+#ifdef GNULIB_UNISTR_U16_UCTOMB
+/* Auxiliary function, also used by u16_chr, u16_strchr, u16_strrchr.  */
+extern int
+       u16_uctomb_aux (uint16_t *s, ucs4_t uc, int n);
+# if !HAVE_INLINE
+extern int
+       u16_uctomb (uint16_t *s, ucs4_t uc, int n);
+# else
+static inline int
+u16_uctomb (uint16_t *s, ucs4_t uc, int n)
+{
+  if (uc < 0xd800 && n > 0)
+    {
+      s[0] = uc;
+      return 1;
+    }
+  else
+    return u16_uctomb_aux (s, uc, n);
+}
+# endif
+#endif
+
+#ifdef GNULIB_UNISTR_U32_UCTOMB
+# if !HAVE_INLINE
+extern int
+       u32_uctomb (uint32_t *s, ucs4_t uc, int n);
+# else
+static inline int
+u32_uctomb (uint32_t *s, ucs4_t uc, int n)
+{
+  if (uc < 0xd800 || (uc >= 0xe000 && uc < 0x110000))
+    {
+      if (n > 0)
+       {
+         *s = uc;
+         return 1;
+       }
+      else
+       return -2;
+    }
+  else
+    return -1;
+}
+# endif
+#endif
+
+/* Copy N units from SRC to DEST.  */
+/* Similar to memcpy().  */
+extern uint8_t *
+       u8_cpy (uint8_t *dest, const uint8_t *src, size_t n);
+extern uint16_t *
+       u16_cpy (uint16_t *dest, const uint16_t *src, size_t n);
+extern uint32_t *
+       u32_cpy (uint32_t *dest, const uint32_t *src, size_t n);
+
+/* Copy N units from SRC to DEST, guaranteeing correct behavior for
+   overlapping memory areas.  */
+/* Similar to memmove().  */
+extern uint8_t *
+       u8_move (uint8_t *dest, const uint8_t *src, size_t n);
+extern uint16_t *
+       u16_move (uint16_t *dest, const uint16_t *src, size_t n);
+extern uint32_t *
+       u32_move (uint32_t *dest, const uint32_t *src, size_t n);
+
+/* Set the first N characters of S to UC.  UC should be a character that
+   occupies only 1 unit.  */
+/* Similar to memset().  */
+extern uint8_t *
+       u8_set (uint8_t *s, ucs4_t uc, size_t n);
+extern uint16_t *
+       u16_set (uint16_t *s, ucs4_t uc, size_t n);
+extern uint32_t *
+       u32_set (uint32_t *s, ucs4_t uc, size_t n);
+
+/* Compare S1 and S2, each of length N.  */
+/* Similar to memcmp().  */
+extern int
+       u8_cmp (const uint8_t *s1, const uint8_t *s2, size_t n);
+extern int
+       u16_cmp (const uint16_t *s1, const uint16_t *s2, size_t n);
+extern int
+       u32_cmp (const uint32_t *s1, const uint32_t *s2, size_t n);
+
+/* Compare S1 and S2.  */
+/* Similar to the gnulib function memcmp2().  */
+extern int
+       u8_cmp2 (const uint8_t *s1, size_t n1, const uint8_t *s2, size_t n2);
+extern int
+       u16_cmp2 (const uint16_t *s1, size_t n1, const uint16_t *s2, size_t n2);
+extern int
+       u32_cmp2 (const uint32_t *s1, size_t n1, const uint32_t *s2, size_t n2);
+
+/* Search the string at S for UC.  */
+/* Similar to memchr().  */
+extern uint8_t *
+       u8_chr (const uint8_t *s, size_t n, ucs4_t uc);
+extern uint16_t *
+       u16_chr (const uint16_t *s, size_t n, ucs4_t uc);
+extern uint32_t *
+       u32_chr (const uint32_t *s, size_t n, ucs4_t uc);
+
+/* Count the number of Unicode characters in the N units from S.  */
+/* Similar to mbsnlen().  */
+extern size_t
+       u8_mbsnlen (const uint8_t *s, size_t n);
+extern size_t
+       u16_mbsnlen (const uint16_t *s, size_t n);
+extern size_t
+       u32_mbsnlen (const uint32_t *s, size_t n);
+
+/* Elementary string functions with memory allocation.  */
+
+/* Make a freshly allocated copy of S, of length N.  */
+extern uint8_t *
+       u8_cpy_alloc (const uint8_t *s, size_t n);
+extern uint16_t *
+       u16_cpy_alloc (const uint16_t *s, size_t n);
+extern uint32_t *
+       u32_cpy_alloc (const uint32_t *s, size_t n);
+
+/* Elementary string functions on NUL terminated strings.  */
+
+/* Return the length (number of units) of the first character in S.
+   Return 0 if it is the NUL character.  Return -1 upon failure.  */
+extern int
+       u8_strmblen (const uint8_t *s);
+extern int
+       u16_strmblen (const uint16_t *s);
+extern int
+       u32_strmblen (const uint32_t *s);
+
+/* Return the length (number of units) of the first character in S, putting
+   its 'ucs4_t' representation in *PUC.  Return 0 if it is the NUL
+   character.  Return -1 upon failure.  */
+extern int
+       u8_strmbtouc (ucs4_t *puc, const uint8_t *s);
+extern int
+       u16_strmbtouc (ucs4_t *puc, const uint16_t *s);
+extern int
+       u32_strmbtouc (ucs4_t *puc, const uint32_t *s);
+
+/* Forward iteration step.  Advances the pointer past the next character,
+   or returns NULL if the end of the string has been reached.  Puts the
+   character's 'ucs4_t' representation in *PUC.  */
+extern const uint8_t *
+       u8_next (ucs4_t *puc, const uint8_t *s);
+extern const uint16_t *
+       u16_next (ucs4_t *puc, const uint16_t *s);
+extern const uint32_t *
+       u32_next (ucs4_t *puc, const uint32_t *s);
+
+/* Backward iteration step.  Advances the pointer to point to the previous
+   character, or returns NULL if the beginning of the string had been reached.
+   Puts the character's 'ucs4_t' representation in *PUC.  */
+extern const uint8_t *
+       u8_prev (ucs4_t *puc, const uint8_t *s, const uint8_t *start);
+extern const uint16_t *
+       u16_prev (ucs4_t *puc, const uint16_t *s, const uint16_t *start);
+extern const uint32_t *
+       u32_prev (ucs4_t *puc, const uint32_t *s, const uint32_t *start);
+
+/* Return the number of units in S.  */
+/* Similar to strlen(), wcslen().  */
+extern size_t
+       u8_strlen (const uint8_t *s);
+extern size_t
+       u16_strlen (const uint16_t *s);
+extern size_t
+       u32_strlen (const uint32_t *s);
+
+/* Return the number of units in S, but at most MAXLEN.  */
+/* Similar to strnlen(), wcsnlen().  */
+extern size_t
+       u8_strnlen (const uint8_t *s, size_t maxlen);
+extern size_t
+       u16_strnlen (const uint16_t *s, size_t maxlen);
+extern size_t
+       u32_strnlen (const uint32_t *s, size_t maxlen);
+
+/* Copy SRC to DEST.  */
+/* Similar to strcpy(), wcscpy().  */
+extern uint8_t *
+       u8_strcpy (uint8_t *dest, const uint8_t *src);
+extern uint16_t *
+       u16_strcpy (uint16_t *dest, const uint16_t *src);
+extern uint32_t *
+       u32_strcpy (uint32_t *dest, const uint32_t *src);
+
+/* Copy SRC to DEST, returning the address of the terminating NUL in DEST.  */
+/* Similar to stpcpy().  */
+extern uint8_t *
+       u8_stpcpy (uint8_t *dest, const uint8_t *src);
+extern uint16_t *
+       u16_stpcpy (uint16_t *dest, const uint16_t *src);
+extern uint32_t *
+       u32_stpcpy (uint32_t *dest, const uint32_t *src);
+
+/* Copy no more than N units of SRC to DEST.  */
+/* Similar to strncpy(), wcsncpy().  */
+extern uint8_t *
+       u8_strncpy (uint8_t *dest, const uint8_t *src, size_t n);
+extern uint16_t *
+       u16_strncpy (uint16_t *dest, const uint16_t *src, size_t n);
+extern uint32_t *
+       u32_strncpy (uint32_t *dest, const uint32_t *src, size_t n);
+
+/* Copy no more than N units of SRC to DEST, returning the address of
+   the last unit written into DEST.  */
+/* Similar to stpncpy().  */
+extern uint8_t *
+       u8_stpncpy (uint8_t *dest, const uint8_t *src, size_t n);
+extern uint16_t *
+       u16_stpncpy (uint16_t *dest, const uint16_t *src, size_t n);
+extern uint32_t *
+       u32_stpncpy (uint32_t *dest, const uint32_t *src, size_t n);
+
+/* Append SRC onto DEST.  */
+/* Similar to strcat(), wcscat().  */
+extern uint8_t *
+       u8_strcat (uint8_t *dest, const uint8_t *src);
+extern uint16_t *
+       u16_strcat (uint16_t *dest, const uint16_t *src);
+extern uint32_t *
+       u32_strcat (uint32_t *dest, const uint32_t *src);
+
+/* Append no more than N units of SRC onto DEST.  */
+/* Similar to strncat(), wcsncat().  */
+extern uint8_t *
+       u8_strncat (uint8_t *dest, const uint8_t *src, size_t n);
+extern uint16_t *
+       u16_strncat (uint16_t *dest, const uint16_t *src, size_t n);
+extern uint32_t *
+       u32_strncat (uint32_t *dest, const uint32_t *src, size_t n);
+
+/* Compare S1 and S2.  */
+/* Similar to strcmp(), wcscmp().  */
+extern int
+       u8_strcmp (const uint8_t *s1, const uint8_t *s2);
+extern int
+       u16_strcmp (const uint16_t *s1, const uint16_t *s2);
+extern int
+       u32_strcmp (const uint32_t *s1, const uint32_t *s2);
+
+/* Compare S1 and S2 using the collation rules of the current locale.
+   Return -1 if S1 < S2, 0 if S1 = S2, 1 if S1 > S2.
+   Upon failure, set errno and return any value.  */
+/* Similar to strcoll(), wcscoll().  */
+extern int
+       u8_strcoll (const uint8_t *s1, const uint8_t *s2);
+extern int
+       u16_strcoll (const uint16_t *s1, const uint16_t *s2);
+extern int
+       u32_strcoll (const uint32_t *s1, const uint32_t *s2);
+
+/* Compare no more than N units of S1 and S2.  */
+/* Similar to strncmp(), wcsncmp().  */
+extern int
+       u8_strncmp (const uint8_t *s1, const uint8_t *s2, size_t n);
+extern int
+       u16_strncmp (const uint16_t *s1, const uint16_t *s2, size_t n);
+extern int
+       u32_strncmp (const uint32_t *s1, const uint32_t *s2, size_t n);
+
+/* Duplicate S, returning an identical malloc'd string.  */
+/* Similar to strdup(), wcsdup().  */
+extern uint8_t *
+       u8_strdup (const uint8_t *s);
+extern uint16_t *
+       u16_strdup (const uint16_t *s);
+extern uint32_t *
+       u32_strdup (const uint32_t *s);
+
+/* Find the first occurrence of UC in STR.  */
+/* Similar to strchr(), wcschr().  */
+extern uint8_t *
+       u8_strchr (const uint8_t *str, ucs4_t uc);
+extern uint16_t *
+       u16_strchr (const uint16_t *str, ucs4_t uc);
+extern uint32_t *
+       u32_strchr (const uint32_t *str, ucs4_t uc);
+
+/* Find the last occurrence of UC in STR.  */
+/* Similar to strrchr(), wcsrchr().  */
+extern uint8_t *
+       u8_strrchr (const uint8_t *str, ucs4_t uc);
+extern uint16_t *
+       u16_strrchr (const uint16_t *str, ucs4_t uc);
+extern uint32_t *
+       u32_strrchr (const uint32_t *str, ucs4_t uc);
+
+/* Return the length of the initial segment of STR which consists entirely
+   of Unicode characters not in REJECT.  */
+/* Similar to strcspn(), wcscspn().  */
+extern size_t
+       u8_strcspn (const uint8_t *str, const uint8_t *reject);
+extern size_t
+       u16_strcspn (const uint16_t *str, const uint16_t *reject);
+extern size_t
+       u32_strcspn (const uint32_t *str, const uint32_t *reject);
+
+/* Return the length of the initial segment of STR which consists entirely
+   of Unicode characters in ACCEPT.  */
+/* Similar to strspn(), wcsspn().  */
+extern size_t
+       u8_strspn (const uint8_t *str, const uint8_t *accept);
+extern size_t
+       u16_strspn (const uint16_t *str, const uint16_t *accept);
+extern size_t
+       u32_strspn (const uint32_t *str, const uint32_t *accept);
+
+/* Find the first occurrence in STR of any character in ACCEPT.  */
+/* Similar to strpbrk(), wcspbrk().  */
+extern uint8_t *
+       u8_strpbrk (const uint8_t *str, const uint8_t *accept);
+extern uint16_t *
+       u16_strpbrk (const uint16_t *str, const uint16_t *accept);
+extern uint32_t *
+       u32_strpbrk (const uint32_t *str, const uint32_t *accept);
+
+/* Find the first occurrence of NEEDLE in HAYSTACK.  */
+/* Similar to strstr(), wcsstr().  */
+extern uint8_t *
+       u8_strstr (const uint8_t *haystack, const uint8_t *needle);
+extern uint16_t *
+       u16_strstr (const uint16_t *haystack, const uint16_t *needle);
+extern uint32_t *
+       u32_strstr (const uint32_t *haystack, const uint32_t *needle);
+
+/* Test whether STR starts with PREFIX.  */
+extern bool
+       u8_startswith (const uint8_t *str, const uint8_t *prefix);
+extern bool
+       u16_startswith (const uint16_t *str, const uint16_t *prefix);
+extern bool
+       u32_startswith (const uint32_t *str, const uint32_t *prefix);
+
+/* Test whether STR ends with SUFFIX.  */
+extern bool
+       u8_endswith (const uint8_t *str, const uint8_t *suffix);
+extern bool
+       u16_endswith (const uint16_t *str, const uint16_t *suffix);
+extern bool
+       u32_endswith (const uint32_t *str, const uint32_t *suffix);
+
+/* Divide STR into tokens separated by characters in DELIM.
+   This interface is actually more similar to wcstok than to strtok.  */
+/* Similar to strtok_r(), wcstok().  */
+extern uint8_t *
+       u8_strtok (uint8_t *str, const uint8_t *delim, uint8_t **ptr);
+extern uint16_t *
+       u16_strtok (uint16_t *str, const uint16_t *delim, uint16_t **ptr);
+extern uint32_t *
+       u32_strtok (uint32_t *str, const uint32_t *delim, uint32_t **ptr);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UNISTR_H */
diff --git a/lib/unistr/u8-mbtouc-aux.c b/lib/unistr/u8-mbtouc-aux.c
new file mode 100644
index 0000000..53d02bf
--- /dev/null
+++ b/lib/unistr/u8-mbtouc-aux.c
@@ -0,0 +1,158 @@
+/* Conversion UTF-8 to UCS-4.
+   Copyright (C) 2001-2002, 2006-2007, 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 2001.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "unistr.h"
+
+#if defined IN_LIBUNISTRING || HAVE_INLINE
+
+int
+u8_mbtouc_aux (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+  uint8_t c = *s;
+
+  if (c >= 0xc2)
+    {
+      if (c < 0xe0)
+       {
+         if (n >= 2)
+           {
+             if ((s[1] ^ 0x80) < 0x40)
+               {
+                 *puc = ((unsigned int) (c & 0x1f) << 6)
+                        | (unsigned int) (s[1] ^ 0x80);
+                 return 2;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xf0)
+       {
+         if (n >= 3)
+           {
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (c >= 0xe1 || s[1] >= 0xa0)
+                 && (c != 0xed || s[1] < 0xa0))
+               {
+                 *puc = ((unsigned int) (c & 0x0f) << 12)
+                        | ((unsigned int) (s[1] ^ 0x80) << 6)
+                        | (unsigned int) (s[2] ^ 0x80);
+                 return 3;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xf8)
+       {
+         if (n >= 4)
+           {
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40
+                 && (c >= 0xf1 || s[1] >= 0x90)
+#if 1
+                 && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90))
+#endif
+                )
+               {
+                 *puc = ((unsigned int) (c & 0x07) << 18)
+                        | ((unsigned int) (s[1] ^ 0x80) << 12)
+                        | ((unsigned int) (s[2] ^ 0x80) << 6)
+                        | (unsigned int) (s[3] ^ 0x80);
+                 return 4;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+#if 0
+      else if (c < 0xfc)
+       {
+         if (n >= 5)
+           {
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                 && (c >= 0xf9 || s[1] >= 0x88))
+               {
+                 *puc = ((unsigned int) (c & 0x03) << 24)
+                        | ((unsigned int) (s[1] ^ 0x80) << 18)
+                        | ((unsigned int) (s[2] ^ 0x80) << 12)
+                        | ((unsigned int) (s[3] ^ 0x80) << 6)
+                        | (unsigned int) (s[4] ^ 0x80);
+                 return 5;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xfe)
+       {
+         if (n >= 6)
+           {
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                 && (s[5] ^ 0x80) < 0x40
+                 && (c >= 0xfd || s[1] >= 0x84))
+               {
+                 *puc = ((unsigned int) (c & 0x01) << 30)
+                        | ((unsigned int) (s[1] ^ 0x80) << 24)
+                        | ((unsigned int) (s[2] ^ 0x80) << 18)
+                        | ((unsigned int) (s[3] ^ 0x80) << 12)
+                        | ((unsigned int) (s[4] ^ 0x80) << 6)
+                        | (unsigned int) (s[5] ^ 0x80);
+                 return 6;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+#endif
+    }
+  /* invalid multibyte character */
+  *puc = 0xfffd;
+  return 1;
+}
+
+#endif
diff --git a/lib/unistr/u8-mbtouc-unsafe-aux.c 
b/lib/unistr/u8-mbtouc-unsafe-aux.c
new file mode 100644
index 0000000..43e4a36
--- /dev/null
+++ b/lib/unistr/u8-mbtouc-unsafe-aux.c
@@ -0,0 +1,168 @@
+/* Conversion UTF-8 to UCS-4.
+   Copyright (C) 2001-2002, 2006-2007, 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 2001.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "unistr.h"
+
+#if defined IN_LIBUNISTRING || HAVE_INLINE
+
+int
+u8_mbtouc_unsafe_aux (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+  uint8_t c = *s;
+
+  if (c >= 0xc2)
+    {
+      if (c < 0xe0)
+       {
+         if (n >= 2)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40)
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x1f) << 6)
+                        | (unsigned int) (s[1] ^ 0x80);
+                 return 2;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xf0)
+       {
+         if (n >= 3)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (c >= 0xe1 || s[1] >= 0xa0)
+                 && (c != 0xed || s[1] < 0xa0))
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x0f) << 12)
+                        | ((unsigned int) (s[1] ^ 0x80) << 6)
+                        | (unsigned int) (s[2] ^ 0x80);
+                 return 3;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xf8)
+       {
+         if (n >= 4)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40
+                 && (c >= 0xf1 || s[1] >= 0x90)
+#if 1
+                 && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90))
+#endif
+                )
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x07) << 18)
+                        | ((unsigned int) (s[1] ^ 0x80) << 12)
+                        | ((unsigned int) (s[2] ^ 0x80) << 6)
+                        | (unsigned int) (s[3] ^ 0x80);
+                 return 4;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+#if 0
+      else if (c < 0xfc)
+       {
+         if (n >= 5)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                 && (c >= 0xf9 || s[1] >= 0x88))
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x03) << 24)
+                        | ((unsigned int) (s[1] ^ 0x80) << 18)
+                        | ((unsigned int) (s[2] ^ 0x80) << 12)
+                        | ((unsigned int) (s[3] ^ 0x80) << 6)
+                        | (unsigned int) (s[4] ^ 0x80);
+                 return 5;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xfe)
+       {
+         if (n >= 6)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                 && (s[5] ^ 0x80) < 0x40
+                 && (c >= 0xfd || s[1] >= 0x84))
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x01) << 30)
+                        | ((unsigned int) (s[1] ^ 0x80) << 24)
+                        | ((unsigned int) (s[2] ^ 0x80) << 18)
+                        | ((unsigned int) (s[3] ^ 0x80) << 12)
+                        | ((unsigned int) (s[4] ^ 0x80) << 6)
+                        | (unsigned int) (s[5] ^ 0x80);
+                 return 6;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+#endif
+    }
+  /* invalid multibyte character */
+  *puc = 0xfffd;
+  return 1;
+}
+
+#endif
diff --git a/lib/unistr/u8-mbtouc-unsafe.c b/lib/unistr/u8-mbtouc-unsafe.c
new file mode 100644
index 0000000..4661569
--- /dev/null
+++ b/lib/unistr/u8-mbtouc-unsafe.c
@@ -0,0 +1,179 @@
+/* Look at first character in UTF-8 string.
+   Copyright (C) 1999-2002, 2006-2007, 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 2001.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#if defined IN_LIBUNISTRING
+/* Tell unistr.h to declare u8_mbtouc_unsafe as 'extern', not
+   'static inline'.  */
+# include "unistring-notinline.h"
+#endif
+
+/* Specification.  */
+#include "unistr.h"
+
+#if !HAVE_INLINE
+
+int
+u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+  uint8_t c = *s;
+
+  if (c < 0x80)
+    {
+      *puc = c;
+      return 1;
+    }
+  else if (c >= 0xc2)
+    {
+      if (c < 0xe0)
+       {
+         if (n >= 2)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40)
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x1f) << 6)
+                        | (unsigned int) (s[1] ^ 0x80);
+                 return 2;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xf0)
+       {
+         if (n >= 3)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (c >= 0xe1 || s[1] >= 0xa0)
+                 && (c != 0xed || s[1] < 0xa0))
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x0f) << 12)
+                        | ((unsigned int) (s[1] ^ 0x80) << 6)
+                        | (unsigned int) (s[2] ^ 0x80);
+                 return 3;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xf8)
+       {
+         if (n >= 4)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40
+                 && (c >= 0xf1 || s[1] >= 0x90)
+#if 1
+                 && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90))
+#endif
+                )
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x07) << 18)
+                        | ((unsigned int) (s[1] ^ 0x80) << 12)
+                        | ((unsigned int) (s[2] ^ 0x80) << 6)
+                        | (unsigned int) (s[3] ^ 0x80);
+                 return 4;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+#if 0
+      else if (c < 0xfc)
+       {
+         if (n >= 5)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                 && (c >= 0xf9 || s[1] >= 0x88))
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x03) << 24)
+                        | ((unsigned int) (s[1] ^ 0x80) << 18)
+                        | ((unsigned int) (s[2] ^ 0x80) << 12)
+                        | ((unsigned int) (s[3] ^ 0x80) << 6)
+                        | (unsigned int) (s[4] ^ 0x80);
+                 return 5;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xfe)
+       {
+         if (n >= 6)
+           {
+#if CONFIG_UNICODE_SAFETY
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                 && (s[5] ^ 0x80) < 0x40
+                 && (c >= 0xfd || s[1] >= 0x84))
+#endif
+               {
+                 *puc = ((unsigned int) (c & 0x01) << 30)
+                        | ((unsigned int) (s[1] ^ 0x80) << 24)
+                        | ((unsigned int) (s[2] ^ 0x80) << 18)
+                        | ((unsigned int) (s[3] ^ 0x80) << 12)
+                        | ((unsigned int) (s[4] ^ 0x80) << 6)
+                        | (unsigned int) (s[5] ^ 0x80);
+                 return 6;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+#endif
+    }
+  /* invalid multibyte character */
+  *puc = 0xfffd;
+  return 1;
+}
+
+#endif
diff --git a/lib/unistr/u8-mbtouc.c b/lib/unistr/u8-mbtouc.c
new file mode 100644
index 0000000..ff624f1
--- /dev/null
+++ b/lib/unistr/u8-mbtouc.c
@@ -0,0 +1,168 @@
+/* Look at first character in UTF-8 string.
+   Copyright (C) 1999-2002, 2006-2007, 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 2001.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#if defined IN_LIBUNISTRING
+/* Tell unistr.h to declare u8_mbtouc as 'extern', not 'static inline'.  */
+# include "unistring-notinline.h"
+#endif
+
+/* Specification.  */
+#include "unistr.h"
+
+#if !HAVE_INLINE
+
+int
+u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+  uint8_t c = *s;
+
+  if (c < 0x80)
+    {
+      *puc = c;
+      return 1;
+    }
+  else if (c >= 0xc2)
+    {
+      if (c < 0xe0)
+       {
+         if (n >= 2)
+           {
+             if ((s[1] ^ 0x80) < 0x40)
+               {
+                 *puc = ((unsigned int) (c & 0x1f) << 6)
+                        | (unsigned int) (s[1] ^ 0x80);
+                 return 2;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xf0)
+       {
+         if (n >= 3)
+           {
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (c >= 0xe1 || s[1] >= 0xa0)
+                 && (c != 0xed || s[1] < 0xa0))
+               {
+                 *puc = ((unsigned int) (c & 0x0f) << 12)
+                        | ((unsigned int) (s[1] ^ 0x80) << 6)
+                        | (unsigned int) (s[2] ^ 0x80);
+                 return 3;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xf8)
+       {
+         if (n >= 4)
+           {
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40
+                 && (c >= 0xf1 || s[1] >= 0x90)
+#if 1
+                 && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90))
+#endif
+                )
+               {
+                 *puc = ((unsigned int) (c & 0x07) << 18)
+                        | ((unsigned int) (s[1] ^ 0x80) << 12)
+                        | ((unsigned int) (s[2] ^ 0x80) << 6)
+                        | (unsigned int) (s[3] ^ 0x80);
+                 return 4;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+#if 0
+      else if (c < 0xfc)
+       {
+         if (n >= 5)
+           {
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                 && (c >= 0xf9 || s[1] >= 0x88))
+               {
+                 *puc = ((unsigned int) (c & 0x03) << 24)
+                        | ((unsigned int) (s[1] ^ 0x80) << 18)
+                        | ((unsigned int) (s[2] ^ 0x80) << 12)
+                        | ((unsigned int) (s[3] ^ 0x80) << 6)
+                        | (unsigned int) (s[4] ^ 0x80);
+                 return 5;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+      else if (c < 0xfe)
+       {
+         if (n >= 6)
+           {
+             if ((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40
+                 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40
+                 && (s[5] ^ 0x80) < 0x40
+                 && (c >= 0xfd || s[1] >= 0x84))
+               {
+                 *puc = ((unsigned int) (c & 0x01) << 30)
+                        | ((unsigned int) (s[1] ^ 0x80) << 24)
+                        | ((unsigned int) (s[2] ^ 0x80) << 18)
+                        | ((unsigned int) (s[3] ^ 0x80) << 12)
+                        | ((unsigned int) (s[4] ^ 0x80) << 6)
+                        | (unsigned int) (s[5] ^ 0x80);
+                 return 6;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return n;
+           }
+       }
+#endif
+    }
+  /* invalid multibyte character */
+  *puc = 0xfffd;
+  return 1;
+}
+
+#endif
diff --git a/lib/unistr/u8-mbtoucr.c b/lib/unistr/u8-mbtoucr.c
new file mode 100644
index 0000000..dd83352
--- /dev/null
+++ b/lib/unistr/u8-mbtoucr.c
@@ -0,0 +1,285 @@
+/* Look at first character in UTF-8 string, returning an error code.
+   Copyright (C) 1999-2002, 2006-2007 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 2001.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "unistr.h"
+
+int
+u8_mbtoucr (ucs4_t *puc, const uint8_t *s, size_t n)
+{
+  uint8_t c = *s;
+
+  if (c < 0x80)
+    {
+      *puc = c;
+      return 1;
+    }
+  else if (c >= 0xc2)
+    {
+      if (c < 0xe0)
+       {
+         if (n >= 2)
+           {
+             if ((s[1] ^ 0x80) < 0x40)
+               {
+                 *puc = ((unsigned int) (c & 0x1f) << 6)
+                        | (unsigned int) (s[1] ^ 0x80);
+                 return 2;
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return -2;
+           }
+       }
+      else if (c < 0xf0)
+       {
+         if (n >= 2)
+           {
+             if ((s[1] ^ 0x80) < 0x40
+                 && (c >= 0xe1 || s[1] >= 0xa0)
+                 && (c != 0xed || s[1] < 0xa0))
+               {
+                 if (n >= 3)
+                   {
+                     if ((s[2] ^ 0x80) < 0x40)
+                       {
+                         *puc = ((unsigned int) (c & 0x0f) << 12)
+                                | ((unsigned int) (s[1] ^ 0x80) << 6)
+                                | (unsigned int) (s[2] ^ 0x80);
+                         return 3;
+                       }
+                     /* invalid multibyte character */
+                   }
+                 else
+                   {
+                     /* incomplete multibyte character */
+                     *puc = 0xfffd;
+                     return -2;
+                   }
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return -2;
+           }
+       }
+      else if (c < 0xf8)
+       {
+         if (n >= 2)
+           {
+             if ((s[1] ^ 0x80) < 0x40
+                 && (c >= 0xf1 || s[1] >= 0x90)
+#if 1
+                 && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90))
+#endif
+                )
+               {
+                 if (n >= 3)
+                   {
+                     if ((s[2] ^ 0x80) < 0x40)
+                       {
+                         if (n >= 4)
+                           {
+                             if ((s[3] ^ 0x80) < 0x40)
+                               {
+                                 *puc = ((unsigned int) (c & 0x07) << 18)
+                                        | ((unsigned int) (s[1] ^ 0x80) << 12)
+                                        | ((unsigned int) (s[2] ^ 0x80) << 6)
+                                        | (unsigned int) (s[3] ^ 0x80);
+                                 return 4;
+                               }
+                             /* invalid multibyte character */
+                           }
+                         else
+                           {
+                             /* incomplete multibyte character */
+                             *puc = 0xfffd;
+                             return -2;
+                           }
+                       }
+                     /* invalid multibyte character */
+                   }
+                 else
+                   {
+                     /* incomplete multibyte character */
+                     *puc = 0xfffd;
+                     return -2;
+                   }
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return -2;
+           }
+       }
+#if 0
+      else if (c < 0xfc)
+       {
+         if (n >= 2)
+           {
+             if ((s[1] ^ 0x80) < 0x40
+                 && (c >= 0xf9 || s[1] >= 0x88))
+               {
+                 if (n >= 3)
+                   {
+                     if ((s[2] ^ 0x80) < 0x40)
+                       {
+                         if (n >= 4)
+                           {
+                             if ((s[3] ^ 0x80) < 0x40)
+                               {
+                                 if (n >= 5)
+                                   {
+                                     if ((s[4] ^ 0x80) < 0x40)
+                                       {
+                                         *puc = ((unsigned int) (c & 0x03) << 
24)
+                                                | ((unsigned int) (s[1] ^ 
0x80) << 18)
+                                                | ((unsigned int) (s[2] ^ 
0x80) << 12)
+                                                | ((unsigned int) (s[3] ^ 
0x80) << 6)
+                                                | (unsigned int) (s[4] ^ 0x80);
+                                         return 5;
+                                       }
+                                     /* invalid multibyte character */
+                                   }
+                                 else
+                                   {
+                                     /* incomplete multibyte character */
+                                     *puc = 0xfffd;
+                                     return -2;
+                                   }
+                               }
+                             /* invalid multibyte character */
+                           }
+                         else
+                           {
+                             /* incomplete multibyte character */
+                             *puc = 0xfffd;
+                             return -2;
+                           }
+                       }
+                     /* invalid multibyte character */
+                   }
+                 else
+                   {
+                     /* incomplete multibyte character */
+                     *puc = 0xfffd;
+                     return -2;
+                   }
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return -2;
+           }
+       }
+      else if (c < 0xfe)
+       {
+         if (n >= 2)
+           {
+             if ((s[1] ^ 0x80) < 0x40
+                 && (c >= 0xfd || s[1] >= 0x84))
+               {
+                 if (n >= 3)
+                   {
+                     if ((s[2] ^ 0x80) < 0x40)
+                       {
+                         if (n >= 4)
+                           {
+                             if ((s[3] ^ 0x80) < 0x40)
+                               {
+                                 if (n >= 5)
+                                   {
+                                     if ((s[4] ^ 0x80) < 0x40)
+                                       {
+                                         if (n >= 6)
+                                           {
+                                             if ((s[5] ^ 0x80) < 0x40)
+                                               {
+                                                 *puc = ((unsigned int) (c & 
0x01) << 30)
+                                                        | ((unsigned int) 
(s[1] ^ 0x80) << 24)
+                                                        | ((unsigned int) 
(s[2] ^ 0x80) << 18)
+                                                        | ((unsigned int) 
(s[3] ^ 0x80) << 12)
+                                                        | ((unsigned int) 
(s[4] ^ 0x80) << 6)
+                                                        | (unsigned int) (s[5] 
^ 0x80);
+                                                 return 6;
+                                               }
+                                             /* invalid multibyte character */
+                                           }
+                                         else
+                                           {
+                                             /* incomplete multibyte character 
*/
+                                             *puc = 0xfffd;
+                                             return -2;
+                                           }
+                                       }
+                                     /* invalid multibyte character */
+                                   }
+                                 else
+                                   {
+                                     /* incomplete multibyte character */
+                                     *puc = 0xfffd;
+                                     return -2;
+                                   }
+                               }
+                             /* invalid multibyte character */
+                           }
+                         else
+                           {
+                             /* incomplete multibyte character */
+                             *puc = 0xfffd;
+                             return -2;
+                           }
+                       }
+                     /* invalid multibyte character */
+                   }
+                 else
+                   {
+                     /* incomplete multibyte character */
+                     *puc = 0xfffd;
+                     return -2;
+                   }
+               }
+             /* invalid multibyte character */
+           }
+         else
+           {
+             /* incomplete multibyte character */
+             *puc = 0xfffd;
+             return -2;
+           }
+       }
+#endif
+    }
+  /* invalid multibyte character */
+  *puc = 0xfffd;
+  return -1;
+}
diff --git a/lib/unistr/u8-prev.c b/lib/unistr/u8-prev.c
new file mode 100644
index 0000000..245d22f
--- /dev/null
+++ b/lib/unistr/u8-prev.c
@@ -0,0 +1,93 @@
+/* Iterate over previous character in UTF-8 string.
+   Copyright (C) 2002, 2006-2007 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 2002.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "unistr.h"
+
+const uint8_t *
+u8_prev (ucs4_t *puc, const uint8_t *s, const uint8_t *start)
+{
+  /* Keep in sync with unistr.h and utf8-ucs4.c.  */
+  if (s != start)
+    {
+      uint8_t c_1 = s[-1];
+
+      if (c_1 < 0x80)
+       {
+         *puc = c_1;
+         return s - 1;
+       }
+#if CONFIG_UNICODE_SAFETY
+      if ((c_1 ^ 0x80) < 0x40)
+#endif
+       if (s - 1 != start)
+         {
+           uint8_t c_2 = s[-2];
+
+           if (c_2 >= 0xc2 && c_2 < 0xe0)
+             {
+               *puc = ((unsigned int) (c_2 & 0x1f) << 6)
+                      | (unsigned int) (c_1 ^ 0x80);
+               return s - 2;
+             }
+#if CONFIG_UNICODE_SAFETY
+           if ((c_2 ^ 0x80) < 0x40)
+#endif
+             if (s - 2 != start)
+               {
+                 uint8_t c_3 = s[-3];
+
+                 if (c_3 >= 0xe0 && c_3 < 0xf0
+#if CONFIG_UNICODE_SAFETY
+                     && (c_3 >= 0xe1 || c_2 >= 0xa0)
+                     && (c_3 != 0xed || c_2 < 0xa0)
+#endif
+                    )
+                   {
+                     *puc = ((unsigned int) (c_3 & 0x0f) << 12)
+                            | ((unsigned int) (c_2 ^ 0x80) << 6)
+                            | (unsigned int) (c_1 ^ 0x80);
+                     return s - 3;
+                   }
+#if CONFIG_UNICODE_SAFETY
+                 if ((c_3 ^ 0x80) < 0x40)
+#endif
+                   if (s - 3 != start)
+                     {
+                       uint8_t c_4 = s[-4];
+
+                       if (c_4 >= 0xf0 && c_4 < 0xf8
+#if CONFIG_UNICODE_SAFETY
+                           && (c_4 >= 0xf1 || c_3 >= 0x90)
+                           && (c_4 < 0xf4 || (c_4 == 0xf4 && c_3 < 0x90))
+#endif
+                          )
+                         {
+                           *puc = ((unsigned int) (c_4 & 0x07) << 18)
+                                  | ((unsigned int) (c_3 ^ 0x80) << 12)
+                                  | ((unsigned int) (c_2 ^ 0x80) << 6)
+                                  | (unsigned int) (c_1 ^ 0x80);
+                           return s - 4;
+                         }
+                     }
+               }
+         }
+    }
+  return NULL;
+}
diff --git a/lib/unistr/u8-uctomb-aux.c b/lib/unistr/u8-uctomb-aux.c
new file mode 100644
index 0000000..c42fa50
--- /dev/null
+++ b/lib/unistr/u8-uctomb-aux.c
@@ -0,0 +1,69 @@
+/* Conversion UCS-4 to UTF-8.
+   Copyright (C) 2002, 2006-2007 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 2002.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "unistr.h"
+
+int
+u8_uctomb_aux (uint8_t *s, ucs4_t uc, int n)
+{
+  int count;
+
+  if (uc < 0x80)
+    /* The case n >= 1 is already handled by the caller.  */
+    return -2;
+  else if (uc < 0x800)
+    count = 2;
+  else if (uc < 0x10000)
+    {
+      if (uc < 0xd800 || uc >= 0xe000)
+       count = 3;
+      else
+       return -1;
+    }
+#if 0
+  else if (uc < 0x200000)
+    count = 4;
+  else if (uc < 0x4000000)
+    count = 5;
+  else if (uc <= 0x7fffffff)
+    count = 6;
+#else
+  else if (uc < 0x110000)
+    count = 4;
+#endif
+  else
+    return -1;
+
+  if (n < count)
+    return -2;
+
+  switch (count) /* note: code falls through cases! */
+    {
+#if 0
+    case 6: s[5] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x4000000;
+    case 5: s[4] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x200000;
+#endif
+    case 4: s[3] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x10000;
+    case 3: s[2] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x800;
+    case 2: s[1] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0xc0;
+  /*case 1:*/ s[0] = uc;
+    }
+  return count;
+}
diff --git a/lib/unistr/u8-uctomb.c b/lib/unistr/u8-uctomb.c
new file mode 100644
index 0000000..3392166
--- /dev/null
+++ b/lib/unistr/u8-uctomb.c
@@ -0,0 +1,88 @@
+/* Store a character in UTF-8 string.
+   Copyright (C) 2002, 2005-2006, 2009 Free Software Foundation, Inc.
+   Written by Bruno Haible <address@hidden>, 2002.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#if defined IN_LIBUNISTRING
+/* Tell unistr.h to declare u8_uctomb as 'extern', not 'static inline'.  */
+# include "unistring-notinline.h"
+#endif
+
+/* Specification.  */
+#include "unistr.h"
+
+#if !HAVE_INLINE
+
+int
+u8_uctomb (uint8_t *s, ucs4_t uc, int n)
+{
+  if (uc < 0x80)
+    {
+      if (n > 0)
+       {
+         s[0] = uc;
+         return 1;
+       }
+      /* else return -2, below.  */
+    }
+  else
+    {
+      int count;
+
+      if (uc < 0x800)
+       count = 2;
+      else if (uc < 0x10000)
+       {
+         if (uc < 0xd800 || uc >= 0xe000)
+           count = 3;
+         else
+           return -1;
+       }
+#if 0
+      else if (uc < 0x200000)
+       count = 4;
+      else if (uc < 0x4000000)
+       count = 5;
+      else if (uc <= 0x7fffffff)
+       count = 6;
+#else
+      else if (uc < 0x110000)
+       count = 4;
+#endif
+      else
+       return -1;
+
+      if (n >= count)
+       {
+         switch (count) /* note: code falls through cases! */
+           {
+#if 0
+           case 6: s[5] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x4000000;
+           case 5: s[4] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x200000;
+#endif
+           case 4: s[3] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x10000;
+           case 3: s[2] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x800;
+           case 2: s[1] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0xc0;
+         /*case 1:*/ s[0] = uc;
+           }
+         return count;
+       }
+    }
+  return -2;
+}
+
+#endif
diff --git a/lib/unitypes.h b/lib/unitypes.h
new file mode 100644
index 0000000..fe8d877
--- /dev/null
+++ b/lib/unitypes.h
@@ -0,0 +1,26 @@
+/* Elementary types for the GNU UniString library.
+   Copyright (C) 2002, 2005-2006 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _UNITYPES_H
+#define _UNITYPES_H
+
+/* Get uint8_t, uint16_t, uint32_t.  */
+#include <stdint.h>
+
+/* Type representing a Unicode character.  */
+typedef uint32_t ucs4_t;
+
+#endif /* _UNITYPES_H */
diff --git a/libguile/deprecated.c b/libguile/deprecated.c
index 00a6a98..af30a7c 100644
--- a/libguile/deprecated.c
+++ b/libguile/deprecated.c
@@ -1086,9 +1086,8 @@ SCM_DEFINE (scm_gentemp, "gentemp", 0, 2, 0,
     {
       SCM_VALIDATE_STRING (1, prefix);
       len = scm_i_string_length (prefix);
-      if (len > MAX_PREFIX_LENGTH)
-       name = SCM_MUST_MALLOC (MAX_PREFIX_LENGTH + SCM_INTBUFLEN);
-      strncpy (name, scm_i_string_chars (prefix), len);
+      name = scm_to_locale_stringn (prefix, (size_t *)(&len));
+      name = scm_realloc (name, len + SCM_INTBUFLEN);
     }
 
   if (SCM_UNBNDP (obarray))
@@ -1110,7 +1109,7 @@ SCM_DEFINE (scm_gentemp, "gentemp", 0, 2, 0,
                                         obarray,
                                         0);
     if (name != buf)
-      scm_must_free (name);
+      free (name);
     return SCM_CAR (vcell);
   }
 }
diff --git a/libguile/ports.c b/libguile/ports.c
index 7f8dea6..275e044 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -1016,6 +1016,8 @@ scm_lfwrite_substr (SCM str, size_t start, size_t end, 
SCM port)
   scm_t_port *pt = SCM_PTAB_ENTRY (port);
   scm_t_ptob_descriptor *ptob = &scm_ptobs[SCM_PTOBNUM (port)];
   scm_t_wchar p;
+  char *buf;
+  size_t len;
 
   if (pt->rw_active == SCM_PORT_READ)
     scm_end_input (port);
@@ -1024,11 +1026,13 @@ scm_lfwrite_substr (SCM str, size_t start, size_t end, 
SCM port)
     end = size;
   size = end - start;
 
-  ptob->write (port, scm_i_string_chars (str) + start, size);
+  buf = scm_to_locale_stringn (scm_c_substring (str, start, end), &len);
+  ptob->write (port, buf, len);
+  free (buf);
 
   for (i = 0; i < size; i++) 
     {
-      p = scm_i_string_ref_to_wchar (str, i);
+      p = scm_i_string_ref_to_wchar (str, i + start);
       update_port_lf (p, port);
     }
 
diff --git a/libguile/posix.c b/libguile/posix.c
index 35a610a..fe5f8b3 100644
--- a/libguile/posix.c
+++ b/libguile/posix.c
@@ -23,6 +23,7 @@
 
 #include <stdio.h>
 #include <errno.h>
+#include <uniconv.h>
 
 #include "libguile/_scm.h"
 #include "libguile/dynwind.h"
@@ -1626,7 +1627,11 @@ SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
            "Otherwise the specified locale category is set to the string\n"
            "@var{locale} and the new value is returned as a\n"
            "system-dependent string.  If @var{locale} is an empty string,\n"
-           "the locale will be set using environment variables.")
+           "the locale will be set using environment variables.\n"
+           "\n"
+           "When the locale is changed, the character encoding of the new\n"
+           "locale (UTF-8, ISO-8859-1, etc.) is used on all subsequent port\n"
+           "input and output.\n")
 #define FUNC_NAME s_scm_setlocale
 {
   int c_category;
@@ -1660,6 +1665,7 @@ SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
       SCM_SYSERROR;
     }
 
+  scm_i_port_encoding = locale_charset ();
   /* Recompute the standard SRFI-14 character sets in a locale-dependent
      (actually charset-dependent) way.  */
   scm_srfi_14_compute_char_sets ();
@@ -1670,6 +1676,30 @@ SCM_DEFINE (scm_setlocale, "setlocale", 1, 1, 0,
 #undef FUNC_NAME
 #endif /* HAVE_SETLOCALE */
 
+const char const scm_i_binary_locale[] = "ISO-8859-1";
+
+SCM_DEFINE (scm_setbinary, "setbinary", 0, 0, 0,
+           (void),
+           "Sets the behavior of all port I/O to treat data as 8-bit\n"
+           "clean bytes with no character encoding.\n" 
+           "This is the default behavior at startup.\n"
+           "Calling @code{setlocale} will modify the character encoding.\n"
+           "Thus, the procedure @code{setbinary} can be used to\n"
+           "clear it.\n"
+           "\n"
+           "In practice, @code{setbinary} sets the port character encoding\n"
+           "to ISO-8859-1: an 8-bit character encoding that does not modify\n"
+           "binary data when it is input or output\n"
+           "\n"
+           "After @code{setbinary} has been called, subsequent calls to \n"
+           "@code{setlocale} will, again, modify the character encoding.\n")
+#define FUNC_NAME s_scm_set_binary
+{
+  scm_i_port_encoding = scm_i_binary_locale;
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
 #ifdef HAVE_MKNOD
 SCM_DEFINE (scm_mknod, "mknod", 4, 0, 0,
             (SCM path, SCM type, SCM perms, SCM dev),
diff --git a/libguile/posix.h b/libguile/posix.h
index 6d282e0..b0873b6 100644
--- a/libguile/posix.h
+++ b/libguile/posix.h
@@ -73,6 +73,7 @@ SCM_API SCM scm_access (SCM path, SCM how);
 SCM_API SCM scm_getpid (void);
 SCM_API SCM scm_putenv (SCM str);
 SCM_API SCM scm_setlocale (SCM category, SCM locale);
+SCM_API SCM scm_setbinary (void);
 SCM_API SCM scm_mknod (SCM path, SCM type, SCM perms, SCM dev);
 SCM_API SCM scm_nice (SCM incr);
 SCM_API SCM scm_sync (void);
diff --git a/libguile/strings.c b/libguile/strings.c
index 0857a0e..91ed0d7 100644
--- a/libguile/strings.c
+++ b/libguile/strings.c
@@ -23,6 +23,8 @@
 
 #include <string.h>
 #include <stdio.h>
+#include <uniconv.h>
+#include <unistr.h>
 
 #include "libguile/_scm.h"
 #include "libguile/chars.h"
@@ -31,7 +33,9 @@
 #include "libguile/deprecation.h"
 #include "libguile/validate.h"
 #include "libguile/dynwind.h"
+#include "libguile/eq.h"
 
+#include "striconveh.h"
 
 
 /* {Strings}
@@ -68,10 +72,12 @@
 
 #define STRINGBUF_F_SHARED      0x100
 #define STRINGBUF_F_INLINE      0x200
+#define STRINGBUF_F_WIDE        0x400
 
 #define STRINGBUF_TAG           scm_tc7_stringbuf
 #define STRINGBUF_SHARED(buf)   (SCM_CELL_WORD_0(buf) & STRINGBUF_F_SHARED)
 #define STRINGBUF_INLINE(buf)   (SCM_CELL_WORD_0(buf) & STRINGBUF_F_INLINE)
+#define STRINGBUF_WIDE(buf)     (SCM_CELL_WORD_0(buf) & STRINGBUF_F_WIDE)
 
 #define STRINGBUF_OUTLINE_CHARS(buf)   ((char *)SCM_CELL_WORD_1(buf))
 #define STRINGBUF_OUTLINE_LENGTH(buf)  (SCM_CELL_WORD_2(buf))
@@ -81,6 +87,7 @@
 #define STRINGBUF_CHARS(buf)  (STRINGBUF_INLINE (buf) \
                                ? STRINGBUF_INLINE_CHARS (buf) \
                                : STRINGBUF_OUTLINE_CHARS (buf))
+#define STRINGBUF_WIDE_CHARS(buf) ((scm_t_wchar *)SCM_CELL_WORD_1(buf))
 #define STRINGBUF_LENGTH(buf) (STRINGBUF_INLINE (buf) \
                                ? STRINGBUF_INLINE_LENGTH (buf) \
                                : STRINGBUF_OUTLINE_LENGTH (buf))
@@ -125,6 +132,24 @@ make_stringbuf (size_t len)
     }
 }
 
+static SCM
+make_wide_stringbuf (size_t len)
+{
+  scm_t_wchar *mem;
+  
+#if SCM_DEBUG_STRINGS
+  if (len < 1000)
+    lenhist[len]++;
+  else
+    lenhist[1000]++;
+#endif
+
+  mem = scm_gc_malloc (sizeof(scm_t_wchar) * (len+1), "string");
+  mem[len] = 0;
+  return scm_double_cell (STRINGBUF_TAG | STRINGBUF_F_WIDE, (scm_t_bits) mem,
+                         (scm_t_bits) len, (scm_t_bits) 0);
+}
+
 /* Return a new stringbuf whose underlying storage consists of the LEN+1
    octets pointed to by STR (the last octet is zero).  */
 SCM
@@ -146,8 +171,56 @@ void
 scm_i_stringbuf_free (SCM buf)
 {
   if (!STRINGBUF_INLINE (buf))
-    scm_gc_free (STRINGBUF_OUTLINE_CHARS (buf),
-                STRINGBUF_OUTLINE_LENGTH (buf) + 1, "string");
+    {
+      if (!STRINGBUF_WIDE (buf))
+       scm_gc_free (STRINGBUF_OUTLINE_CHARS (buf),
+                    STRINGBUF_OUTLINE_LENGTH (buf) + 1, "string");
+      else
+       scm_gc_free (STRINGBUF_OUTLINE_CHARS (buf),
+                    sizeof (scm_t_wchar) * (STRINGBUF_OUTLINE_LENGTH (buf) + 
1),
+                    "string");
+    }
+
+}
+
+static void
+widen_stringbuf (SCM buf)
+{
+  size_t i, len;
+  scm_t_wchar *mem;
+
+  if (STRINGBUF_WIDE (buf))
+    return;
+
+  if (STRINGBUF_INLINE (buf))
+    {
+      len = STRINGBUF_INLINE_LENGTH (buf);
+
+      mem = scm_gc_malloc (sizeof (scm_t_wchar) * (len+1), "string");
+      for (i = 0; i < len; i ++)
+         mem[i] = (scm_t_wchar) (unsigned char) STRINGBUF_INLINE_CHARS 
(buf)[i];
+      mem[len] = 0;
+
+      SCM_SET_CELL_WORD_0 (buf, SCM_CELL_WORD_0 (buf) ^ STRINGBUF_F_INLINE);
+      SCM_SET_CELL_WORD_0 (buf, SCM_CELL_WORD_0 (buf) | STRINGBUF_F_WIDE);
+      SCM_SET_CELL_WORD_1 (buf, mem);
+      SCM_SET_CELL_WORD_2 (buf, len);
+    }
+  else
+    {
+      len = STRINGBUF_OUTLINE_LENGTH (buf);
+
+      mem = scm_gc_malloc (sizeof (scm_t_wchar) * (len+1), "string");
+      for (i = 0; i < len; i ++)
+         mem[i] = (scm_t_wchar) (unsigned char) STRINGBUF_OUTLINE_CHARS 
(buf)[i];
+      mem[len] = 0;
+
+      scm_gc_free (STRINGBUF_OUTLINE_CHARS (buf), len + 1, "string");
+
+      SCM_SET_CELL_WORD_0 (buf, SCM_CELL_WORD_0 (buf) | STRINGBUF_F_WIDE);
+      SCM_SET_CELL_WORD_1 (buf, mem);
+      SCM_SET_CELL_WORD_2 (buf, len);
+    }
 }
 
 scm_i_pthread_mutex_t stringbuf_write_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
@@ -182,6 +255,12 @@ scm_i_pthread_mutex_t stringbuf_write_mutex = 
SCM_I_PTHREAD_MUTEX_INITIALIZER;
 
 #define IS_SH_STRING(str)   (SCM_CELL_TYPE(str)==SH_STRING_TAG)
 
+/* This determines how conversions handle unconvertible characters.  */
+enum iconv_ilseq_handler scm_conversion_strategy;
+
+/* This is the current locale encoding.  */
+const char *scm_i_port_encoding;
+
 SCM
 scm_i_make_string (size_t len, char **charsp)
 {
@@ -194,6 +273,18 @@ scm_i_make_string (size_t len, char **charsp)
   return res;
 }
 
+SCM
+scm_i_make_wide_string (size_t len, scm_t_wchar **charsp)
+{
+  SCM buf = make_wide_stringbuf (len);
+  SCM res;
+  if (charsp)
+    *charsp = STRINGBUF_WIDE_CHARS (buf);
+  res = scm_double_cell (STRING_TAG, SCM_UNPACK(buf),
+                        (scm_t_bits)0, (scm_t_bits) len);
+  return res;
+}
+
 static void
 validate_substring_args (SCM str, size_t start, size_t end)
 {
@@ -252,9 +343,21 @@ scm_i_substring_copy (SCM str, size_t start, size_t end)
   SCM buf, my_buf;
   size_t str_start;
   get_str_buf_start (&str, &buf, &str_start);
-  my_buf = make_stringbuf (len);
-  memcpy (STRINGBUF_CHARS (my_buf),
-         STRINGBUF_CHARS (buf) + str_start + start, len);
+  if (scm_i_is_narrow_string (str))
+    {
+      my_buf = make_stringbuf (len);
+      memcpy (STRINGBUF_CHARS (my_buf),
+             STRINGBUF_CHARS (buf) + str_start + start, len);
+    }
+  else
+    {
+      my_buf = make_wide_stringbuf (len);
+      u32_cpy ((scm_t_uint32 *) STRINGBUF_WIDE_CHARS (my_buf),
+              (scm_t_uint32 *) STRINGBUF_WIDE_CHARS (buf) + str_start + start, 
+              len);
+      /* Even though this string is wide, the substring may be narrow.
+        Consider adding code to narrow string.  */
+    }
   scm_remember_upto_here_1 (buf);
   return scm_double_cell (STRING_TAG, SCM_UNPACK(my_buf),
                          (scm_t_bits)0, (scm_t_bits) len);
@@ -329,13 +432,43 @@ scm_i_string_length (SCM str)
   return STRING_LENGTH (str);
 }
 
+int
+scm_i_is_narrow_string (SCM str)
+{
+  return !STRINGBUF_WIDE (STRING_STRINGBUF (str));
+}
+
 const char *
 scm_i_string_chars (SCM str)
 {
   SCM buf;
   size_t start;
   get_str_buf_start (&str, &buf, &start);
-  return STRINGBUF_CHARS (buf) + start;
+  if (scm_i_is_narrow_string (str))
+    return STRINGBUF_CHARS (buf) + start;
+  else
+    scm_misc_error (NULL, "Invalid access to chars of wide string: ~s",
+                   scm_list_1 (str));
+    return NULL;
+}
+
+const scm_t_wchar *
+scm_i_string_wide_chars (SCM str)
+{
+  SCM buf;
+  size_t start;
+
+#if SCM_DEBUG_STRINGS
+  if (!IS_STRING (str)) 
+    scm_wrong_type_arg ("scm_i_string_wide_chars", 0, str);
+#endif
+
+  get_str_buf_start (&str, &buf, &start);
+  if (!scm_i_is_narrow_string (str))
+    return STRINGBUF_WIDE_CHARS (buf) + start;
+  else
+    scm_misc_error (NULL, "Invalid access to chars of narrow string: ~s",
+                   scm_list_1 (str));
 }
 
 char *
@@ -348,6 +481,10 @@ scm_i_string_writable_chars (SCM orig_str)
   if (IS_RO_STRING (str))
     scm_misc_error (NULL, "string is read-only: ~s", scm_list_1 (orig_str));
 
+  if (!scm_i_is_narrow_string (orig_str))
+    scm_misc_error (NULL, "Invalid access to writable chars of wide string: 
~s",
+                   scm_list_1 (orig_str));
+
   scm_i_pthread_mutex_lock (&stringbuf_write_mutex);
   if (STRINGBUF_SHARED (buf))
     {
@@ -374,76 +511,188 @@ scm_i_string_writable_chars (SCM orig_str)
       scm_i_pthread_mutex_lock (&stringbuf_write_mutex);
     }
 
-  return STRINGBUF_CHARS (buf) + start;
+    return STRINGBUF_CHARS (buf) + start;
 }
 
-void
-scm_i_string_stop_writing (void)
+static scm_t_wchar *
+scm_i_string_writable_wide_chars (SCM orig_str)
 {
-  scm_i_pthread_mutex_unlock (&stringbuf_write_mutex);
+  SCM buf, str = orig_str;
+  size_t start;
+
+#if SCM_DEBUG_STRINGS
+  if (!IS_STRING (orig_str)) 
+    scm_wrong_type_arg ("scm_i_string_writable_wide_chars", 0, orig_str);
+#endif
+
+  get_str_buf_start (&str, &buf, &start);
+  if (IS_RO_STRING (str))
+    scm_misc_error (NULL, "string is read-only: ~s", scm_list_1 (orig_str));
+
+  if (scm_i_is_narrow_string (orig_str))
+    scm_misc_error (NULL, "Invalid access to writable chars of narrow string: 
~s",
+                   scm_list_1 (orig_str));
+
+  scm_i_pthread_mutex_lock (&stringbuf_write_mutex);
+  if (STRINGBUF_SHARED (buf))
+    {
+      /* Clone stringbuf.  For this, we put all threads to sleep.
+       */
+
+      size_t len = STRING_LENGTH (str);
+      SCM new_buf;
+
+      scm_i_pthread_mutex_unlock (&stringbuf_write_mutex);
+
+      new_buf = make_wide_stringbuf (len);
+      u32_cpy ((scm_t_uint32 *) STRINGBUF_WIDE_CHARS (new_buf),
+              (scm_t_uint32 *) STRINGBUF_WIDE_CHARS (buf) + STRING_START (str),
+              len);
+
+      scm_i_thread_put_to_sleep ();
+      SET_STRING_STRINGBUF (str, new_buf);
+      start -= STRING_START (str);
+      SET_STRING_START (str, 0);
+      scm_i_thread_wake_up ();
+
+      buf = new_buf;
+
+      scm_i_pthread_mutex_lock (&stringbuf_write_mutex);
+    }
+
+  return STRINGBUF_WIDE_CHARS (buf) + start;
 }
 
-/* Return true if string only contains Latin 1 characters */
-int
-scm_i_is_narrow_string (SCM str)
+void
+scm_i_string_stop_writing (void)
 {
-  return 1;
+  scm_i_pthread_mutex_unlock (&stringbuf_write_mutex);
 }
 
 /* Return the Xth character is C.  */
 SCM
 scm_i_string_ref(SCM str, size_t x)
 {
-  return SCM_MAKE_CHAR (scm_i_string_chars (str)[x]);
+  if (scm_i_is_narrow_string (str))
+    return SCM_MAKE_CHAR (scm_i_string_chars (str)[x]);
+  else
+    return SCM_MAKE_CHAR (scm_i_string_wide_chars (str)[x]);
 }
 
 scm_t_wchar
 scm_i_string_ref_to_wchar (SCM str, size_t x)
 {
-  return (scm_t_wchar) (unsigned char) (scm_i_string_chars (str)[x]);
+  if (scm_i_is_narrow_string (str))
+    return (scm_t_wchar) (unsigned char) (scm_i_string_chars (str)[x]);
+  else
+    return scm_i_string_wide_chars (str)[x];
 }
 
 int
 scm_i_string_ref_eq_char (SCM str, size_t x, char c)
 {
-  return (c == scm_i_string_chars (str)[x]);
+  if (scm_i_is_narrow_string (str))
+    return (c == scm_i_string_chars (str)[x]);
+  else
+    return ((unsigned char) c == scm_i_string_wide_chars (str) [x]);
 }
 
 int
 scm_i_string_ref_eq_wchar (SCM str, size_t x, scm_t_wchar c)
 {
-  return (c == (scm_t_wchar) (unsigned char) scm_i_string_chars (str)[x]);
+  if (scm_i_is_narrow_string (str))
+    return (c == (scm_t_wchar) (unsigned char) scm_i_string_chars (str)[x]);
+  else
+    return (c == scm_i_string_wide_chars (str)[x]);
 }
 
 /* Returns the index of the first char in STR that matches C.  */
-int 
-scm_i_string_contains_char (SCM str, char c)
+int
+scm_i_string_contains_char (SCM str, char ch)
 {
-  char *ptr;
-  ptr = memchr (scm_i_string_chars (str), c, scm_i_string_length (str));
-  if (ptr == NULL)
-    return 0;
+  size_t i;
+  size_t len = scm_i_string_length (str);
+
+#if SCM_DEBUG_STRINGS
+  if (!IS_STRING (str)) 
+    scm_wrong_type_arg ("scm_i_symbol_ref_eq_char", 0, str);
+#endif
+
+  i = 0;
+  if (scm_i_is_narrow_string (str))
+    {
+      while (i < len)
+       {
+         if (scm_i_string_chars (str)[i] == ch)
+           return 1;
+         i++;
+       }
+    }
   else
-    return 1;
+    {
+      while (i < len)
+       {
+         if (scm_i_string_wide_chars (str)[i] 
+             == (scm_t_wchar) (unsigned char) ch)
+           return 1;
+         i++;
+       }
+    }
+  return 0;
 }
 
 int 
 scm_i_string_strcmp (SCM sstr, size_t start_x, const char *cstr)
 {
-  const char *a = scm_i_string_chars (sstr) + start_x;
-  const char *b = cstr;
-  return strncmp (a, b, strlen(b));
+  if (scm_i_is_narrow_string (sstr))
+    {
+      const char *a = scm_i_string_chars (sstr) + start_x;
+      const char *b = cstr;
+      return strncmp (a, b, strlen(b));
+    }
+  else
+    {
+      size_t i;
+      const scm_t_wchar *a = scm_i_string_wide_chars (sstr) + start_x;
+      const char *b = cstr;
+      for (i = 0; i < strlen (b); i++)
+       {
+         if (a[i] != (unsigned char) b[i])
+           return 1;
+       }
+    }
+  return 0;
 }
 
 void
-scm_i_string_set (SCM str, size_t x, SCM chr)
+scm_i_string_set (SCM str, size_t p, SCM chr)
 {
-  char *dst = scm_i_string_writable_chars (str);
-  dst[x] = SCM_CHAR (chr);
-  scm_i_string_stop_writing ();
+  scm_t_wchar c;
+
+  c = SCM_CHAR (chr);
+
+  scm_i_string_set_from_wchar (str, p, c);
 }
-#undef FUNC_NAME
 
+void
+scm_i_string_set_from_wchar (SCM str, size_t p, scm_t_wchar chr)
+{
+  if (chr > 0xFF && scm_i_is_narrow_string (str))
+    widen_stringbuf (STRING_STRINGBUF (str));
+
+  if (scm_i_is_narrow_string (str))
+    {
+      char *dst = scm_i_string_writable_chars (str);
+      dst[p] = (char) (unsigned char) chr;
+      scm_i_string_stop_writing ();
+    }
+  else
+    {
+      scm_t_wchar *dst = scm_i_string_writable_wide_chars (str);
+      dst[p] = chr;
+      scm_i_string_stop_writing ();
+    }
+}
 
 
 /* Symbols.
@@ -480,10 +729,20 @@ scm_i_make_symbol (SCM name, scm_t_bits flags,
   else
     {
       /* make new buf. */
-      SCM new_buf = make_stringbuf (length);
-      memcpy (STRINGBUF_CHARS (new_buf),
-             STRINGBUF_CHARS (buf) + start, length);
-      buf = new_buf;
+      if (scm_i_is_narrow_string (name))
+       {
+         SCM new_buf = make_stringbuf (length);
+         memcpy (STRINGBUF_CHARS (new_buf),
+                 STRINGBUF_CHARS (buf) + start, length);
+         buf = new_buf;
+       }
+      else
+       {
+         SCM new_buf = make_wide_stringbuf (length);
+         u32_cpy ((scm_t_uint32 *) STRINGBUF_WIDE_CHARS (new_buf),
+                  (scm_t_uint32 *) STRINGBUF_WIDE_CHARS (buf) + start, length);
+         buf = new_buf;
+       }
     }
   return scm_double_cell (scm_tc7_symbol | flags, SCM_UNPACK (buf),
                          (scm_t_bits) hash, SCM_UNPACK (props));
@@ -528,11 +787,39 @@ scm_c_symbol_length (SCM sym)
 }
 #undef FUNC_NAME
 
+int
+scm_i_is_narrow_symbol (SCM sym)
+{
+  SCM buf;
+
+  buf = SYMBOL_STRINGBUF (sym);
+  return !STRINGBUF_WIDE (buf);
+}
+
 const char *
 scm_i_symbol_chars (SCM sym)
 {
-  SCM buf = SYMBOL_STRINGBUF (sym);
-  return STRINGBUF_CHARS (buf);
+  SCM buf;
+
+  buf = SYMBOL_STRINGBUF (sym);
+  if (!STRINGBUF_WIDE (buf))
+    return STRINGBUF_CHARS (buf);
+  else
+    scm_misc_error (NULL, "Invalid access of chars of a wide symbol ~S", 
+                   scm_list_1 (sym));
+}
+
+const scm_t_wchar *
+scm_i_symbol_wide_chars (SCM sym)
+{
+  SCM buf;
+
+  buf = SYMBOL_STRINGBUF (sym);
+  if (STRINGBUF_WIDE (buf))
+    return STRINGBUF_WIDE_CHARS (buf);
+  else
+    scm_misc_error (NULL, "Invalid access of chars of a narrow symbol ~S", 
+                   scm_list_1 (sym));
 }
 
 SCM
@@ -609,6 +896,10 @@ SCM_DEFINE (scm_sys_string_dump, "%string-dump", 1, 0, 0,
   fprintf (stderr, "%p:\n", str);
   fprintf (stderr, " start: %u\n", STRING_START (str));
   fprintf (stderr, " len:   %u\n", STRING_LENGTH (str));
+  if (scm_i_is_narrow_string (str))
+    fprintf (stderr, " format: narrow\n");
+  else
+    fprintf (stderr, " format: wide\n");
   if (IS_SH_STRING (str))
     {
       fprintf (stderr, " string: %p\n", SH_STRING_STRING (str));
@@ -619,9 +910,20 @@ SCM_DEFINE (scm_sys_string_dump, "%string-dump", 1, 0, 0,
     {
       SCM buf = STRING_STRINGBUF (str);
       fprintf (stderr, " buf:   %p\n", buf);
-      fprintf (stderr, "  chars:  %p\n", STRINGBUF_CHARS (buf));
+      if (scm_i_is_narrow_string (str))
+       fprintf (stderr, "  chars:  %p\n", STRINGBUF_CHARS (buf));
+      else
+       fprintf (stderr, "  chars:   %p\n", STRINGBUF_WIDE_CHARS (buf));
       fprintf (stderr, "  length: %u\n", STRINGBUF_LENGTH (buf));
-      fprintf (stderr, "  flags: %x\n", (SCM_CELL_WORD_0 (buf) & 0x300));
+      if (STRINGBUF_SHARED (buf))
+       fprintf (stderr, "  shared: true\n");
+      else
+       fprintf (stderr, "  shared: false\n");
+      if (STRINGBUF_INLINE (buf))
+       fprintf (stderr, "  inline: true\n");
+      else
+       fprintf (stderr, "  inline: false\n");
+
     }
   return SCM_UNSPECIFIED;
 }
@@ -635,12 +937,23 @@ SCM_DEFINE (scm_sys_symbol_dump, "%symbol-dump", 1, 0, 0,
   SCM_VALIDATE_SYMBOL (1, sym);
   fprintf (stderr, "%p:\n", sym);
   fprintf (stderr, " hash: %lu\n", scm_i_symbol_hash (sym));
+  if (scm_i_is_narrow_symbol (sym))
+    fprintf (stderr, " format: narrow\n");
+  else
+    fprintf (stderr, " format: wide\n");
   {
     SCM buf = SYMBOL_STRINGBUF (sym);
     fprintf (stderr, " buf: %p\n", buf);
-    fprintf (stderr, "  chars:  %p\n", STRINGBUF_CHARS (buf));
+    if (scm_i_is_narrow_symbol (sym))
+      fprintf (stderr, "  chars:  %p\n", STRINGBUF_CHARS (buf));
+    else
+      fprintf (stderr, "  chars:  %p\n", STRINGBUF_WIDE_CHARS (buf));
     fprintf (stderr, "  length: %u\n", STRINGBUF_LENGTH (buf));
-    fprintf (stderr, "  shared: %u\n", STRINGBUF_SHARED (buf));
+    if (STRINGBUF_SHARED (buf))
+      fprintf (stderr, "  shared: true\n");
+    else
+      fprintf (stderr, "  shared: false\n");
+      
   }
   return SCM_UNSPECIFIED;
 }
@@ -664,6 +977,45 @@ SCM_DEFINE (scm_sys_stringbuf_hist, "%stringbuf-hist", 0, 
0, 0,
 
 
 
+SCM_DEFINE (scm_set_conversion_error_behavior_x, 
"set-conversion-error-behavior!",
+           1, 0, 0, 
+           (SCM sym),
+           "Sets the behavior of the interpreter when outputting a character\n"
+           "that is not representable in the current locale.\n"
+           "@var{sym} can be either @code{'error}, @code{'questionmark}, or\n"
+           "@code{'escape}.  If it is @code{'error}, an error will be thrown\n"
+           "when an unconvertible character is encountered.  If it is\n"
+           "@code{'questionmark}, then unconvertiable characters will \n"
+           "appear as question marks on output.  If it is @code{'escape},\n"
+           "it will appear as a hex escape when output.\n")
+#define FUNC_NAME s_scm_set_conversion_error_behavior_x
+{
+  static SCM err;
+  static SCM qm;
+  static SCM esc;
+  static int first = 1;
+  
+  if (first)
+    {
+      err = scm_from_locale_symbol ("error");
+      qm = scm_from_locale_symbol ("questionmark");
+      esc = scm_from_locale_symbol ("error");
+      first = 0;
+    }
+
+  if (scm_eq_p (sym, err))
+    scm_conversion_strategy = iconveh_error;
+  else if (scm_eq_p (sym, qm))
+    scm_conversion_strategy = iconveh_question_mark;
+  else if (scm_eq_p (sym, esc))
+    scm_conversion_strategy = iconveh_escape_sequence;
+  else
+    SCM_MISC_ERROR ("unknown conversion behavior ~s", scm_list_1 (sym));
+
+  return SCM_UNSPECIFIED;
+}
+#undef FUNC_NAME
+
 SCM_DEFINE (scm_string_p, "string?", 1, 0, 0, 
            (SCM obj),
            "Return @code{#t} if @var{obj} is a string, else @code{#f}.")
@@ -685,22 +1037,23 @@ SCM_DEFINE (scm_string, "string", 0, 0, 1,
 {
   SCM result;
   size_t len;
-  char *data;
+  size_t p = 0;
 
   {
     long i = scm_ilength (chrs);
 
     SCM_ASSERT (i >= 0, chrs, SCM_ARG1, FUNC_NAME);
-    len = i;
+    len = (size_t) i;
   }
 
-  result = scm_i_make_string (len, &data);
+  result = scm_i_make_string (len, NULL);
   while (len > 0 && scm_is_pair (chrs))
     {
       SCM elt = SCM_CAR (chrs);
 
       SCM_VALIDATE_CHAR (SCM_ARGn, elt);
-      *data++ = SCM_CHAR (elt);
+      scm_i_string_set (result, p, elt);
+      p++;
       chrs = SCM_CDR (chrs);
       len--;
     }
@@ -729,13 +1082,14 @@ SCM
 scm_c_make_string (size_t len, SCM chr)
 #define FUNC_NAME NULL
 {
-  char *dst;
-  SCM res = scm_i_make_string (len, &dst);
+  size_t p;
+  SCM res = scm_i_make_string (len, NULL);
 
   if (!SCM_UNBNDP (chr))
     {
       SCM_VALIDATE_CHAR (0, chr);
-      memset (dst, SCM_CHAR (chr), len);
+      for (p = 0; p < len; p ++)
+       scm_i_string_set (res, p, chr);
     }
 
   return res;
@@ -777,7 +1131,10 @@ SCM_DEFINE (scm_string_ref, "string-ref", 2, 0, 0,
   else
     scm_out_of_range (NULL, k);
 
-  return SCM_MAKE_CHAR (scm_i_string_chars (str)[idx]);
+  if (scm_i_is_narrow_string (str))
+    return SCM_MAKE_CHAR (scm_i_string_chars (str)[idx]);
+  else
+    return SCM_MAKE_CHAR (scm_i_string_wide_chars (str)[idx]);
 }
 #undef FUNC_NAME
 
@@ -786,7 +1143,11 @@ scm_c_string_ref (SCM str, size_t p)
 {
   if (p >= scm_i_string_length (str))
     scm_out_of_range (NULL, scm_from_size_t (p));
-  return SCM_MAKE_CHAR (scm_i_string_chars (str)[p]);
+  if (scm_i_is_narrow_string (str))
+    return SCM_MAKE_CHAR (scm_i_string_chars (str)[p]);
+  else
+    return SCM_MAKE_CHAR (scm_i_string_wide_chars (str)[p]);
+
 }
 
 SCM_DEFINE (scm_string_set_x, "string-set!", 3, 0, 0,
@@ -808,11 +1169,8 @@ SCM_DEFINE (scm_string_set_x, "string-set!", 3, 0, 0,
     scm_out_of_range (NULL, k);
 
   SCM_VALIDATE_CHAR (3, chr);
-  {
-    char *dst = scm_i_string_writable_chars (str);
-    dst[idx] = SCM_CHAR (chr);
-    scm_i_string_stop_writing ();
-  }
+  scm_i_string_set (str, idx, chr);
+
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
@@ -822,11 +1180,8 @@ scm_c_string_set_x (SCM str, size_t p, SCM chr)
 {
   if (p >= scm_i_string_length (str))
     scm_out_of_range (NULL, scm_from_size_t (p));
-  {
-    char *dst = scm_i_string_writable_chars (str);
-    dst[p] = SCM_CHAR (chr);
-    scm_i_string_stop_writing ();
-  }
+
+  scm_i_string_set (str, p, chr);
 }
 
 SCM_DEFINE (scm_substring, "substring", 2, 1, 0,
@@ -932,26 +1287,44 @@ SCM_DEFINE (scm_string_append, "string-append", 0, 0, 1,
 #define FUNC_NAME s_scm_string_append
 {
   SCM res;
-  size_t i = 0;
+  size_t len = 0;
+  int wide = 0;
   SCM l, s;
   char *data;
+  scm_t_wchar *wdata;
 
   SCM_VALIDATE_REST_ARGUMENT (args);
   for (l = args; !scm_is_null (l); l = SCM_CDR (l)) 
     {
       s = SCM_CAR (l);
       SCM_VALIDATE_STRING (SCM_ARGn, s);
-      i += scm_i_string_length (s);
+      len += scm_i_string_length (s);
+      if (!scm_i_is_narrow_string (s))
+       wide = 1;
     }
-  res = scm_i_make_string (i, &data);
+
+  if (!wide)
+    res = scm_i_make_string (len, &data);
+  else
+    res = scm_i_make_wide_string (len, &wdata);
+
   for (l = args; !scm_is_null (l); l = SCM_CDR (l)) 
     {
-      size_t len;
       s = SCM_CAR (l);
       SCM_VALIDATE_STRING (SCM_ARGn, s);
       len = scm_i_string_length (s);
-      memcpy (data, scm_i_string_chars (s), len);
-      data += len;
+      if (!wide)
+       {
+         memcpy (data, scm_i_string_chars (s), len);
+         data += len;
+       }
+      else
+       {
+         u32_cpy ((scm_t_uint32 *) wdata, 
+                  (scm_t_uint32 *) scm_i_string_wide_chars (s), 
+                  len);
+         wdata += len;
+       }
       scm_remember_upto_here_1 (s);
     }
   return res;
@@ -968,12 +1341,74 @@ SCM
 scm_from_locale_stringn (const char *str, size_t len)
 {
   SCM res;
+  scm_t_wchar *u32, *wdst;
+  size_t u32len, i;
+  int wide = 0;
   char *dst;
 
   if (len == (size_t)-1)
     len = strlen (str);
-  res = scm_i_make_string (len, &dst);
-  memcpy (dst, str, len);
+
+  if (len == 0)
+    return scm_nullstr;
+
+  if (scm_i_port_encoding == NULL
+      || strcmp(scm_i_port_encoding, "ISO-8859-1") == 0)
+    {
+      res = scm_i_make_string (len, &dst);
+      memcpy (dst, str, len);
+      return res;
+    }
+
+  u32len = 0;
+  u32 = (scm_t_wchar *) u32_conv_from_encoding (scm_i_port_encoding,
+                                               scm_conversion_strategy,
+                                               str, len,
+                                               NULL,
+                                               NULL, &u32len);
+  
+  if (u32 == NULL)
+    {
+      if (errno == ENOMEM)     
+       scm_memory_error ("locale string conversion");
+      else
+       {
+         /* Input encoding error should only occur when there
+            are invalid sequences in the input string. */
+         SCM escaped_str;
+         /* Try to generate an string for the error message. */
+         /* FIXME: want to make a true ASCII string with hex escapes here. */
+         escaped_str = scm_i_make_string (len, &dst);
+         memcpy (dst, str, len);
+         scm_misc_error (NULL, "input locale conversion error from ~s: ~s",
+                         scm_list_2 (scm_from_locale_string 
(scm_i_port_encoding),
+                                     escaped_str));
+       }
+    }
+  
+  i = 0;
+  while (i < u32len)
+    if (u32[i++] > 0xFF)
+      {
+       wide = 1;
+       break;
+      }
+
+  if (!wide)
+    {
+      res = scm_i_make_string (u32len, &dst);
+      for (i = 0; i < u32len; i ++)
+       dst[i] = (char) (unsigned char) u32[i];
+      dst[u32len] = '\0';
+    }
+  else
+    {
+      res = scm_i_make_wide_string (u32len, &wdst);
+      u32_cpy ((scm_t_uint32 *) wdst, (scm_t_uint32 *) u32, u32len);
+      wdst[u32len] = 0;
+    }
+
+  free (u32);
   return res;
 }
 
@@ -1021,32 +1456,97 @@ scm_take_locale_string (char *str)
 char *
 scm_to_locale_stringn (SCM str, size_t *lenp)
 {
-  char *res;
-  size_t len;
+  char *buf;
+  size_t len, i;
+  int ret;
 
   if (!scm_is_string (str))
     scm_wrong_type_arg_msg (NULL, 0, str, "string");
-  len = scm_i_string_length (str);
-  res = scm_malloc (len + ((lenp==NULL)? 1 : 0));
-  memcpy (res, scm_i_string_chars (str), len);
+
   if (lenp == NULL)
-    {
-      res[len] = '\0';
-      if (strlen (res) != len)
-       {
-         free (res);
+    for (i = 0; i < scm_i_string_length (str); i++)
+      if (scm_i_string_ref_eq_char (str, i, '\0'))
          scm_misc_error (NULL,
                          "string contains #\\nul character: ~S",
                          scm_list_1 (str));
+         
+
+  buf = NULL;
+  len = 0;
+  if (scm_i_is_narrow_string (str))
+    {
+      ret = mem_iconveh (scm_i_string_chars (str), scm_i_string_length (str),
+                        "ISO-8859-1", scm_i_port_encoding,
+                        scm_conversion_strategy, NULL,
+                        &buf, &len);
+
+      if (ret != 0)
+       {
+         /* If there is a conversion error, try to generate an escaped
+            version of the string for the error message.  */
+         SCM escape_str;
+         if (scm_conversion_strategy != iconveh_escape_sequence)
+           ret = mem_iconveh (scm_i_string_chars (str), 
+                              scm_i_string_length (str),
+                              "ISO-8859-1", scm_i_port_encoding,
+                              iconveh_escape_sequence, NULL,
+                              &buf, &len);
+         if (ret == 0)
+           {
+             /* scm_unistring_escapes_to_guile_escapes (&buf, &len) */
+             escape_str = scm_from_locale_stringn (buf, len);
+             free (buf);
+             scm_misc_error (NULL, "output conversion error: ~s", scm_list_1 
(escape_str));
+           }
+         else
+           scm_misc_error (NULL, "output conversion error", SCM_EOL);
        }
     }
   else
+    {
+      buf = u32_conv_to_encoding (scm_i_port_encoding, 
+                                 scm_conversion_strategy,
+                                 (scm_t_uint32 *) scm_i_string_wide_chars 
(str), 
+                                 scm_i_string_length (str),
+                                 NULL,
+                                 NULL, &len);
+      if (buf == NULL)
+       {
+         /* If there is a conversion error, try to generate an escaped
+            version of the string for the error message.  */
+         SCM escape_str;
+         if (scm_conversion_strategy != iconveh_escape_sequence)
+           buf = u32_conv_to_encoding (scm_i_port_encoding, 
+                                       iconveh_escape_sequence,
+                                       (scm_t_uint32 *) 
scm_i_string_wide_chars (str), 
+                                       scm_i_string_length (str),
+                                       NULL,
+                                       NULL, &len);
+         if (buf != NULL)
+           {
+             /* scm_unistring_escapes_to_guile_escapes (&buf, &len) */
+             escape_str = scm_from_locale_stringn (buf, len);
+             free (buf);
+             scm_misc_error (NULL, "conversion error: ~s", scm_list_1 
(escape_str));
+           }
+         else
+           scm_misc_error (NULL, "conversion error", SCM_EOL);
+       }
+    }
+
+  if (lenp)
     *lenp = len;
+  else
+    {
+      buf = scm_realloc (buf, len+1);
+      buf[len] = '\0';
+    }
 
   scm_remember_upto_here_1 (str);
-  return res;
+  return buf;
 }
 
+
 char *
 scm_to_locale_string (SCM str)
 {
@@ -1063,11 +1563,16 @@ size_t
 scm_to_locale_stringbuf (SCM str, char *buf, size_t max_len)
 {
   size_t len;
+  char *result = NULL;
   
   if (!scm_is_string (str))
     scm_wrong_type_arg_msg (NULL, 0, str, "string");
-  len = scm_i_string_length (str);
-  memcpy (buf, scm_i_string_chars (str), (len > max_len)? max_len : len);
+  
+  result = scm_to_locale_stringn (str, &len);
+
+  memcpy (buf, result, (len > max_len) ? max_len : len);
+  free (result);
+
   scm_remember_upto_here_1 (str);
   return len;
 }
@@ -1207,8 +1712,13 @@ void
 scm_init_strings ()
 {
   scm_nullstr = scm_i_make_string (0, NULL);
+  scm_conversion_strategy = iconveh_question_mark;
 
-#include "libguile/strings.x"
+  /* Since, ISO-8859-1 is an 8-bit charset with the Unicode codepoints
+     0 to 255, it is effectively the same as doing no conversion on
+     input or output. */
+  scm_i_port_encoding = "ISO-8859-1"; 
+#include "libguile/strings.x" 
 }
 
 
diff --git a/libguile/strings.h b/libguile/strings.h
index 1a70a7c..08dd89c 100644
--- a/libguile/strings.h
+++ b/libguile/strings.h
@@ -76,6 +76,9 @@
      an error for for strings that are not null-terminated.
 */
 
+extern const char *scm_i_port_encoding;
+
+SCM_API SCM scm_set_conversion_error_behavior_x (SCM behavior);
 SCM_API SCM scm_string_p (SCM x);
 SCM_API SCM scm_string (SCM chrs);
 SCM_API SCM scm_make_string (SCM k, SCM chr);
@@ -114,12 +117,14 @@ SCM_API SCM scm_makfromstrs (int argc, char **argv);
 /* internal accessor functions.  Arguments must be valid. */
 
 SCM_INTERNAL SCM scm_i_make_string (size_t len, char **datap);
+SCM_INTERNAL SCM scm_i_make_wide_string (size_t len, scm_t_wchar **datap);
 SCM_INTERNAL SCM scm_i_substring (SCM str, size_t start, size_t end);
 SCM_INTERNAL SCM scm_i_substring_read_only (SCM str, size_t start, size_t end);
 SCM_INTERNAL SCM scm_i_substring_shared (SCM str, size_t start, size_t end);
 SCM_INTERNAL SCM scm_i_substring_copy (SCM str, size_t start, size_t end);
 SCM_INTERNAL size_t scm_i_string_length (SCM str);
 SCM_API /* FIXME: not internal */ const char *scm_i_string_chars (SCM str);
+SCM_API const scm_t_wchar *scm_i_string_wide_chars (SCM str);
 SCM_API /* FIXME: not internal */ char *scm_i_string_writable_chars (SCM str);
 SCM_INTERNAL void scm_i_string_stop_writing (void);
 SCM_INTERNAL int scm_i_is_narrow_string (SCM str);
@@ -130,6 +135,7 @@ SCM_INTERNAL int scm_i_string_ref_eq_wchar (SCM str, size_t 
x, scm_t_wchar c);
 SCM_INTERNAL int scm_i_string_contains_char (SCM str, char c);
 SCM_INTERNAL int scm_i_string_strcmp (SCM sstr, size_t start_x, const char 
*cstr);
 SCM_INTERNAL void scm_i_string_set (SCM str, size_t x, SCM chr);
+SCM_INTERNAL void scm_i_string_set_from_wchar (SCM str, size_t p, scm_t_wchar 
chr);
 
 /* internal functions related to symbols. */
 
@@ -142,7 +148,9 @@ SCM_INTERNAL SCM
 scm_i_c_take_symbol (char *name, size_t len,
                     scm_t_bits flags, unsigned long hash, SCM props);
 SCM_INTERNAL const char *scm_i_symbol_chars (SCM sym);
+SCM_INTERNAL const scm_t_wchar *scm_i_symbol_wide_chars (SCM sym);
 SCM_INTERNAL size_t scm_i_symbol_length (SCM sym);
+SCM_INTERNAL int scm_i_is_narrow_symbol (SCM str);
 SCM_INTERNAL SCM scm_i_symbol_substring (SCM sym, size_t start, size_t end);
 SCM_INTERNAL SCM scm_i_symbol_ref (SCM sym, size_t x);
 SCM_INTERNAL scm_t_wchar scm_i_symbol_ref_to_wchar (SCM sym, size_t x);
diff --git a/libguile/throw.c b/libguile/throw.c
index e0dda27..b971b69 100644
--- a/libguile/throw.c
+++ b/libguile/throw.c
@@ -22,6 +22,7 @@
 #endif
 
 #include <stdio.h>
+#include <unistdio.h>
 #include "libguile/_scm.h"
 #include "libguile/async.h"
 #include "libguile/smob.h"
@@ -743,8 +744,12 @@ scm_ithrow (SCM key, SCM args, int noreturn SCM_UNUSED)
        */
       fprintf (stderr, "throw from within critical section.\n");
       if (scm_is_symbol (key))
-       fprintf (stderr, "error key: %s\n", scm_i_symbol_chars (key));
-
+       {
+         if (scm_i_is_narrow_symbol (key))
+           fprintf (stderr, "error key: %s\n", scm_i_symbol_chars (key));
+         else
+           ulc_fprintf (stderr, "error key: %llU\n", scm_i_symbol_wide_chars 
(key));
+       }
       
       for (; scm_is_pair (s); s = scm_cdr (s), i++)
        {
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index 11c2a89..869f4b8 100644
--- a/m4/gnulib-cache.m4
+++ b/m4/gnulib-cache.m4
@@ -15,7 +15,7 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 
--doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl --libtool 
--macro-prefix=gl --no-vc-files alloca-opt autobuild count-one-bits extensions 
full-read full-write libunistring strcase strftime
+#   gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 
--doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl --libtool 
--macro-prefix=gl --no-vc-files alloca-opt autobuild count-one-bits extensions 
full-read full-write libunistring strcase strftime striconveh
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([])
@@ -29,6 +29,7 @@ gl_MODULES([
   libunistring
   strcase
   strftime
+  striconveh
 ])
 gl_AVOID([])
 gl_SOURCE_BASE([lib])
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 4d112e3..5717280 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -25,6 +25,7 @@ AC_DEFUN([gl_EARLY],
   m4_pattern_allow([^gl_LIBOBJS$])dnl a variable
   m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable
   AC_REQUIRE([AC_PROG_RANLIB])
+  AC_REQUIRE([AM_PROG_CC_C_O])
   AB_INIT
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
 ])
@@ -45,6 +46,8 @@ AC_DEFUN([gl_INIT],
   gl_FUNC_ALLOCA
   gl_COUNT_ONE_BITS
   AM_ICONV
+  gl_ICONV_H
+  gl_FUNC_ICONV_OPEN
   gl_INLINE
   gl_LIBUNISTRING
   gl_LOCALCHARSET
@@ -56,16 +59,26 @@ AC_DEFUN([gl_INIT],
   gl_WCHAR_MODULE_INDICATOR([mbrtowc])
   gl_FUNC_MBSINIT
   gl_WCHAR_MODULE_INDICATOR([mbsinit])
+  gl_MULTIARCH
   gl_SAFE_READ
   gl_SAFE_WRITE
   gt_TYPE_SSIZE_T
   AM_STDBOOL_H
+  gl_STDINT_H
   gl_STRCASE
   gl_FUNC_GNU_STRFTIME
+  if test $gl_cond_libtool = false; then
+    gl_ltlibdeps="$gl_ltlibdeps $LTLIBICONV"
+    gl_libdeps="$gl_libdeps $LIBICONV"
+  fi
   gl_HEADER_STRINGS_H
   gl_HEADER_TIME_H
   gl_TIME_R
   gl_UNISTD_H
+  gl_MODULE_INDICATOR([unistr/u8-mbtouc])
+  gl_MODULE_INDICATOR([unistr/u8-mbtouc-unsafe])
+  gl_MODULE_INDICATOR([unistr/u8-mbtoucr])
+  gl_MODULE_INDICATOR([unistr/u8-uctomb])
   gl_WCHAR_H
   gl_FUNC_WRITE
   gl_UNISTD_MODULE_INDICATOR([write])
@@ -200,12 +213,25 @@ AC_DEFUN([gl_FILE_LIST], [
   build-aux/config.rpath
   build-aux/link-warning.h
   lib/alloca.in.h
+  lib/c-ctype.c
+  lib/c-ctype.h
+  lib/c-strcase.h
+  lib/c-strcasecmp.c
+  lib/c-strcaseeq.h
+  lib/c-strncasecmp.c
   lib/config.charset
   lib/count-one-bits.h
   lib/full-read.c
   lib/full-read.h
   lib/full-write.c
   lib/full-write.h
+  lib/iconv.in.h
+  lib/iconv_open-aix.gperf
+  lib/iconv_open-hpux.gperf
+  lib/iconv_open-irix.gperf
+  lib/iconv_open-osf.gperf
+  lib/iconv_open.c
+  lib/iconveh.h
   lib/localcharset.c
   lib/localcharset.h
   lib/mbrlen.c
@@ -218,15 +244,28 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/safe-write.c
   lib/safe-write.h
   lib/stdbool.in.h
+  lib/stdint.in.h
   lib/strcasecmp.c
   lib/streq.h
   lib/strftime.c
   lib/strftime.h
+  lib/striconveh.c
+  lib/striconveh.h
   lib/strings.in.h
   lib/strncasecmp.c
   lib/time.in.h
   lib/time_r.c
   lib/unistd.in.h
+  lib/unistr.h
+  lib/unistr/u8-mbtouc-aux.c
+  lib/unistr/u8-mbtouc-unsafe-aux.c
+  lib/unistr/u8-mbtouc-unsafe.c
+  lib/unistr/u8-mbtouc.c
+  lib/unistr/u8-mbtoucr.c
+  lib/unistr/u8-prev.c
+  lib/unistr/u8-uctomb-aux.c
+  lib/unistr/u8-uctomb.c
+  lib/unitypes.h
   lib/verify.h
   lib/wchar.in.h
   lib/write.c
@@ -239,6 +278,8 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/glibc21.m4
   m4/gnulib-common.m4
   m4/iconv.m4
+  m4/iconv_h.m4
+  m4/iconv_open.m4
   m4/include_next.m4
   m4/inline.m4
   m4/lib-ld.m4
@@ -249,14 +290,17 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/locale-fr.m4
   m4/locale-ja.m4
   m4/locale-zh.m4
+  m4/longlong.m4
   m4/mbrlen.m4
   m4/mbrtowc.m4
   m4/mbsinit.m4
   m4/mbstate_t.m4
+  m4/multiarch.m4
   m4/safe-read.m4
   m4/safe-write.m4
   m4/ssize_t.m4
   m4/stdbool.m4
+  m4/stdint.m4
   m4/strcase.m4
   m4/strftime.m4
   m4/strings_h.m4
diff --git a/m4/iconv_h.m4 b/m4/iconv_h.m4
new file mode 100644
index 0000000..bc05b05
--- /dev/null
+++ b/m4/iconv_h.m4
@@ -0,0 +1,34 @@
+# iconv_h.m4 serial 4
+dnl Copyright (C) 2007-2008 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_ICONV_H],
+[
+  AC_REQUIRE([gl_ICONV_H_DEFAULTS])
+  gl_CHECK_NEXT_HEADERS([iconv.h])
+])
+
+dnl Unconditionally enables the replacement of <iconv.h>.
+AC_DEFUN([gl_REPLACE_ICONV_H],
+[
+  AC_REQUIRE([gl_ICONV_H_DEFAULTS])
+  ICONV_H='iconv.h'
+])
+
+AC_DEFUN([gl_ICONV_MODULE_INDICATOR],
+[
+  dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
+  AC_REQUIRE([gl_ICONV_H_DEFAULTS])
+  
GNULIB_[]m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./-],[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])=1
+])
+
+AC_DEFUN([gl_ICONV_H_DEFAULTS],
+[
+  dnl Assume proper GNU behavior unless another module says otherwise.
+  REPLACE_ICONV=0;      AC_SUBST([REPLACE_ICONV])
+  REPLACE_ICONV_OPEN=0; AC_SUBST([REPLACE_ICONV_OPEN])
+  REPLACE_ICONV_UTF=0;  AC_SUBST([REPLACE_ICONV_UTF])
+  ICONV_H='';           AC_SUBST([ICONV_H])
+])
diff --git a/m4/iconv_open.m4 b/m4/iconv_open.m4
new file mode 100644
index 0000000..c7b948e
--- /dev/null
+++ b/m4/iconv_open.m4
@@ -0,0 +1,237 @@
+# iconv_open.m4 serial 5
+dnl Copyright (C) 2007-2009 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_ICONV_OPEN],
+[
+  AC_REQUIRE([AM_ICONV])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_REQUIRE([gl_ICONV_H_DEFAULTS])
+  if test "$am_cv_func_iconv" = yes; then
+    dnl Test whether iconv_open accepts standardized encoding names.
+    dnl We know that GNU libiconv and GNU libc do.
+    AC_EGREP_CPP([gnu_iconv], [
+      #include <iconv.h>
+      #if defined _LIBICONV_VERSION || defined __GLIBC__
+       gnu_iconv
+      #endif
+      ], [gl_func_iconv_gnu=yes], [gl_func_iconv_gnu=no])
+    if test $gl_func_iconv_gnu = no; then
+      iconv_flavor=
+      case "$host_os" in
+        aix*)  iconv_flavor=ICONV_FLAVOR_AIX ;;
+        irix*) iconv_flavor=ICONV_FLAVOR_IRIX ;;
+        hpux*) iconv_flavor=ICONV_FLAVOR_HPUX ;;
+        osf*)  iconv_flavor=ICONV_FLAVOR_OSF ;;
+      esac
+      if test -n "$iconv_flavor"; then
+        AC_DEFINE_UNQUOTED([ICONV_FLAVOR], [$iconv_flavor],
+          [Define to a symbolic name denoting the flavor of iconv_open()
+           implementation.])
+        gl_REPLACE_ICONV_OPEN
+      fi
+    fi
+  fi
+])
+
+AC_DEFUN([gl_REPLACE_ICONV_OPEN],
+[
+  gl_REPLACE_ICONV_H
+  REPLACE_ICONV_OPEN=1
+  AC_LIBOBJ([iconv_open])
+])
+
+AC_DEFUN([gl_FUNC_ICONV_OPEN_UTF],
+[
+  AC_REQUIRE([gl_FUNC_ICONV_OPEN])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_REQUIRE([gl_ICONV_H_DEFAULTS])
+  if test "$am_cv_func_iconv" = yes; then
+    if test -n "$am_cv_proto_iconv_arg1"; then
+      ICONV_CONST="const"
+    else
+      ICONV_CONST=
+    fi
+    AC_SUBST([ICONV_CONST])
+    AC_CACHE_CHECK([whether iconv supports conversion between UTF-8 and 
UTF-{16,32}{BE,LE}],
+      [gl_cv_func_iconv_supports_utf],
+      [
+        save_LIBS="$LIBS"
+        LIBS="$LIBS $LIBICONV"
+        AC_TRY_RUN([
+#include <iconv.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define ASSERT(expr) if (!(expr)) return 1;
+int main ()
+{
+  /* Test conversion from UTF-8 to UTF-16BE with no errors.  */
+  {
+    static const char input[] =
+      "Japanese (\346\227\245\346\234\254\350\252\236) 
[\360\235\224\215\360\235\224\236\360\235\224\255]";
+    static const char expected[] =
+      "\000J\000a\000p\000a\000n\000e\000s\000e\000 
\000(\145\345\147\054\212\236\000)\000 
\000[\330\065\335\015\330\065\335\036\330\065\335\055\000]";
+    iconv_t cd;
+    char buf[100];
+    const char *inptr;
+    size_t inbytesleft;
+    char *outptr;
+    size_t outbytesleft;
+    size_t res;
+    cd = iconv_open ("UTF-16BE", "UTF-8");
+    ASSERT (cd != (iconv_t)(-1));
+    inptr = input;
+    inbytesleft = sizeof (input) - 1;
+    outptr = buf;
+    outbytesleft = sizeof (buf);
+    res = iconv (cd,
+                (ICONV_CONST char **) &inptr, &inbytesleft,
+                &outptr, &outbytesleft);
+    ASSERT (res == 0 && inbytesleft == 0);
+    ASSERT (outptr == buf + (sizeof (expected) - 1));
+    ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
+    ASSERT (iconv_close (cd) == 0);
+  }
+  /* Test conversion from UTF-8 to UTF-16LE with no errors.  */
+  {
+    static const char input[] =
+      "Japanese (\346\227\245\346\234\254\350\252\236) 
[\360\235\224\215\360\235\224\236\360\235\224\255]";
+    static const char expected[] =
+      "J\000a\000p\000a\000n\000e\000s\000e\000 
\000(\000\345\145\054\147\236\212)\000 
\000[\000\065\330\015\335\065\330\036\335\065\330\055\335]\000";
+    iconv_t cd;
+    char buf[100];
+    const char *inptr;
+    size_t inbytesleft;
+    char *outptr;
+    size_t outbytesleft;
+    size_t res;
+    cd = iconv_open ("UTF-16LE", "UTF-8");
+    ASSERT (cd != (iconv_t)(-1));
+    inptr = input;
+    inbytesleft = sizeof (input) - 1;
+    outptr = buf;
+    outbytesleft = sizeof (buf);
+    res = iconv (cd,
+                (ICONV_CONST char **) &inptr, &inbytesleft,
+                &outptr, &outbytesleft);
+    ASSERT (res == 0 && inbytesleft == 0);
+    ASSERT (outptr == buf + (sizeof (expected) - 1));
+    ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
+    ASSERT (iconv_close (cd) == 0);
+  }
+  /* Test conversion from UTF-8 to UTF-32BE with no errors.  */
+  {
+    static const char input[] =
+      "Japanese (\346\227\245\346\234\254\350\252\236) 
[\360\235\224\215\360\235\224\236\360\235\224\255]";
+    static const char expected[] =
+      
"\000\000\000J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000
 
\000\000\000(\000\000\145\345\000\000\147\054\000\000\212\236\000\000\000)\000\000\000
 \000\000\000[\000\001\325\015\000\001\325\036\000\001\325\055\000\000\000]";
+    iconv_t cd;
+    char buf[100];
+    const char *inptr;
+    size_t inbytesleft;
+    char *outptr;
+    size_t outbytesleft;
+    size_t res;
+    cd = iconv_open ("UTF-32BE", "UTF-8");
+    ASSERT (cd != (iconv_t)(-1));
+    inptr = input;
+    inbytesleft = sizeof (input) - 1;
+    outptr = buf;
+    outbytesleft = sizeof (buf);
+    res = iconv (cd,
+                (ICONV_CONST char **) &inptr, &inbytesleft,
+                &outptr, &outbytesleft);
+    ASSERT (res == 0 && inbytesleft == 0);
+    ASSERT (outptr == buf + (sizeof (expected) - 1));
+    ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
+    ASSERT (iconv_close (cd) == 0);
+  }
+  /* Test conversion from UTF-8 to UTF-32LE with no errors.  */
+  {
+    static const char input[] =
+      "Japanese (\346\227\245\346\234\254\350\252\236) 
[\360\235\224\215\360\235\224\236\360\235\224\255]";
+    static const char expected[] =
+      
"J\000\000\000a\000\000\000p\000\000\000a\000\000\000n\000\000\000e\000\000\000s\000\000\000e\000\000\000
 
\000\000\000(\000\000\000\345\145\000\000\054\147\000\000\236\212\000\000)\000\000\000
 
\000\000\000[\000\000\000\015\325\001\000\036\325\001\000\055\325\001\000]\000\000\000";
+    iconv_t cd;
+    char buf[100];
+    const char *inptr;
+    size_t inbytesleft;
+    char *outptr;
+    size_t outbytesleft;
+    size_t res;
+    cd = iconv_open ("UTF-32LE", "UTF-8");
+    ASSERT (cd != (iconv_t)(-1));
+    inptr = input;
+    inbytesleft = sizeof (input) - 1;
+    outptr = buf;
+    outbytesleft = sizeof (buf);
+    res = iconv (cd,
+                (ICONV_CONST char **) &inptr, &inbytesleft,
+                &outptr, &outbytesleft);
+    ASSERT (res == 0 && inbytesleft == 0);
+    ASSERT (outptr == buf + (sizeof (expected) - 1));
+    ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
+    ASSERT (iconv_close (cd) == 0);
+  }
+  /* Test conversion from UTF-16BE to UTF-8 with no errors.
+     This test fails on NetBSD 3.0.  */
+  {
+    static const char input[] =
+      "\000J\000a\000p\000a\000n\000e\000s\000e\000 
\000(\145\345\147\054\212\236\000)\000 
\000[\330\065\335\015\330\065\335\036\330\065\335\055\000]";
+    static const char expected[] =
+      "Japanese (\346\227\245\346\234\254\350\252\236) 
[\360\235\224\215\360\235\224\236\360\235\224\255]";
+    iconv_t cd;
+    char buf[100];
+    const char *inptr;
+    size_t inbytesleft;
+    char *outptr;
+    size_t outbytesleft;
+    size_t res;
+    cd = iconv_open ("UTF-8", "UTF-16BE");
+    ASSERT (cd != (iconv_t)(-1));
+    inptr = input;
+    inbytesleft = sizeof (input) - 1;
+    outptr = buf;
+    outbytesleft = sizeof (buf);
+    res = iconv (cd,
+                (ICONV_CONST char **) &inptr, &inbytesleft,
+                &outptr, &outbytesleft);
+    ASSERT (res == 0 && inbytesleft == 0);
+    ASSERT (outptr == buf + (sizeof (expected) - 1));
+    ASSERT (memcmp (buf, expected, sizeof (expected) - 1) == 0);
+    ASSERT (iconv_close (cd) == 0);
+  }
+  return 0;
+}], [gl_cv_func_iconv_supports_utf=yes], [gl_cv_func_iconv_supports_utf=no],
+          [
+           dnl We know that GNU libiconv, GNU libc, and Solaris >= 9 do.
+           dnl OSF/1 5.1 has these encodings, but inserts a BOM in the "to"
+           dnl direction.
+           gl_cv_func_iconv_supports_utf=no
+           if test $gl_func_iconv_gnu = yes; then
+             gl_cv_func_iconv_supports_utf=yes
+           else
+changequote(,)dnl
+             case "$host_os" in
+               solaris2.9 | solaris2.1[0-9]) gl_cv_func_iconv_supports_utf=yes 
;;
+             esac
+changequote([,])dnl
+           fi
+          ])
+        LIBS="$save_LIBS"
+      ])
+    if test $gl_cv_func_iconv_supports_utf = no; then
+      REPLACE_ICONV_UTF=1
+      AC_DEFINE([REPLACE_ICONV_UTF], [1],
+        [Define if the iconv() functions are enhanced to handle the 
UTF-{16,32}{BE,LE} encodings.])
+      REPLACE_ICONV=1
+      gl_REPLACE_ICONV_OPEN
+      AC_LIBOBJ([iconv])
+      AC_LIBOBJ([iconv_close])
+    fi
+  fi
+])
diff --git a/m4/longlong.m4 b/m4/longlong.m4
new file mode 100644
index 0000000..eedc8d5
--- /dev/null
+++ b/m4/longlong.m4
@@ -0,0 +1,106 @@
+# longlong.m4 serial 14
+dnl Copyright (C) 1999-2007, 2009 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+
+# Define HAVE_LONG_LONG_INT if 'long long int' works.
+# This fixes a bug in Autoconf 2.61, but can be removed once we
+# assume 2.62 everywhere.
+
+# Note: If the type 'long long int' exists but is only 32 bits large
+# (as on some very old compilers), HAVE_LONG_LONG_INT will not be
+# defined. In this case you can treat 'long long int' like 'long int'.
+
+AC_DEFUN([AC_TYPE_LONG_LONG_INT],
+[
+  AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int],
+    [AC_LINK_IFELSE(
+       [_AC_TYPE_LONG_LONG_SNIPPET],
+       [dnl This catches a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004.
+       dnl If cross compiling, assume the bug isn't important, since
+       dnl nobody cross compiles for this platform as far as we know.
+       AC_RUN_IFELSE(
+         [AC_LANG_PROGRAM(
+            address@hidden:@include <limits.h>
+              @%:@ifndef LLONG_MAX
+              @%:@ define HALF \
+                       (1LL << (sizeof (long long int) * CHAR_BIT - 2))
+              @%:@ define LLONG_MAX (HALF - 1 + HALF)
+              @%:@endif]],
+            [[long long int n = 1;
+              int i;
+              for (i = 0; ; i++)
+                {
+                  long long int m = n << i;
+                  if (m >> i != n)
+                    return 1;
+                  if (LLONG_MAX / 2 < m)
+                    break;
+                }
+              return 0;]])],
+         [ac_cv_type_long_long_int=yes],
+         [ac_cv_type_long_long_int=no],
+         [ac_cv_type_long_long_int=yes])],
+       [ac_cv_type_long_long_int=no])])
+  if test $ac_cv_type_long_long_int = yes; then
+    AC_DEFINE([HAVE_LONG_LONG_INT], [1],
+      [Define to 1 if the system has the type `long long int'.])
+  fi
+])
+
+# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works.
+# This fixes a bug in Autoconf 2.61, but can be removed once we
+# assume 2.62 everywhere.
+
+# Note: If the type 'unsigned long long int' exists but is only 32 bits
+# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT
+# will not be defined. In this case you can treat 'unsigned long long int'
+# like 'unsigned long int'.
+
+AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT],
+[
+  AC_CACHE_CHECK([for unsigned long long int],
+    [ac_cv_type_unsigned_long_long_int],
+    [AC_LINK_IFELSE(
+       [_AC_TYPE_LONG_LONG_SNIPPET],
+       [ac_cv_type_unsigned_long_long_int=yes],
+       [ac_cv_type_unsigned_long_long_int=no])])
+  if test $ac_cv_type_unsigned_long_long_int = yes; then
+    AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1],
+      [Define to 1 if the system has the type `unsigned long long int'.])
+  fi
+])
+
+# Expands to a C program that can be used to test for simultaneous support
+# of 'long long' and 'unsigned long long'. We don't want to say that
+# 'long long' is available if 'unsigned long long' is not, or vice versa,
+# because too many programs rely on the symmetry between signed and unsigned
+# integer types (excluding 'bool').
+AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET],
+[
+  AC_LANG_PROGRAM(
+    [[/* For now, do not test the preprocessor; as of 2007 there are too many
+        implementations with broken preprocessors.  Perhaps this can
+        be revisited in 2012.  In the meantime, code should not expect
+        #if to work with literals wider than 32 bits.  */
+      /* Test literals.  */
+      long long int ll = 9223372036854775807ll;
+      long long int nll = -9223372036854775807LL;
+      unsigned long long int ull = 18446744073709551615ULL;
+      /* Test constant expressions.   */
+      typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
+                    ? 1 : -1)];
+      typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
+                    ? 1 : -1)];
+      int i = 63;]],
+    [[/* Test availability of runtime routines for shift and division.  */
+      long long int llmax = 9223372036854775807ll;
+      unsigned long long int ullmax = 18446744073709551615ull;
+      return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
+             | (llmax / ll) | (llmax % ll)
+             | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
+             | (ullmax / ull) | (ullmax % ull));]])
+])
diff --git a/m4/multiarch.m4 b/m4/multiarch.m4
new file mode 100644
index 0000000..ec377ba
--- /dev/null
+++ b/m4/multiarch.m4
@@ -0,0 +1,65 @@
+# multiarch.m4 serial 5
+dnl Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Determine whether the compiler is or may be producing universal binaries.
+#
+# On MacOS X 10.5 and later systems, the user can create libraries and
+# executables that work on multiple system types--known as "fat" or
+# "universal" binaries--by specifying multiple '-arch' options to the
+# compiler but only a single '-arch' option to the preprocessor.  Like
+# this:
+#
+#     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+#                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+#                 CPP="gcc -E" CXXCPP="g++ -E"
+#
+# Detect this situation and set the macro AA_APPLE_UNIVERSAL_BUILD at the
+# beginning of config.h and set APPLE_UNIVERSAL_BUILD accordingly.
+
+AC_DEFUN_ONCE([gl_MULTIARCH],
+[
+  dnl Code similar to autoconf-2.63 AC_C_BIGENDIAN.
+  gl_cv_c_multiarch=no
+  AC_COMPILE_IFELSE(
+    [AC_LANG_SOURCE(
+      [[#ifndef __APPLE_CC__
+         not a universal capable compiler
+        #endif
+        typedef int dummy;
+      ]])],
+    [
+     dnl Check for potential -arch flags.  It is not universal unless
+     dnl there are at least two -arch flags with different values.
+     arch=
+     prev=
+     for word in ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS}; do
+       if test -n "$prev"; then
+         case $word in
+           i?86 | x86_64 | ppc | ppc64)
+             if test -z "$arch" || test "$arch" = "$word"; then
+               arch="$word"
+             else
+               gl_cv_c_multiarch=yes
+             fi
+             ;;
+         esac
+         prev=
+       else
+         if test "x$word" = "x-arch"; then
+           prev=arch
+         fi
+       fi
+     done
+    ])
+  if test $gl_cv_c_multiarch = yes; then
+    AC_DEFINE([AA_APPLE_UNIVERSAL_BUILD], [1],
+      [Define if the compiler is building for multiple architectures of Apple 
platforms at once.])
+    APPLE_UNIVERSAL_BUILD=1
+  else
+    APPLE_UNIVERSAL_BUILD=0
+  fi
+  AC_SUBST([APPLE_UNIVERSAL_BUILD])
+])
diff --git a/m4/stdint.m4 b/m4/stdint.m4
new file mode 100644
index 0000000..a2e8bdd
--- /dev/null
+++ b/m4/stdint.m4
@@ -0,0 +1,472 @@
+# stdint.m4 serial 34
+dnl Copyright (C) 2001-2009 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert and Bruno Haible.
+dnl Test whether <stdint.h> is supported or must be substituted.
+
+AC_DEFUN([gl_STDINT_H],
+[
+  AC_PREREQ([2.59])dnl
+
+  dnl Check for long long int and unsigned long long int.
+  AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
+  if test $ac_cv_type_long_long_int = yes; then
+    HAVE_LONG_LONG_INT=1
+  else
+    HAVE_LONG_LONG_INT=0
+  fi
+  AC_SUBST([HAVE_LONG_LONG_INT])
+  AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT])
+  if test $ac_cv_type_unsigned_long_long_int = yes; then
+    HAVE_UNSIGNED_LONG_LONG_INT=1
+  else
+    HAVE_UNSIGNED_LONG_LONG_INT=0
+  fi
+  AC_SUBST([HAVE_UNSIGNED_LONG_LONG_INT])
+
+  dnl Check for <inttypes.h>.
+  dnl AC_INCLUDES_DEFAULT defines $ac_cv_header_inttypes_h.
+  if test $ac_cv_header_inttypes_h = yes; then
+    HAVE_INTTYPES_H=1
+  else
+    HAVE_INTTYPES_H=0
+  fi
+  AC_SUBST([HAVE_INTTYPES_H])
+
+  dnl Check for <sys/types.h>.
+  dnl AC_INCLUDES_DEFAULT defines $ac_cv_header_sys_types_h.
+  if test $ac_cv_header_sys_types_h = yes; then
+    HAVE_SYS_TYPES_H=1
+  else
+    HAVE_SYS_TYPES_H=0
+  fi
+  AC_SUBST([HAVE_SYS_TYPES_H])
+
+  gl_CHECK_NEXT_HEADERS([stdint.h])
+  if test $ac_cv_header_stdint_h = yes; then
+    HAVE_STDINT_H=1
+  else
+    HAVE_STDINT_H=0
+  fi
+  AC_SUBST([HAVE_STDINT_H])
+
+  dnl Now see whether we need a substitute <stdint.h>.
+  if test $ac_cv_header_stdint_h = yes; then
+    AC_CACHE_CHECK([whether stdint.h conforms to C99],
+      [gl_cv_header_working_stdint_h],
+      [gl_cv_header_working_stdint_h=no
+       AC_COMPILE_IFELSE([
+         AC_LANG_PROGRAM([[
+#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */
+#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */
+#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */
+#include <stdint.h>
+/* Dragonfly defines WCHAR_MIN, WCHAR_MAX only in <wchar.h>.  */
+#if !(defined WCHAR_MIN && defined WCHAR_MAX)
+#error "WCHAR_MIN, WCHAR_MAX not defined in <stdint.h>"
+#endif
+]
+gl_STDINT_INCLUDES
+[
+#ifdef INT8_MAX
+int8_t a1 = INT8_MAX;
+int8_t a1min = INT8_MIN;
+#endif
+#ifdef INT16_MAX
+int16_t a2 = INT16_MAX;
+int16_t a2min = INT16_MIN;
+#endif
+#ifdef INT32_MAX
+int32_t a3 = INT32_MAX;
+int32_t a3min = INT32_MIN;
+#endif
+#ifdef INT64_MAX
+int64_t a4 = INT64_MAX;
+int64_t a4min = INT64_MIN;
+#endif
+#ifdef UINT8_MAX
+uint8_t b1 = UINT8_MAX;
+#else
+typedef int b1[(unsigned char) -1 != 255 ? 1 : -1];
+#endif
+#ifdef UINT16_MAX
+uint16_t b2 = UINT16_MAX;
+#endif
+#ifdef UINT32_MAX
+uint32_t b3 = UINT32_MAX;
+#endif
+#ifdef UINT64_MAX
+uint64_t b4 = UINT64_MAX;
+#endif
+int_least8_t c1 = INT8_C (0x7f);
+int_least8_t c1max = INT_LEAST8_MAX;
+int_least8_t c1min = INT_LEAST8_MIN;
+int_least16_t c2 = INT16_C (0x7fff);
+int_least16_t c2max = INT_LEAST16_MAX;
+int_least16_t c2min = INT_LEAST16_MIN;
+int_least32_t c3 = INT32_C (0x7fffffff);
+int_least32_t c3max = INT_LEAST32_MAX;
+int_least32_t c3min = INT_LEAST32_MIN;
+int_least64_t c4 = INT64_C (0x7fffffffffffffff);
+int_least64_t c4max = INT_LEAST64_MAX;
+int_least64_t c4min = INT_LEAST64_MIN;
+uint_least8_t d1 = UINT8_C (0xff);
+uint_least8_t d1max = UINT_LEAST8_MAX;
+uint_least16_t d2 = UINT16_C (0xffff);
+uint_least16_t d2max = UINT_LEAST16_MAX;
+uint_least32_t d3 = UINT32_C (0xffffffff);
+uint_least32_t d3max = UINT_LEAST32_MAX;
+uint_least64_t d4 = UINT64_C (0xffffffffffffffff);
+uint_least64_t d4max = UINT_LEAST64_MAX;
+int_fast8_t e1 = INT_FAST8_MAX;
+int_fast8_t e1min = INT_FAST8_MIN;
+int_fast16_t e2 = INT_FAST16_MAX;
+int_fast16_t e2min = INT_FAST16_MIN;
+int_fast32_t e3 = INT_FAST32_MAX;
+int_fast32_t e3min = INT_FAST32_MIN;
+int_fast64_t e4 = INT_FAST64_MAX;
+int_fast64_t e4min = INT_FAST64_MIN;
+uint_fast8_t f1 = UINT_FAST8_MAX;
+uint_fast16_t f2 = UINT_FAST16_MAX;
+uint_fast32_t f3 = UINT_FAST32_MAX;
+uint_fast64_t f4 = UINT_FAST64_MAX;
+#ifdef INTPTR_MAX
+intptr_t g = INTPTR_MAX;
+intptr_t gmin = INTPTR_MIN;
+#endif
+#ifdef UINTPTR_MAX
+uintptr_t h = UINTPTR_MAX;
+#endif
+intmax_t i = INTMAX_MAX;
+uintmax_t j = UINTMAX_MAX;
+
+#include <limits.h> /* for CHAR_BIT */
+#define TYPE_MINIMUM(t) \
+  ((t) ((t) 0 < (t) -1 ? (t) 0 : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))
+#define TYPE_MAXIMUM(t) \
+  ((t) ((t) 0 < (t) -1 ? (t) -1 : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+struct s {
+  int check_PTRDIFF:
+      PTRDIFF_MIN == TYPE_MINIMUM (ptrdiff_t)
+      && PTRDIFF_MAX == TYPE_MAXIMUM (ptrdiff_t)
+      ? 1 : -1;
+  /* Detect bug in FreeBSD 6.0 / ia64.  */
+  int check_SIG_ATOMIC:
+      SIG_ATOMIC_MIN == TYPE_MINIMUM (sig_atomic_t)
+      && SIG_ATOMIC_MAX == TYPE_MAXIMUM (sig_atomic_t)
+      ? 1 : -1;
+  int check_SIZE: SIZE_MAX == TYPE_MAXIMUM (size_t) ? 1 : -1;
+  int check_WCHAR:
+      WCHAR_MIN == TYPE_MINIMUM (wchar_t)
+      && WCHAR_MAX == TYPE_MAXIMUM (wchar_t)
+      ? 1 : -1;
+  /* Detect bug in mingw.  */
+  int check_WINT:
+      WINT_MIN == TYPE_MINIMUM (wint_t)
+      && WINT_MAX == TYPE_MAXIMUM (wint_t)
+      ? 1 : -1;
+
+  /* Detect bugs in glibc 2.4 and Solaris 10 stdint.h, among others.  */
+  int check_UINT8_C:
+        (-1 < UINT8_C (0)) == (-1 < (uint_least8_t) 0) ? 1 : -1;
+  int check_UINT16_C:
+        (-1 < UINT16_C (0)) == (-1 < (uint_least16_t) 0) ? 1 : -1;
+
+  /* Detect bugs in OpenBSD 3.9 stdint.h.  */
+#ifdef UINT8_MAX
+  int check_uint8: (uint8_t) -1 == UINT8_MAX ? 1 : -1;
+#endif
+#ifdef UINT16_MAX
+  int check_uint16: (uint16_t) -1 == UINT16_MAX ? 1 : -1;
+#endif
+#ifdef UINT32_MAX
+  int check_uint32: (uint32_t) -1 == UINT32_MAX ? 1 : -1;
+#endif
+#ifdef UINT64_MAX
+  int check_uint64: (uint64_t) -1 == UINT64_MAX ? 1 : -1;
+#endif
+  int check_uint_least8: (uint_least8_t) -1 == UINT_LEAST8_MAX ? 1 : -1;
+  int check_uint_least16: (uint_least16_t) -1 == UINT_LEAST16_MAX ? 1 : -1;
+  int check_uint_least32: (uint_least32_t) -1 == UINT_LEAST32_MAX ? 1 : -1;
+  int check_uint_least64: (uint_least64_t) -1 == UINT_LEAST64_MAX ? 1 : -1;
+  int check_uint_fast8: (uint_fast8_t) -1 == UINT_FAST8_MAX ? 1 : -1;
+  int check_uint_fast16: (uint_fast16_t) -1 == UINT_FAST16_MAX ? 1 : -1;
+  int check_uint_fast32: (uint_fast32_t) -1 == UINT_FAST32_MAX ? 1 : -1;
+  int check_uint_fast64: (uint_fast64_t) -1 == UINT_FAST64_MAX ? 1 : -1;
+  int check_uintptr: (uintptr_t) -1 == UINTPTR_MAX ? 1 : -1;
+  int check_uintmax: (uintmax_t) -1 == UINTMAX_MAX ? 1 : -1;
+  int check_size: (size_t) -1 == SIZE_MAX ? 1 : -1;
+};
+         ]])],
+         [dnl Determine whether the various *_MIN, *_MAX macros are usable
+          dnl in preprocessor expression. We could do it by compiling a test
+          dnl program for each of these macros. It is faster to run a program
+          dnl that inspects the macro expansion.
+          dnl This detects a bug on HP-UX 11.23/ia64.
+          AC_RUN_IFELSE([
+            AC_LANG_PROGRAM([[
+#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */
+#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */
+#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */
+#include <stdint.h>
+]
+gl_STDINT_INCLUDES
+[
+#include <stdio.h>
+#include <string.h>
+#define MVAL(macro) MVAL1(macro)
+#define MVAL1(expression) #expression
+static const char *macro_values[] =
+  {
+#ifdef INT8_MAX
+    MVAL (INT8_MAX),
+#endif
+#ifdef INT16_MAX
+    MVAL (INT16_MAX),
+#endif
+#ifdef INT32_MAX
+    MVAL (INT32_MAX),
+#endif
+#ifdef INT64_MAX
+    MVAL (INT64_MAX),
+#endif
+#ifdef UINT8_MAX
+    MVAL (UINT8_MAX),
+#endif
+#ifdef UINT16_MAX
+    MVAL (UINT16_MAX),
+#endif
+#ifdef UINT32_MAX
+    MVAL (UINT32_MAX),
+#endif
+#ifdef UINT64_MAX
+    MVAL (UINT64_MAX),
+#endif
+    NULL
+  };
+]], [[
+  const char **mv;
+  for (mv = macro_values; *mv != NULL; mv++)
+    {
+      const char *value = *mv;
+      /* Test whether it looks like a cast expression.  */
+      if (strncmp (value, "((unsigned int)"/*)*/, 15) == 0
+          || strncmp (value, "((unsigned short)"/*)*/, 17) == 0
+          || strncmp (value, "((unsigned char)"/*)*/, 16) == 0
+          || strncmp (value, "((int)"/*)*/, 6) == 0
+          || strncmp (value, "((signed short)"/*)*/, 15) == 0
+          || strncmp (value, "((signed char)"/*)*/, 14) == 0)
+        return 1;
+    }
+  return 0;
+]])],
+              [gl_cv_header_working_stdint_h=yes],
+              [],
+              [dnl When cross-compiling, assume it works.
+               gl_cv_header_working_stdint_h=yes
+              ])
+         ])
+      ])
+  fi
+  if test "$gl_cv_header_working_stdint_h" = yes; then
+    STDINT_H=
+  else
+    dnl Check for <sys/inttypes.h>, and for
+    dnl <sys/bitypes.h> (used in Linux libc4 >= 4.6.7 and libc5).
+    AC_CHECK_HEADERS([sys/inttypes.h sys/bitypes.h])
+    if test $ac_cv_header_sys_inttypes_h = yes; then
+      HAVE_SYS_INTTYPES_H=1
+    else
+      HAVE_SYS_INTTYPES_H=0
+    fi
+    AC_SUBST([HAVE_SYS_INTTYPES_H])
+    if test $ac_cv_header_sys_bitypes_h = yes; then
+      HAVE_SYS_BITYPES_H=1
+    else
+      HAVE_SYS_BITYPES_H=0
+    fi
+    AC_SUBST([HAVE_SYS_BITYPES_H])
+
+    dnl Check for <wchar.h> (missing in Linux uClibc when built without wide
+    dnl character support).
+    AC_CHECK_HEADERS_ONCE([wchar.h])
+
+    gl_STDINT_TYPE_PROPERTIES
+    STDINT_H=stdint.h
+  fi
+  AC_SUBST([STDINT_H])
+])
+
+dnl gl_STDINT_BITSIZEOF(TYPES, INCLUDES)
+dnl Determine the size of each of the given types in bits.
+AC_DEFUN([gl_STDINT_BITSIZEOF],
+[
+  dnl Use a shell loop, to avoid bloating configure, and
+  dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into
+  dnl   config.h.in,
+  dnl - extra AC_SUBST calls, so that the right substitutions are made.
+  m4_foreach_w([gltype], [$1],
+    [AH_TEMPLATE([BITSIZEOF_]translit(gltype,[abcdefghijklmnopqrstuvwxyz 
],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]),
+       [Define to the number of bits in type ']gltype['.])])
+  for gltype in $1 ; do
+    AC_CACHE_CHECK([for bit size of $gltype], [gl_cv_bitsizeof_${gltype}],
+      [AC_COMPUTE_INT([result], [sizeof ($gltype) * CHAR_BIT],
+         [$2
+#include <limits.h>], [result=unknown])
+       eval gl_cv_bitsizeof_${gltype}=\$result
+      ])
+    eval result=\$gl_cv_bitsizeof_${gltype}
+    if test $result = unknown; then
+      dnl Use a nonempty default, because some compilers, such as IRIX 5 cc,
+      dnl do a syntax check even on unused #if conditions and give an error
+      dnl on valid C code like this:
+      dnl   #if 0
+      dnl   # if  > 32
+      dnl   # endif
+      dnl   #endif
+      result=0
+    fi
+    GLTYPE=`echo "$gltype" | tr 'abcdefghijklmnopqrstuvwxyz ' 
'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'`
+    AC_DEFINE_UNQUOTED([BITSIZEOF_${GLTYPE}], [$result])
+    eval BITSIZEOF_${GLTYPE}=\$result
+  done
+  m4_foreach_w([gltype], [$1],
+    [AC_SUBST([BITSIZEOF_]translit(gltype,[abcdefghijklmnopqrstuvwxyz 
],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))])
+])
+
+dnl gl_CHECK_TYPES_SIGNED(TYPES, INCLUDES)
+dnl Determine the signedness of each of the given types.
+dnl Define HAVE_SIGNED_TYPE if type is signed.
+AC_DEFUN([gl_CHECK_TYPES_SIGNED],
+[
+  dnl Use a shell loop, to avoid bloating configure, and
+  dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into
+  dnl   config.h.in,
+  dnl - extra AC_SUBST calls, so that the right substitutions are made.
+  m4_foreach_w([gltype], [$1],
+    [AH_TEMPLATE([HAVE_SIGNED_]translit(gltype,[abcdefghijklmnopqrstuvwxyz 
],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]),
+       [Define to 1 if ']gltype[' is a signed integer type.])])
+  for gltype in $1 ; do
+    AC_CACHE_CHECK([whether $gltype is signed], [gl_cv_type_${gltype}_signed],
+      [AC_COMPILE_IFELSE(
+         [AC_LANG_PROGRAM([$2[
+            int verify[2 * (($gltype) -1 < ($gltype) 0) - 1];]])],
+         result=yes, result=no)
+       eval gl_cv_type_${gltype}_signed=\$result
+      ])
+    eval result=\$gl_cv_type_${gltype}_signed
+    GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 
'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'`
+    if test "$result" = yes; then
+      AC_DEFINE_UNQUOTED([HAVE_SIGNED_${GLTYPE}], [1])
+      eval HAVE_SIGNED_${GLTYPE}=1
+    else
+      eval HAVE_SIGNED_${GLTYPE}=0
+    fi
+  done
+  m4_foreach_w([gltype], [$1],
+    [AC_SUBST([HAVE_SIGNED_]translit(gltype,[abcdefghijklmnopqrstuvwxyz 
],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_]))])
+])
+
+dnl gl_INTEGER_TYPE_SUFFIX(TYPES, INCLUDES)
+dnl Determine the suffix to use for integer constants of the given types.
+dnl Define t_SUFFIX for each such type.
+AC_DEFUN([gl_INTEGER_TYPE_SUFFIX],
+[
+  dnl Use a shell loop, to avoid bloating configure, and
+  dnl - extra AH_TEMPLATE calls, so that autoheader knows what to put into
+  dnl   config.h.in,
+  dnl - extra AC_SUBST calls, so that the right substitutions are made.
+  m4_foreach_w([gltype], [$1],
+    [AH_TEMPLATE(translit(gltype,[abcdefghijklmnopqrstuvwxyz 
],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX],
+       [Define to l, ll, u, ul, ull, etc., as suitable for
+        constants of type ']gltype['.])])
+  for gltype in $1 ; do
+    AC_CACHE_CHECK([for $gltype integer literal suffix],
+      [gl_cv_type_${gltype}_suffix],
+      [eval gl_cv_type_${gltype}_suffix=no
+       eval result=\$gl_cv_type_${gltype}_signed
+       if test "$result" = yes; then
+         glsufu=
+       else
+         glsufu=u
+       fi
+       for glsuf in "$glsufu" ${glsufu}l ${glsufu}ll ${glsufu}i64; do
+         case $glsuf in
+           '')  gltype1='int';;
+           l)  gltype1='long int';;
+           ll) gltype1='long long int';;
+           i64)        gltype1='__int64';;
+           u)  gltype1='unsigned int';;
+           ul) gltype1='unsigned long int';;
+           ull)        gltype1='unsigned long long int';;
+           ui64)gltype1='unsigned __int64';;
+         esac
+         AC_COMPILE_IFELSE(
+           [AC_LANG_PROGRAM([$2[
+              extern $gltype foo;
+              extern $gltype1 foo;]])],
+           [eval gl_cv_type_${gltype}_suffix=\$glsuf])
+         eval result=\$gl_cv_type_${gltype}_suffix
+         test "$result" != no && break
+       done])
+    GLTYPE=`echo $gltype | tr 'abcdefghijklmnopqrstuvwxyz ' 
'ABCDEFGHIJKLMNOPQRSTUVWXYZ_'`
+    eval result=\$gl_cv_type_${gltype}_suffix
+    test "$result" = no && result=
+    eval ${GLTYPE}_SUFFIX=\$result
+    AC_DEFINE_UNQUOTED([${GLTYPE}_SUFFIX], [$result])
+  done
+  m4_foreach_w([gltype], [$1],
+    [AC_SUBST(translit(gltype,[abcdefghijklmnopqrstuvwxyz 
],[ABCDEFGHIJKLMNOPQRSTUVWXYZ_])[_SUFFIX])])
+])
+
+dnl gl_STDINT_INCLUDES
+AC_DEFUN([gl_STDINT_INCLUDES],
+[[
+  /* BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
+     included before <wchar.h>.  */
+  #include <stddef.h>
+  #include <signal.h>
+  #if HAVE_WCHAR_H
+  # include <stdio.h>
+  # include <time.h>
+  # include <wchar.h>
+  #endif
+]])
+
+dnl gl_STDINT_TYPE_PROPERTIES
+dnl Compute HAVE_SIGNED_t, BITSIZEOF_t and t_SUFFIX, for all the types t
+dnl of interest to stdint.in.h.
+AC_DEFUN([gl_STDINT_TYPE_PROPERTIES],
+[
+  AC_REQUIRE([gl_MULTIARCH])
+  if test $APPLE_UNIVERSAL_BUILD = 0; then
+    gl_STDINT_BITSIZEOF([ptrdiff_t size_t],
+      [gl_STDINT_INCLUDES])
+  fi
+  gl_STDINT_BITSIZEOF([sig_atomic_t wchar_t wint_t],
+    [gl_STDINT_INCLUDES])
+  gl_CHECK_TYPES_SIGNED([sig_atomic_t wchar_t wint_t],
+    [gl_STDINT_INCLUDES])
+  gl_cv_type_ptrdiff_t_signed=yes
+  gl_cv_type_size_t_signed=no
+  if test $APPLE_UNIVERSAL_BUILD = 0; then
+    gl_INTEGER_TYPE_SUFFIX([ptrdiff_t size_t],
+      [gl_STDINT_INCLUDES])
+  fi
+  gl_INTEGER_TYPE_SUFFIX([sig_atomic_t wchar_t wint_t],
+    [gl_STDINT_INCLUDES])
+])
+
+dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in.
+dnl Remove this when we can assume autoconf >= 2.61.
+m4_ifdef([AC_COMPUTE_INT], [], [
+  AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])])
+])
+
+# Hey Emacs!
+# Local Variables:
+# indent-tabs-mode: nil
+# End:
diff --git a/test-suite/tests/i18n.test b/test-suite/tests/i18n.test
index 78d7e54..97e70d2 100644
--- a/test-suite/tests/i18n.test
+++ b/test-suite/tests/i18n.test
@@ -97,6 +97,11 @@
                (throw 'unresolved)))
       (throw 'unresolved)))
 
+;; Set the locale to a Latin-1 encoding so that the following
+;; strings can read.  The English locale will be used so that
+;; we can still test that the French text collation.
+(setlocale LC_ALL "en_US.ISO-8859-1")
+
 (with-test-prefix "text collation (French)"
 
   (pass-if "string-locale<?"
diff --git a/test-suite/tests/ports.test b/test-suite/tests/ports.test
index f1ba80b..88782a0 100644
--- a/test-suite/tests/ports.test
+++ b/test-suite/tests/ports.test
@@ -31,6 +31,9 @@
 (define (test-file)
   (data-file-name "ports-test.tmp"))
 
+;; Make sure that we are set up for 8-bit clean data
+(setbinary)
+
 
 ;;;; Some general utilities for testing ports.
 


hooks/post-receive
-- 
GNU Guile




reply via email to

[Prev in Thread] Current Thread [Next in Thread]