Avoid macro redefinition warnings.
[gnulib.git] / lib / striconveh.c
index 2b67305..10cb06f 100644 (file)
@@ -1,11 +1,11 @@
 /* Character set conversion with error handling.
-   Copyright (C) 2001-2007 Free Software Foundation, Inc.
+   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
+   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.
+   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
@@ -13,8 +13,7 @@
    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.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
@@ -80,9 +79,13 @@ iconv_carefully (iconv_t cd,
                       &outptr, &outsize);
          if (!(res == (size_t)(-1) && errno == EINVAL))
            break;
-         /* We expect that no input bytes have been consumed so far.  */
-         if (inptr != inptr_before)
-           abort ();
+         /* 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)
@@ -118,31 +121,36 @@ iconv_carefully (iconv_t cd,
 # endif
 
 /* iconv_carefully_1 is like iconv_carefully, except that it stops after
-   converting one character.  */
+   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 = *inbuf;
-  const char *inptr_end = inptr + *inbytesleft;
+  const char *inptr_before = *inbuf;
+  const char *inptr = inptr_before;
+  const char *inptr_end = inptr_before + *inbytesleft;
   char *outptr = *outbuf;
   size_t outsize = *outbytesleft;
-  const char *inptr_before = inptr;
   size_t res = (size_t)(-1);
   size_t insize;
 
-  for (insize = 1; inptr + insize <= inptr_end; 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;
-      /* We expect that no input bytes have been consumed so far.  */
-      if (inptr != inptr_before)
-       abort ();
+      /* 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;
@@ -871,9 +879,10 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
   /* Now the final memory allocation.  */
   if (result == tmpbuf)
     {
+      size_t memsize = length + extra_alloc;
       char *memory;
 
-      memory = (char *) malloc (length + extra_alloc);
+      memory = (char *) malloc (memsize > 0 ? memsize : 1);
       if (memory != NULL)
        {
          memcpy (memory, tmpbuf, length);
@@ -888,9 +897,10 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
   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, length + extra_alloc);
+      memory = (char *) realloc (result, memsize > 0 ? memsize : 1);
       if (memory != NULL)
        result = memory;
     }
@@ -1016,7 +1026,11 @@ mem_iconveh (const char *src, size_t srclen,
            }
        }
 
-      if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0))
+      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
        {
@@ -1152,7 +1166,11 @@ str_iconveh (const char *src,
            }
        }
 
-      if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0))
+      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
        {