changeset 11979:4dab439a2737

Work around towlower, towupper bug on mingw.
author Bruno Haible <bruno@clisp.org>
date Tue, 08 Sep 2009 23:27:09 +0200
parents e14497f7747c
children 0811c19e147f
files ChangeLog doc/posix-functions/towlower.texi doc/posix-functions/towupper.texi lib/wctype.in.h m4/wctype.m4
diffstat 5 files changed, 59 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-09-08  Bruno Haible  <bruno@clisp.org>
+
+	Work around towlower, towupper bug on mingw.
+	* lib/wctype.in.h (towlower, towupper) [__MINGW32__]: New replacements.
+	* m4/wctype.m4 (gl_WCTYPE_H): Replace <wctype.h> also on mingw.
+	* doc/posix-functions/towlower.texi: Mention the mingw bug.
+	* doc/posix-functions/towupper.texi: Likewise.
+	Reported by Eric Blake.
+
 2009-09-08  Jim Meyering  <meyering@redhat.com>
 
 	build: don't try to run autoheader if we don't use it
--- a/doc/posix-functions/towlower.texi
+++ b/doc/posix-functions/towlower.texi
@@ -11,6 +11,10 @@
 @item
 This function is missing on some platforms:
 IRIX 5.3, Solaris 2.5.1.
+@item
+This function returns values of which the upper 16 bits are incorrect
+on some platforms:
+mingw.
 @end itemize
 
 Portability problems not fixed by Gnulib:
--- a/doc/posix-functions/towupper.texi
+++ b/doc/posix-functions/towupper.texi
@@ -11,6 +11,10 @@
 @item
 This function is missing on some platforms:
 IRIX 5.3, Solaris 2.5.1.
+@item
+This function returns values of which the upper 16 bits are incorrect
+on some platforms:
+mingw.
 @end itemize
 
 Portability problems not fixed by Gnulib:
--- a/lib/wctype.in.h
+++ b/lib/wctype.in.h
@@ -196,5 +196,36 @@
 
 # endif /* ! HAVE_ISWCNTRL */
 
+# if defined __MINGW32__
+
+/* On native Windows, wchar_t is uint16_t, and wint_t is uint32_t.
+   The functions towlower and towupper are implemented in the MSVCRT library
+   to take a wchar_t argument and return a wchar_t result.  mingw declares
+   these functions to take a wint_t argument and return a wint_t result.
+   This means that:
+   1. When the user passes an argument outside the range 0x0000..0xFFFF, the
+      function will look only at the lower 16 bits.  This is allowed according
+      to POSIX.
+   2. The return value is returned in the lower 16 bits of the result register.
+      The upper 16 bits are random: whatever happened to be in that part of the
+      result register.  We need to fix this by adding a zero-extend from
+      wchar_t to wint_t after the call.  */
+
+static inline wint_t
+rpl_towlower (wint_t wc)
+{
+  return (wint_t) (wchar_t) towlower (wc);
+}
+#  define towlower rpl_towlower
+
+static inline wint_t
+rpl_towupper (wint_t wc)
+{
+  return (wint_t) (wchar_t) towupper (wc);
+}
+#  define towupper rpl_towupper
+
+# endif
+
 #endif /* _GL_WCTYPE_H */
 #endif /* _GL_WCTYPE_H */
--- a/m4/wctype.m4
+++ b/m4/wctype.m4
@@ -1,4 +1,4 @@
-# wctype.m4 serial 2
+# wctype.m4 serial 3
 
 dnl A placeholder for ISO C99 <wctype.h>, for platforms that lack it.
 
@@ -12,6 +12,7 @@
 AC_DEFUN([gl_WCTYPE_H],
 [
   AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST])
   AC_CHECK_FUNCS_ONCE([iswcntrl])
   if test $ac_cv_func_iswcntrl = yes; then
     HAVE_ISWCNTRL=1
@@ -52,7 +53,15 @@
             ])
         ])
       if test $gl_cv_func_iswcntrl_works = yes; then
-        WCTYPE_H=
+        case "$host_os" in
+          mingw*)
+            dnl On mingw, towlower and towupper return random high 16 bits.
+            ;;
+          *)
+            dnl iswcntrl works. towlower and towupper work as well.
+            WCTYPE_H=
+            ;;
+        esac
       fi
     fi
     dnl Compute NEXT_WCTYPE_H even if WCTYPE_H is empty,