On mingw and older MSVC versions (fixed in MSVC 14), the wcstok function takes
only 2 arguments (like strtok, not multithread-safe).

The first patch works around it. The second patch verifies it through a unit
test.


2019-11-24  Bruno Haible  <br...@clisp.org>

        wcstok: Work around wrong signature on native Windows.
        * lib/wchar.in.h (wcstok): Override when REPLACE_WCSTOK is 1.
        * m4/wcstok.m4 (gl_FUNC_WCSTOK): Check for signature of wcstok. Set
        REPLACE_WCSTOK.
        * m4/wchar_h.m4 (gl_WCHAR_H_DEFAULTS): Initialize REPLACE_WCSTOK.
        * modules/wchar (Makefile.am): Substitute REPLACE_WCSTOK.
        * modules/wcstok (Depends-on, configure.ac): Consider REPLACE_WCSTOK.
        * doc/posix-functions/wcstok.texi: Mention the problem.

2019-11-24  Bruno Haible  <br...@clisp.org>

        wcstok: Add tests.
        * tests/test-wcstok.c: New file.
        * modules/wcstok-tests: New file.

>From 5ac9de982d61df59a1afc3446000f50a4ca705b6 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sun, 24 Nov 2019 13:11:12 +0100
Subject: [PATCH 1/2] wcstok: Work around wrong signature on native Windows.

* lib/wchar.in.h (wcstok): Override when REPLACE_WCSTOK is 1.
* m4/wcstok.m4 (gl_FUNC_WCSTOK): Check for signature of wcstok. Set
REPLACE_WCSTOK.
* m4/wchar_h.m4 (gl_WCHAR_H_DEFAULTS): Initialize REPLACE_WCSTOK.
* modules/wchar (Makefile.am): Substitute REPLACE_WCSTOK.
* modules/wcstok (Depends-on, configure.ac): Consider REPLACE_WCSTOK.
* doc/posix-functions/wcstok.texi: Mention the problem.
---
 ChangeLog                       | 11 +++++++++++
 doc/posix-functions/wcstok.texi |  3 +++
 lib/wchar.in.h                  | 15 +++++++++++++--
 m4/wchar_h.m4                   |  3 ++-
 m4/wcstok.m4                    | 29 +++++++++++++++++++++++++++--
 modules/wchar                   |  1 +
 modules/wcstok                  |  6 +++---
 7 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 47b079b..9e6725a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2019-11-24  Bruno Haible  <br...@clisp.org>
+
+	wcstok: Work around wrong signature on native Windows.
+	* lib/wchar.in.h (wcstok): Override when REPLACE_WCSTOK is 1.
+	* m4/wcstok.m4 (gl_FUNC_WCSTOK): Check for signature of wcstok. Set
+	REPLACE_WCSTOK.
+	* m4/wchar_h.m4 (gl_WCHAR_H_DEFAULTS): Initialize REPLACE_WCSTOK.
+	* modules/wchar (Makefile.am): Substitute REPLACE_WCSTOK.
+	* modules/wcstok (Depends-on, configure.ac): Consider REPLACE_WCSTOK.
+	* doc/posix-functions/wcstok.texi: Mention the problem.
+
 2019-11-22  Paul Eggert  <egg...@cs.ucla.edu>
 
 	intprops: INT_MULTIPLY_WRAPV speedup for GCC 8.4+
diff --git a/doc/posix-functions/wcstok.texi b/doc/posix-functions/wcstok.texi
index c93e236..6f971e1 100644
--- a/doc/posix-functions/wcstok.texi
+++ b/doc/posix-functions/wcstok.texi
@@ -11,6 +11,9 @@ Portability problems fixed by Gnulib:
 @item
 This function is missing on some platforms:
 Cygwin 1.5.x.
+@item
+This function takes only two arguments on some platforms:
+mingw, MSVC 14.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/lib/wchar.in.h b/lib/wchar.in.h
index 3ebcdba..9807f60 100644
--- a/lib/wchar.in.h
+++ b/lib/wchar.in.h
@@ -1037,12 +1037,23 @@ _GL_WARN_ON_USE (wcsstr, "wcsstr is unportable - "
 
 /* Divide WCS into tokens separated by characters in DELIM.  */
 #if @GNULIB_WCSTOK@
-# if !@HAVE_WCSTOK@
+# if @REPLACE_WCSTOK@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef wcstok
+#   define wcstok rpl_wcstok
+#  endif
+_GL_FUNCDECL_RPL (wcstok, wchar_t *,
+                  (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr));
+_GL_CXXALIAS_RPL (wcstok, wchar_t *,
+                  (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr));
+# else
+#  if !@HAVE_WCSTOK@
 _GL_FUNCDECL_SYS (wcstok, wchar_t *,
                   (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (wcstok, wchar_t *,
                   (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr));
+# endif
 # if __GLIBC__ >= 2
 _GL_CXXALIASWARN (wcstok);
 # endif
diff --git a/m4/wchar_h.m4 b/m4/wchar_h.m4
index cd20e7a..8c6ebcc 100644
--- a/m4/wchar_h.m4
+++ b/m4/wchar_h.m4
@@ -7,7 +7,7 @@ dnl with or without modifications, as long as this notice is preserved.
 
 dnl Written by Eric Blake.
 
-# wchar_h.m4 serial 43
+# wchar_h.m4 serial 44
 
 AC_DEFUN([gl_WCHAR_H],
 [
@@ -237,4 +237,5 @@ AC_DEFUN([gl_WCHAR_H_DEFAULTS],
   REPLACE_WCWIDTH=0;    AC_SUBST([REPLACE_WCWIDTH])
   REPLACE_WCSWIDTH=0;   AC_SUBST([REPLACE_WCSWIDTH])
   REPLACE_WCSFTIME=0;   AC_SUBST([REPLACE_WCSFTIME])
+  REPLACE_WCSTOK=0;     AC_SUBST([REPLACE_WCSTOK])
 ])
diff --git a/m4/wcstok.m4 b/m4/wcstok.m4
index 8201ca3..8f0aeb0 100644
--- a/m4/wcstok.m4
+++ b/m4/wcstok.m4
@@ -1,4 +1,4 @@
-# wcstok.m4 serial 2
+# wcstok.m4 serial 3
 dnl Copyright (C) 2011-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,7 +8,32 @@ AC_DEFUN([gl_FUNC_WCSTOK],
 [
   AC_REQUIRE([gl_WCHAR_H_DEFAULTS])
   AC_CHECK_FUNCS_ONCE([wcstok])
-  if test $ac_cv_func_wcstok = no; then
+  if test $ac_cv_func_wcstok = yes; then
+    dnl POSIX:        wchar_t *wcstok (wchar_t *, const wchar_t *, wchar_t **);
+    dnl mingw, MSVC:  wchar_t *wcstok (wchar_t *, const wchar_t *);
+    AC_CACHE_CHECK([for wcstok with POSIX signature],
+      [gl_cv_func_wcstok_posix_signature],
+      [AC_COMPILE_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[
+/* 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>
+wchar_t *wcstok (wchar_t *, const wchar_t *, wchar_t **);
+]],
+            [])],
+         [gl_cv_func_wcstok_posix_signature=yes],
+         [gl_cv_func_wcstok_posix_signature=no])
+      ])
+    if test $gl_cv_func_wcstok_posix_signature = no; then
+      REPLACE_WCSTOK=1
+    fi
+  else
     HAVE_WCSTOK=0
   fi
 ])
diff --git a/modules/wchar b/modules/wchar
index 29c67e8..a943740 100644
--- a/modules/wchar
+++ b/modules/wchar
@@ -131,6 +131,7 @@ wchar.h: wchar.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
 	      -e 's|@''REPLACE_WCWIDTH''@|$(REPLACE_WCWIDTH)|g' \
 	      -e 's|@''REPLACE_WCSWIDTH''@|$(REPLACE_WCSWIDTH)|g' \
 	      -e 's|@''REPLACE_WCSFTIME''@|$(REPLACE_WCSFTIME)|g' \
+	      -e 's|@''REPLACE_WCSTOK''@|$(REPLACE_WCSTOK)|g' \
 	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
 	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
 	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
diff --git a/modules/wcstok b/modules/wcstok
index 3ee3192..6f7e62c 100644
--- a/modules/wcstok
+++ b/modules/wcstok
@@ -8,12 +8,12 @@ m4/wcstok.m4
 
 Depends-on:
 wchar
-wcsspn          [test $HAVE_WCSTOK = 0]
-wcspbrk         [test $HAVE_WCSTOK = 0]
+wcsspn          [test $HAVE_WCSTOK = 0 || test $REPLACE_WCSTOK = 1]
+wcspbrk         [test $HAVE_WCSTOK = 0 || test $REPLACE_WCSTOK = 1]
 
 configure.ac:
 gl_FUNC_WCSTOK
-if test $HAVE_WCSTOK = 0; then
+if test $HAVE_WCSTOK = 0 || test $REPLACE_WCSTOK = 1; then
   AC_LIBOBJ([wcstok])
 fi
 gl_WCHAR_MODULE_INDICATOR([wcstok])
-- 
2.7.4

>From f50a5a002d05c2a75994896f47457edc60eea7a6 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sun, 24 Nov 2019 13:12:53 +0100
Subject: [PATCH 2/2] wcstok: Add tests.

* tests/test-wcstok.c: New file.
* modules/wcstok-tests: New file.
---
 ChangeLog            |  6 ++++++
 modules/wcstok-tests | 12 ++++++++++++
 tests/test-wcstok.c  | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)
 create mode 100644 modules/wcstok-tests
 create mode 100644 tests/test-wcstok.c

diff --git a/ChangeLog b/ChangeLog
index 9e6725a..984792b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2019-11-24  Bruno Haible  <br...@clisp.org>
 
+	wcstok: Add tests.
+	* tests/test-wcstok.c: New file.
+	* modules/wcstok-tests: New file.
+
+2019-11-24  Bruno Haible  <br...@clisp.org>
+
 	wcstok: Work around wrong signature on native Windows.
 	* lib/wchar.in.h (wcstok): Override when REPLACE_WCSTOK is 1.
 	* m4/wcstok.m4 (gl_FUNC_WCSTOK): Check for signature of wcstok. Set
diff --git a/modules/wcstok-tests b/modules/wcstok-tests
new file mode 100644
index 0000000..57ccd08
--- /dev/null
+++ b/modules/wcstok-tests
@@ -0,0 +1,12 @@
+Files:
+tests/test-wcstok.c
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-wcstok
+check_PROGRAMS += test-wcstok
diff --git a/tests/test-wcstok.c b/tests/test-wcstok.c
new file mode 100644
index 0000000..5c6fd51
--- /dev/null
+++ b/tests/test-wcstok.c
@@ -0,0 +1,53 @@
+/* Test of conversion of wide string to string.
+   Copyright (C) 2019 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 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
+   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, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>, 2019.  */
+
+#include <config.h>
+
+#include <wchar.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (wcstok, wchar_t *,
+                 (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr));
+
+#include <string.h>
+
+#include "macros.h"
+
+int
+main ()
+{
+  wchar_t string[] = L"hello  world!";
+  wchar_t delim[] = L" ";
+  wchar_t *ptr;
+  wchar_t *ret;
+
+  ret = wcstok (string, delim, &ptr);
+  ASSERT (ret == string);
+  ASSERT (memcmp (string, L"hello\0 world!", 14 * sizeof (wchar_t)) == 0);
+  ASSERT (ptr == string + 6);
+
+  ret = wcstok (NULL, delim, &ptr);
+  ASSERT (ret == string + 7);
+  ASSERT (memcmp (string, L"hello\0 world!", 14 * sizeof (wchar_t)) == 0);
+  ASSERT (ptr == NULL || *ptr == L'\0');
+
+  ret = wcstok (NULL, delim, &ptr);
+  ASSERT (ret == NULL);
+
+  return 0;
+}
-- 
2.7.4

Reply via email to