Some proprietary iconv() implementations (IRIX, OSF/1, Solaris) are actually usable if 1. one is willing to do an indirect conversion (through UTF-8) if a direct conversion between two encodings doesn't exist, 2. one maps the standardized encoding names to the implementation specific ones (not needed on Solaris).
2007-03-31 Bruno Haible <[EMAIL PROTECTED]> Support old proprietary implementations of iconv. * modules/iconv_open: New file. * lib/iconv_.h: New file. * m4/iconv_h.m4: New file. * lib/iconv_open.c: New file. * lib/iconv_open-aix.gperf: New file. * lib/iconv_open-hpux.gperf: New file. * lib/iconv_open-irix.gperf: New file. * lib/iconv_open-osf.gperf: New file. * m4/iconv_open.m4: New file. * modules/linebreak (Depends-on): Add iconv_open. * modules/striconv (Depends-on): Likewise. * modules/striconveh (Depends-on): Likewise. * modules/unicodeio (Depends-on): Likewise. * lib/striconveh.h (mem_cd_iconveh, str_cd_iconveh): Allow cd to be (iconv_t)(-1). * lib/striconveh.c (mem_cd_iconveh_internal): Use an indirect conversion if cd is (iconv_t)(-1). (mem_iconveh, str_iconveh): Don't fail just because a direct conversion is not possible. =========================== modules/iconv_open =============================== Description: Character set conversion. Files: lib/iconv_.h lib/iconv_open.c lib/iconv_open-aix.gperf lib/iconv_open-hpux.gperf lib/iconv_open-irix.gperf lib/iconv_open-osf.gperf m4/iconv_h.m4 m4/iconv_open.m4 Depends-on: absolute-header iconv c-ctype configure.ac: gl_ICONV_H gl_FUNC_ICONV_OPEN Makefile.am: 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_.h rm -f [EMAIL PROTECTED] $@ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ sed -e 's|@''ABSOLUTE_ICONV_H''@|$(ABSOLUTE_ICONV_H)|g' \ -e 's|@''REPLACE_ICONV_OPEN''@|$(REPLACE_ICONV_OPEN)|g' \ < $(srcdir)/iconv_.h; \ } > [EMAIL PROTECTED] mv [EMAIL PROTECTED] $@ MOSTLYCLEANFILES += iconv.h iconv.h-t GPERF = gperf iconv_open-aix.h: iconv_open-aix.gperf $(GPERF) -m 10 iconv_open-aix.gperf > [EMAIL PROTECTED] mv [EMAIL PROTECTED] $@ iconv_open-hpux.h: iconv_open-hpux.gperf $(GPERF) -m 10 iconv_open-hpux.gperf > [EMAIL PROTECTED] mv [EMAIL PROTECTED] $@ iconv_open-irix.h: iconv_open-irix.gperf $(GPERF) -m 10 iconv_open-irix.gperf > [EMAIL PROTECTED] mv [EMAIL PROTECTED] $@ iconv_open-osf.h: iconv_open-osf.gperf $(GPERF) -m 10 iconv_open-osf.gperf > [EMAIL PROTECTED] mv [EMAIL PROTECTED] $@ 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 Include: <iconv.h> License: LGPL Maintainer: Bruno Haible ============================= lib/iconv_.h =================================== /* A GNU-like <iconv.h>. 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 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 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 #define _GL_ICONV_H #include @ABSOLUTE_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 #ifdef __cplusplus } #endif #endif ============================= m4/iconv_h.m4 ================================== # iconv_h.m4 serial 1 dnl Copyright (C) 2007 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_ABSOLUTE_HEADER([iconv.h]) ABSOLUTE_ICONV_H=\"$gl_cv_absolute_iconv_h\" AC_SUBST([ABSOLUTE_ICONV_H]) ICONV_H= AC_SUBST([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_OPEN=0; AC_SUBST([REPLACE_ICONV_OPEN]) ]) =========================== lib/ionv_open.c ================================== /* 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 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 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" #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. */ #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" #include ICONV_FLAVOR 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; /* 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; } /* 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); } return iconv_open (tocode, fromcode); } ========================= lib/iconv_open-aix.gperf =========================== 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" ========================= lib/iconv_open-hpux.gperf ========================== 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" ========================= lib/iconv_open-irix.gperf ========================== 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" ========================= lib/iconv_open-osf.gperf =========================== 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" ============================ m4/iconv_open.m4 ================================ # iconv_open.m4 serial 1 dnl Copyright (C) 2007 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.]) REPLACE_ICONV_OPEN=1 AC_LIBOBJ([iconv_open]) ICONV_H='iconv.h' fi fi fi ]) ============================================================================== *** modules/linebreak 28 Jan 2007 02:04:41 -0000 1.5 --- modules/linebreak 31 Mar 2007 20:46:36 -0000 *************** *** 11,16 **** --- 11,17 ---- localcharset c-ctype iconv + iconv_open utf8-ucs4-unsafe utf16-ucs4-unsafe xsize *** modules/striconv 9 Sep 2006 19:02:08 -0000 1.2 --- modules/striconv 31 Mar 2007 20:46:36 -0000 *************** *** 7,12 **** --- 7,13 ---- Depends-on: iconv + iconv_open strdup c-strcase *** modules/striconveh 28 Mar 2007 21:50:51 -0000 1.5 --- modules/striconveh 31 Mar 2007 20:46:36 -0000 *************** *** 8,13 **** --- 8,14 ---- Depends-on: stdbool iconv + iconv_open unistr/u8-prev unistr/u8-mbtouc-unsafe unistr/u8-mbtouc *** modules/unicodeio 6 Jul 2005 15:58:47 -0000 1.6 --- modules/unicodeio 31 Mar 2007 20:46:36 -0000 *************** *** 8,13 **** --- 8,14 ---- Depends-on: iconv + iconv_open gettext-h localcharset error *** lib/striconveh.h 23 Jan 2007 01:17:42 -0000 1.6 --- lib/striconveh.h 31 Mar 2007 20:46:36 -0000 *************** *** 42,48 **** /* Convert an entire string from one encoding to another, using iconv. The original string is at [SRC,...,SRC+SRCLEN-1]. ! The conversion descriptor from FROMCODE to TOCODE is passed as CD. 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) --- 42,49 ---- /* 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) *************** *** 67,75 **** /* Convert an entire string from one encoding to another, using iconv. The original string is the NUL-terminated string starting at SRC. ! The conversion descriptor is passed as CD. 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) --- 68,77 ---- /* 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) *** lib/striconveh.c 28 Mar 2007 22:25:24 -0000 1.14 --- lib/striconveh.c 31 Mar 2007 20:46:36 -0000 *************** *** 283,288 **** --- 283,292 ---- } 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; *************** *** 481,488 **** goto done; indirectly: ! /* The direct conversion failed, handler != iconveh_error, ! and cd2 != (iconv_t)(-1). Use a conversion through UTF-8. */ if (offsets != NULL) { --- 485,491 ---- goto done; indirectly: ! /* The direct conversion failed. Use a conversion through UTF-8. */ if (offsets != NULL) { *************** *** 495,500 **** --- 498,504 ---- } 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; *************** *** 509,515 **** /* Set to the initial state. */ if (cd1 != (iconv_t)(-1)) iconv (cd1, NULL, NULL, NULL, NULL); ! iconv (cd2, NULL, NULL, NULL, NULL); # endif while (in1size > 0 || do_final_flush1 || utf8len > 0 || do_final_flush2) --- 513,520 ---- /* 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) *************** *** 531,537 **** } if (cd1 != (iconv_t)(-1)) { ! if (offsets != NULL) res1 = iconv_carefully_1 (cd1, &in1ptr, &in1size, &out1ptr, &out1size, --- 536,542 ---- } if (cd1 != (iconv_t)(-1)) { ! if (slowly) res1 = iconv_carefully_1 (cd1, &in1ptr, &in1size, &out1ptr, &out1size, *************** *** 545,551 **** else { /* FROM_CODESET is UTF-8. */ ! res1 = utf8conv_carefully (offsets != NULL, &in1ptr, &in1size, &out1ptr, &out1size, &incremented1); --- 550,556 ---- else { /* FROM_CODESET is UTF-8. */ ! res1 = utf8conv_carefully (slowly, &in1ptr, &in1size, &out1ptr, &out1size, &incremented1); *************** *** 618,627 **** bool grow; if (in2size > 0) ! res2 = iconv_carefully (cd2, ! &in2ptr, &in2size, ! &out2ptr, &out2size, ! &incremented2); else /* in1size == 0 && !do_final_flush1 && in2size == 0 && do_final_flush2 */ { --- 623,641 ---- 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 */ { *************** *** 629,638 **** state. But avoid glibc-2.1 bug and Solaris 2.7 bug. */ # if defined _LIBICONV_VERSION \ || !((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) || defined __sun) ! res2 = iconv (cd2, NULL, NULL, &out2ptr, &out2size); ! # else ! res2 = 0; # endif do_final_flush2 = false; incremented2 = true; } --- 643,653 ---- 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; } *************** *** 703,711 **** inptr = scratchbuf; insize = scratchlen; ! res = iconv (cd2, ! (ICONV_CONST char **) &inptr, &insize, ! &out2ptr, &out2size); length = out2ptr - result; if (res == (size_t)(-1) && errno == E2BIG) { --- 718,745 ---- 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) { *************** *** 732,740 **** out2ptr = result + length; out2size = allocated - extra_alloc - length; ! res = iconv (cd2, ! (ICONV_CONST char **) &inptr, &insize, ! &out2ptr, &out2size); length = out2ptr - result; } # if !defined _LIBICONV_VERSION && !defined __GLIBC__ --- 766,788 ---- 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__ *************** *** 952,959 **** # endif cd = iconv_open (to_codeset, from_codeset); - if (cd == (iconv_t)(-1)) - return -1; if (STRCASEEQ (from_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)) cd1 = (iconv_t)(-1); --- 1000,1005 ---- *************** *** 963,969 **** if (cd1 == (iconv_t)(-1)) { int saved_errno = errno; ! iconv_close (cd); errno = saved_errno; return -1; } --- 1009,1016 ---- if (cd1 == (iconv_t)(-1)) { int saved_errno = errno; ! if (cd != (iconv_t)(-1)) ! iconv_close (cd); errno = saved_errno; return -1; } *************** *** 979,985 **** int saved_errno = errno; if (cd1 != (iconv_t)(-1)) iconv_close (cd1); ! iconv_close (cd); errno = saved_errno; return -1; } --- 1026,1033 ---- 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; } *************** *** 998,1004 **** iconv_close (cd2); if (cd1 != (iconv_t)(-1)) iconv_close (cd1); ! iconv_close (cd); errno = saved_errno; } else --- 1046,1053 ---- iconv_close (cd2); if (cd1 != (iconv_t)(-1)) iconv_close (cd1); ! if (cd != (iconv_t)(-1)) ! iconv_close (cd); errno = saved_errno; } else *************** *** 1010,1016 **** int saved_errno = errno; if (cd1 != (iconv_t)(-1)) iconv_close (cd1); ! iconv_close (cd); if (result != *resultp && result != NULL) free (result); errno = saved_errno; --- 1059,1066 ---- 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; *************** *** 1021,1033 **** /* Return -1, but free the allocated memory, and while doing that, preserve the errno from iconv_close. */ int saved_errno = errno; ! iconv_close (cd); if (result != *resultp && result != NULL) free (result); errno = saved_errno; return -1; } ! if (iconv_close (cd) < 0) { /* Return -1, but free the allocated memory, and while doing that, preserve the errno from iconv_close. */ --- 1071,1084 ---- /* 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. */ *************** *** 1085,1092 **** # endif cd = iconv_open (to_codeset, from_codeset); - if (cd == (iconv_t)(-1)) - return NULL; if (STRCASEEQ (from_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)) cd1 = (iconv_t)(-1); --- 1136,1141 ---- *************** *** 1096,1102 **** if (cd1 == (iconv_t)(-1)) { int saved_errno = errno; ! iconv_close (cd); errno = saved_errno; return NULL; } --- 1145,1152 ---- if (cd1 == (iconv_t)(-1)) { int saved_errno = errno; ! if (cd != (iconv_t)(-1)) ! iconv_close (cd); errno = saved_errno; return NULL; } *************** *** 1112,1118 **** int saved_errno = errno; if (cd1 != (iconv_t)(-1)) iconv_close (cd1); ! iconv_close (cd); errno = saved_errno; return NULL; } --- 1162,1169 ---- 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; } *************** *** 1128,1134 **** iconv_close (cd2); if (cd1 != (iconv_t)(-1)) iconv_close (cd1); ! iconv_close (cd); errno = saved_errno; } else --- 1179,1186 ---- iconv_close (cd2); if (cd1 != (iconv_t)(-1)) iconv_close (cd1); ! if (cd != (iconv_t)(-1)) ! iconv_close (cd); errno = saved_errno; } else *************** *** 1140,1146 **** int saved_errno = errno; if (cd1 != (iconv_t)(-1)) iconv_close (cd1); ! iconv_close (cd); free (result); errno = saved_errno; return NULL; --- 1192,1199 ---- 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; *************** *** 1150,1161 **** /* Return NULL, but free the allocated memory, and while doing that, preserve the errno from iconv_close. */ int saved_errno = errno; ! iconv_close (cd); free (result); errno = saved_errno; return NULL; } ! if (iconv_close (cd) < 0) { /* Return NULL, but free the allocated memory, and while doing that, preserve the errno from iconv_close. */ --- 1203,1215 ---- /* 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. */