changeset 39914:32ddb61dde22

mbsnrtowcs: Work around Solaris 11.4 bug. * m4/mbsnrtowcs.m4 (gl_MBSNRTOWCS_WORKS_IN_TRADITIONAL_LOCALE): New macro. (gl_FUNC_MBSNRTOWCS): Invoke it. * doc/posix-functions/mbsnrtowcs.texi: Mention the Solaris bug.
author Bruno Haible <bruno@clisp.org>
date Sun, 14 Oct 2018 09:19:12 +0200
parents 73d60b1f9c96
children 6ad3d081a5ab
files ChangeLog doc/posix-functions/mbsnrtowcs.texi m4/mbsnrtowcs.m4
diffstat 3 files changed, 113 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Oct 14 09:33:46 2018 +0200
+++ b/ChangeLog	Sun Oct 14 09:19:12 2018 +0200
@@ -1,3 +1,11 @@
+2018-10-14  Bruno Haible  <bruno@clisp.org>
+
+	mbsnrtowcs: Work around Solaris 11.4 bug.
+	* m4/mbsnrtowcs.m4 (gl_MBSNRTOWCS_WORKS_IN_TRADITIONAL_LOCALE): New
+	macro.
+	(gl_FUNC_MBSNRTOWCS): Invoke it.
+	* doc/posix-functions/mbsnrtowcs.texi: Mention the Solaris bug.
+
 2018-10-14  Bruno Haible  <bruno@clisp.org>
 
 	doc: Update for Solaris 11.4.
--- a/doc/posix-functions/mbsnrtowcs.texi	Sun Oct 14 09:33:46 2018 +0200
+++ b/doc/posix-functions/mbsnrtowcs.texi	Sun Oct 14 09:19:12 2018 +0200
@@ -11,6 +11,9 @@
 @item
 This function is missing on some platforms:
 Mac OS X 10.3, FreeBSD 5.2.1, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 4.3.2, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 11.3, Cygwin 1.5.x, mingw, MSVC 14, Interix 3.5, BeOS, Android 4.4.
+@item
+This function produces invalid wide characters on some platforms:
+Solaris 11.4.
 @end itemize
 
 Portability problems not fixed by Gnulib:
--- a/m4/mbsnrtowcs.m4	Sun Oct 14 09:33:46 2018 +0200
+++ b/m4/mbsnrtowcs.m4	Sun Oct 14 09:19:12 2018 +0200
@@ -1,4 +1,4 @@
-# mbsnrtowcs.m4 serial 4
+# mbsnrtowcs.m4 serial 5
 dnl Copyright (C) 2008, 2010-2018 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -20,6 +20,12 @@
   else
     if test $REPLACE_MBSTATE_T = 1; then
       REPLACE_MBSNRTOWCS=1
+    else
+      gl_MBSNRTOWCS_WORKS_IN_TRADITIONAL_LOCALE
+      case "$gl_cv_func_mbsnrtowcs_works_in_traditional_locale" in
+        *yes) ;;
+        *) REPLACE_MBSNRTOWCS=1 ;;
+      esac
     fi
   fi
 ])
@@ -28,3 +34,98 @@
 AC_DEFUN([gl_PREREQ_MBSNRTOWCS], [
   :
 ])
+
+dnl Test whether mbsnrtowcs works in an ISO-8859-1 locale.
+dnl Result is gl_cv_func_mbsnrtowcs_works_in_traditional_locale.
+
+AC_DEFUN([gl_MBSNRTOWCS_WORKS_IN_TRADITIONAL_LOCALE],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([gt_LOCALE_FR])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether mbsnrtowcs works in a traditional locale],
+    [gl_cv_func_mbsnrtowcs_works_in_traditional_locale],
+    [
+      dnl Initial guess, used when cross-compiling or when no suitable locale
+      dnl is present.
+changequote(,)dnl
+      case "$host_os" in
+                  # Guess no on Solaris.
+        solaris*) gl_cv_func_mbsnrtowcs_works_in_traditional_locale="guessing no" ;;
+                  # Guess yes otherwise.
+        *)        gl_cv_func_mbsnrtowcs_works_in_traditional_locale="guessing yes" ;;
+      esac
+changequote([,])dnl
+      if test $LOCALE_FR != none; then
+        AC_RUN_IFELSE(
+          [AC_LANG_SOURCE([[
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+   <wchar.h>.
+   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 <stdio.h>
+#include <time.h>
+#include <wchar.h>
+int main ()
+{
+  /* This fails on Solaris 11.4:
+     mbsnrtowcs stores a wrong wide character: 0xDF instead of btowc (0xDF).  */
+  if (setlocale (LC_ALL, "$LOCALE_FR") != NULL)
+    {
+      /* Locale encoding is ISO-8859-1 or ISO-8859-15.  */
+      char input[] = "B\374\337er"; /* "Büßer" */
+      mbstate_t state;
+      mbstate_t temp_state;
+      wchar_t wc;
+      size_t ret;
+      const char *src;
+
+      #define BUFSIZE 10
+      wchar_t buf[BUFSIZE];
+      {
+        size_t i;
+        for (i = 0; i < BUFSIZE; i++)
+          buf[i] = (wchar_t) 0xBADFACE;
+      }
+
+      memset (&state, '\0', sizeof (mbstate_t));
+
+      wc = (wchar_t) 0xBADFACE;
+      ret = mbrtowc (&wc, input, 1, &state);
+      if (!(ret == 1 && wc == 'B' && mbsinit (&state)))
+        return 1;
+      input[0] = '\0';
+
+      wc = (wchar_t) 0xBADFACE;
+      ret = mbrtowc (&wc, input + 1, 1, &state);
+      if (!(ret == 1 && wctob (wc) == (unsigned char) '\374' && mbsinit (&state)))
+        return 2;
+      input[1] = '\0';
+
+      src = input + 2;
+      temp_state = state;
+      ret = mbsnrtowcs (NULL, &src, 4, 1, &temp_state);
+      if (!(ret == 3 && src == input + 2 && mbsinit (&state)))
+        return 3;
+
+      src = input + 2;
+      ret = mbsnrtowcs (buf, &src, 4, 1, &state);
+      if (!(ret == 1))
+        return 4;
+      if (!(src == input + 3))
+        return 5;
+      if (!(buf[0] == btowc ((unsigned char) '\337')))
+        return 6;
+    }
+  return 0;
+}]])],
+          [gl_cv_func_mbsnrtowcs_works_in_traditional_locale=yes],
+          [gl_cv_func_mbsnrtowcs_works_in_traditional_locale=no],
+          [:])
+      fi
+    ])
+])