libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

iconv.m4 (11052B)


      1 # iconv.m4
      2 # serial 28
      3 dnl Copyright (C) 2000-2002, 2007-2014, 2016-2024 Free Software Foundation,
      4 dnl Inc.
      5 dnl This file is free software; the Free Software Foundation
      6 dnl gives unlimited permission to copy and/or distribute it,
      7 dnl with or without modifications, as long as this notice is preserved.
      8 dnl This file is offered as-is, without any warranty.
      9 
     10 dnl From Bruno Haible.
     11 
     12 AC_PREREQ([2.64])
     13 
     14 dnl Note: AM_ICONV is documented in the GNU gettext manual
     15 dnl <https://www.gnu.org/software/gettext/manual/html_node/AM_005fICONV.html>.
     16 dnl Don't make changes that are incompatible with that documentation!
     17 
     18 AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
     19 [
     20   dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
     21   AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
     22   AC_REQUIRE([AC_LIB_RPATH])
     23 
     24   dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
     25   dnl accordingly.
     26   AC_LIB_LINKFLAGS_BODY([iconv])
     27 ])
     28 
     29 AC_DEFUN([AM_ICONV_LINK],
     30 [
     31   dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
     32   dnl those with the standalone portable GNU libiconv installed).
     33   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
     34 
     35   dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
     36   dnl accordingly.
     37   AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
     38 
     39   dnl Add $INCICONV to CPPFLAGS before performing the following checks,
     40   dnl because if the user has installed libiconv and not disabled its use
     41   dnl via --without-libiconv-prefix, he wants to use it. The first
     42   dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed.
     43   gl_saved_CPPFLAGS="$CPPFLAGS"
     44   AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
     45 
     46   AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [
     47     am_cv_func_iconv="no, consider installing GNU libiconv"
     48     am_cv_lib_iconv=no
     49     AC_LINK_IFELSE(
     50       [AC_LANG_PROGRAM(
     51          [[
     52 #include <stdlib.h>
     53 #include <iconv.h>
     54          ]],
     55          [[iconv_t cd = iconv_open("","");
     56            iconv(cd,NULL,NULL,NULL,NULL);
     57            iconv_close(cd);]])],
     58       [am_cv_func_iconv=yes])
     59     if test "$am_cv_func_iconv" != yes; then
     60       gl_saved_LIBS="$LIBS"
     61       LIBS="$LIBS $LIBICONV"
     62       AC_LINK_IFELSE(
     63         [AC_LANG_PROGRAM(
     64            [[
     65 #include <stdlib.h>
     66 #include <iconv.h>
     67            ]],
     68            [[iconv_t cd = iconv_open("","");
     69              iconv(cd,NULL,NULL,NULL,NULL);
     70              iconv_close(cd);]])],
     71         [am_cv_lib_iconv=yes]
     72         [am_cv_func_iconv=yes])
     73       LIBS="$gl_saved_LIBS"
     74     fi
     75   ])
     76   if test "$am_cv_func_iconv" = yes; then
     77     AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [
     78       dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11,
     79       dnl Solaris 10, macOS 14.4.
     80       gl_saved_LIBS="$LIBS"
     81       if test $am_cv_lib_iconv = yes; then
     82         LIBS="$LIBS $LIBICONV"
     83       fi
     84       am_cv_func_iconv_works=no
     85       for ac_iconv_const in '' 'const'; do
     86         AC_RUN_IFELSE(
     87           [AC_LANG_PROGRAM(
     88              [[
     89 #include <iconv.h>
     90 #include <string.h>
     91 
     92 #ifndef ICONV_CONST
     93 # define ICONV_CONST $ac_iconv_const
     94 #endif
     95              ]],
     96              [[int result = 0;
     97   /* Test against AIX 5.1...7.2 bug: Failures are not distinguishable from
     98      successful returns.  This is even documented in
     99      <https://www.ibm.com/support/knowledgecenter/ssw_aix_72/i_bostechref/iconv.html> */
    100   {
    101     iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
    102     if (cd_utf8_to_88591 != (iconv_t)(-1))
    103       {
    104         static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */
    105         char buf[10];
    106         ICONV_CONST char *inptr = input;
    107         size_t inbytesleft = strlen (input);
    108         char *outptr = buf;
    109         size_t outbytesleft = sizeof (buf);
    110         size_t res = iconv (cd_utf8_to_88591,
    111                             &inptr, &inbytesleft,
    112                             &outptr, &outbytesleft);
    113         if (res == 0)
    114           result |= 1;
    115         iconv_close (cd_utf8_to_88591);
    116       }
    117   }
    118   /* Test against macOS 14.4 bug: Failures are not distinguishable from
    119      successful returns.
    120      POSIX:2018 says: "The iconv() function shall ... return the number of
    121      non-identical conversions performed."
    122      But here, the conversion always does transliteration (the suffixes
    123      "//TRANSLIT" and "//IGNORE" have no effect, nor does iconvctl()) and
    124      does not report when it does a non-identical conversion.  */
    125   {
    126     iconv_t cd_utf8_to_88591 = iconv_open ("ISO-8859-1", "UTF-8");
    127     if (cd_utf8_to_88591 != (iconv_t)(-1))
    128       {
    129         static ICONV_CONST char input[] = "\305\202"; /* LATIN SMALL LETTER L WITH STROKE */
    130         char buf[10];
    131         ICONV_CONST char *inptr = input;
    132         size_t inbytesleft = strlen (input);
    133         char *outptr = buf;
    134         size_t outbytesleft = sizeof (buf);
    135         size_t res = iconv (cd_utf8_to_88591,
    136                             &inptr, &inbytesleft,
    137                             &outptr, &outbytesleft);
    138         /* Here:
    139            With glibc, GNU libiconv (including macOS up to 13): res == (size_t)-1, errno == EILSEQ.
    140            With musl libc, NetBSD 10, Solaris 11: res == 1.
    141            With macOS 14.4: res == 0, output is "l".  */
    142         if (res == 0)
    143           result |= 2;
    144         iconv_close (cd_utf8_to_88591);
    145       }
    146   }
    147   /* Test against Solaris 10 bug: Failures are not distinguishable from
    148      successful returns.  */
    149   {
    150     iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
    151     if (cd_ascii_to_88591 != (iconv_t)(-1))
    152       {
    153         static ICONV_CONST char input[] = "\263";
    154         char buf[10];
    155         ICONV_CONST char *inptr = input;
    156         size_t inbytesleft = strlen (input);
    157         char *outptr = buf;
    158         size_t outbytesleft = sizeof (buf);
    159         size_t res = iconv (cd_ascii_to_88591,
    160                             &inptr, &inbytesleft,
    161                             &outptr, &outbytesleft);
    162         if (res == 0)
    163           result |= 4;
    164         iconv_close (cd_ascii_to_88591);
    165       }
    166   }
    167   /* Test against AIX 6.1..7.1 bug: Buffer overrun.  */
    168   {
    169     iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
    170     if (cd_88591_to_utf8 != (iconv_t)(-1))
    171       {
    172         static ICONV_CONST char input[] = "\304";
    173         static char buf[2] = { (char)0xDE, (char)0xAD };
    174         ICONV_CONST char *inptr = input;
    175         size_t inbytesleft = 1;
    176         char *outptr = buf;
    177         size_t outbytesleft = 1;
    178         size_t res = iconv (cd_88591_to_utf8,
    179                             &inptr, &inbytesleft,
    180                             &outptr, &outbytesleft);
    181         if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD)
    182           result |= 8;
    183         iconv_close (cd_88591_to_utf8);
    184       }
    185   }
    186 #if 0 /* This bug could be worked around by the caller.  */
    187   /* Test against HP-UX 11.11 bug: Positive return value instead of 0.  */
    188   {
    189     iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
    190     if (cd_88591_to_utf8 != (iconv_t)(-1))
    191       {
    192         static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
    193         char buf[50];
    194         ICONV_CONST char *inptr = input;
    195         size_t inbytesleft = strlen (input);
    196         char *outptr = buf;
    197         size_t outbytesleft = sizeof (buf);
    198         size_t res = iconv (cd_88591_to_utf8,
    199                             &inptr, &inbytesleft,
    200                             &outptr, &outbytesleft);
    201         if ((int)res > 0)
    202           result |= 16;
    203         iconv_close (cd_88591_to_utf8);
    204       }
    205   }
    206 #endif
    207   /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
    208      provided.  */
    209   {
    210     /* Try standardized names.  */
    211     iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP");
    212     /* Try IRIX, OSF/1 names.  */
    213     iconv_t cd2 = iconv_open ("UTF-8", "eucJP");
    214     /* Try AIX names.  */
    215     iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP");
    216     /* Try HP-UX names.  */
    217     iconv_t cd4 = iconv_open ("utf8", "eucJP");
    218     if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1)
    219         && cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1))
    220       result |= 32;
    221     if (cd1 != (iconv_t)(-1))
    222       iconv_close (cd1);
    223     if (cd2 != (iconv_t)(-1))
    224       iconv_close (cd2);
    225     if (cd3 != (iconv_t)(-1))
    226       iconv_close (cd3);
    227     if (cd4 != (iconv_t)(-1))
    228       iconv_close (cd4);
    229   }
    230   return result;
    231 ]])],
    232           [am_cv_func_iconv_works=yes], ,
    233           [case "$host_os" in
    234              aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
    235              *)            am_cv_func_iconv_works="guessing yes" ;;
    236            esac])
    237         test "$am_cv_func_iconv_works" = no || break
    238       done
    239       LIBS="$gl_saved_LIBS"
    240     ])
    241     case "$am_cv_func_iconv_works" in
    242       *no) am_func_iconv=no am_cv_lib_iconv=no ;;
    243       *)   am_func_iconv=yes ;;
    244     esac
    245   else
    246     am_func_iconv=no am_cv_lib_iconv=no
    247   fi
    248   if test "$am_func_iconv" = yes; then
    249     AC_DEFINE([HAVE_ICONV], [1],
    250       [Define if you have the iconv() function and it works.])
    251   fi
    252   if test "$am_cv_lib_iconv" = yes; then
    253     AC_MSG_CHECKING([how to link with libiconv])
    254     AC_MSG_RESULT([$LIBICONV])
    255   else
    256     dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
    257     dnl either.
    258     CPPFLAGS="$gl_saved_CPPFLAGS"
    259     LIBICONV=
    260     LTLIBICONV=
    261   fi
    262   AC_SUBST([LIBICONV])
    263   AC_SUBST([LTLIBICONV])
    264 ])
    265 
    266 dnl Define AM_ICONV using AC_DEFUN_ONCE, in order to avoid warnings like
    267 dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
    268 AC_DEFUN_ONCE([AM_ICONV],
    269 [
    270   AM_ICONV_LINK
    271   if test "$am_cv_func_iconv" = yes; then
    272     AC_CACHE_CHECK([whether iconv is compatible with its POSIX signature],
    273       [gl_cv_iconv_nonconst],
    274       [AC_COMPILE_IFELSE(
    275          [AC_LANG_PROGRAM(
    276             [[
    277 #include <stdlib.h>
    278 #include <iconv.h>
    279 extern
    280 #ifdef __cplusplus
    281 "C"
    282 #endif
    283 size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
    284             ]],
    285             [[]])],
    286          [gl_cv_iconv_nonconst=yes],
    287          [gl_cv_iconv_nonconst=no])
    288       ])
    289   else
    290     dnl When compiling GNU libiconv on a system that does not have iconv yet,
    291     dnl pick the POSIX compliant declaration without 'const'.
    292     gl_cv_iconv_nonconst=yes
    293   fi
    294   if test $gl_cv_iconv_nonconst = yes; then
    295     iconv_arg1=""
    296   else
    297     iconv_arg1="const"
    298   fi
    299   AC_DEFINE_UNQUOTED([ICONV_CONST], [$iconv_arg1],
    300     [Define as const if the declaration of iconv() needs const.])
    301   dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
    302   m4_ifdef([gl_ICONV_H_DEFAULTS],
    303     [AC_REQUIRE([gl_ICONV_H_DEFAULTS])
    304      if test $gl_cv_iconv_nonconst != yes; then
    305        ICONV_CONST="const"
    306      fi
    307     ])
    308 
    309   dnl A summary result, for those packages which want to print a summary at the
    310   dnl end of the configuration.
    311   if test "$am_func_iconv" = yes; then
    312     if test -n "$LIBICONV"; then
    313       am_cv_func_iconv_summary='yes, in libiconv'
    314     else
    315       am_cv_func_iconv_summary='yes, in libc'
    316     fi
    317   else
    318     if test "$am_cv_func_iconv" = yes; then
    319       am_cv_func_iconv_summary='not working, consider installing GNU libiconv'
    320     else
    321       am_cv_func_iconv_summary='no, consider installing GNU libiconv'
    322     fi
    323   fi
    324 ])