]> Savannah Git Hosting - gnulib.git/commitdiff
striconveh: Make the last change also work on musl libc.
authorBruno Haible <bruno@clisp.org>
Sun, 2 Jan 2022 18:55:27 +0000 (19:55 +0100)
committerBruno Haible <bruno@clisp.org>
Sun, 2 Jan 2022 18:55:27 +0000 (19:55 +0100)
* lib/striconveh.c (mem_cd_iconveh_internal): Make the U+FFFD conversion
also work with non-GNU iconv() implementations.

ChangeLog
lib/striconveh.c

index 3d837b1c1848265bebc99cfe6f773e867c15ca0f..6f21e7409756c0df3db784168764ade694af695f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2022-01-02  Bruno Haible  <bruno@clisp.org>
+
+       striconveh: Make the last change also work on musl libc.
+       * lib/striconveh.c (mem_cd_iconveh_internal): Make the U+FFFD conversion
+       also work with non-GNU iconv() implementations.
+
 2022-01-01  Paul Eggert  <eggert@cs.ucla.edu>
 
        gen-header: port to BusyBox ‘sed’
index 612c38c3ebb4cd588dbe2034c46d76599c5d077a..736482842705ee16709c8ab5fff1a5962a6051a7 100644 (file)
@@ -847,14 +847,27 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
                         insize = scratchlen;
                         if (cd2 != (iconv_t)(-1))
                           {
+                            char *out2ptr_try = out2ptr;
+                            size_t out2size_try = out2size;
                             res = iconv (cd2,
                                          (ICONV_CONST char **) &inptr, &insize,
-                                         &out2ptr, &out2size);
+                                         &out2ptr_try, &out2size_try);
                             if (handler == iconveh_replacement_character
-                                && res == (size_t)(-1) && errno == EILSEQ)
+                                && ((res == (size_t)(-1) && errno == EILSEQ)
+                                    /* FreeBSD iconv(), NetBSD iconv(), and
+                                       Solaris 11 iconv() insert a '?' if they
+                                       cannot convert.  This is what we want.
+                                       But IRIX iconv() inserts a NUL byte if it
+                                       cannot convert.
+                                       And musl libc iconv() inserts a '*' if it
+                                       cannot convert.  */
+                                    || (res > 0
+                                        && !(out2ptr_try - out2ptr == 1
+                                             && *out2ptr == '?'))))
                               {
-                                 /* U+FFFD can't be converted to TO_CODESET.
-                                    Use '?' instead.  */
+                                /* The iconv() call failed.
+                                   U+FFFD can't be converted to TO_CODESET.
+                                   Use '?' instead.  */
                                 scratchbuf[0] = '?';
                                 scratchlen = 1;
                                 inptr = scratchbuf;
@@ -863,6 +876,12 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
                                              (ICONV_CONST char **) &inptr, &insize,
                                              &out2ptr, &out2size);
                               }
+                            else
+                              {
+                                /* Accept the results of the iconv() call.  */
+                                out2ptr = out2ptr_try;
+                                out2size = out2size_try;
+                              }
                           }
                         else
                           {