# HG changeset patch # User Bruno Haible # Date 1293456491 -3600 # Node ID 1a75c9206d288a261ae9e01c54e06277c5f33eac # Parent 1bc2888f2fcb378baf717c1b6776499d8490b626 mbrtowc: Work around a Solaris 7 bug. * m4/mbrtowc.m4 (gl_MBRTOWC_NULL_ARG1): New macro. (gl_MBRTOWC_NULL_ARG2): Renamed from gl_MBRTOWC_NULL_ARG. (gl_FUNC_MBRTOWC): Update. Define MBRTOWC_NULL_ARG2_BUG instead of MBRTOWC_NULL_ARG_BUG. Invoke gl_MBRTOWC_NULL_ARG1 and define MBRTOWC_NULL_ARG1_BUG. * lib/mbrtowc.c (rpl_mbrtowc): Use MBRTOWC_NULL_ARG2_BUG instead of MBRTOWC_NULL_ARG_BUG. Handle MBRTOWC_NULL_ARG1_BUG. * tests/test-mbrtowc.c (main): Test support of a NULL first argument. * doc/posix-functions/mbrtowc.texi: Mention the Solaris 7 bug. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2010-12-27 Bruno Haible + + mbrtowc: Work around a Solaris 7 bug. + * m4/mbrtowc.m4 (gl_MBRTOWC_NULL_ARG1): New macro. + (gl_MBRTOWC_NULL_ARG2): Renamed from gl_MBRTOWC_NULL_ARG. + (gl_FUNC_MBRTOWC): Update. Define MBRTOWC_NULL_ARG2_BUG instead of + MBRTOWC_NULL_ARG_BUG. Invoke gl_MBRTOWC_NULL_ARG1 and define + MBRTOWC_NULL_ARG1_BUG. + * lib/mbrtowc.c (rpl_mbrtowc): Use MBRTOWC_NULL_ARG2_BUG instead of + MBRTOWC_NULL_ARG_BUG. Handle MBRTOWC_NULL_ARG1_BUG. + * tests/test-mbrtowc.c (main): Test support of a NULL first argument. + * doc/posix-functions/mbrtowc.texi: Mention the Solaris 7 bug. + 2010-12-27 Jim Meyering read-file.c: tweak syntax diff --git a/doc/posix-functions/mbrtowc.texi b/doc/posix-functions/mbrtowc.texi --- a/doc/posix-functions/mbrtowc.texi +++ b/doc/posix-functions/mbrtowc.texi @@ -20,6 +20,9 @@ some platforms: Solaris 8. @item +This function fails if the @code{pwc} argument is NULL on some platforms: +Solaris 7. +@item This function does not ignore the @code{pwc} argument if the string argument is NULL on some platforms: OSF/1 5.1. diff --git a/lib/mbrtowc.c b/lib/mbrtowc.c --- a/lib/mbrtowc.c +++ b/lib/mbrtowc.c @@ -321,7 +321,7 @@ size_t rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) { -# if MBRTOWC_NULL_ARG_BUG || MBRTOWC_RETVAL_BUG +# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG if (s == NULL) { pwc = NULL; @@ -379,7 +379,16 @@ return ret; } # else - return mbrtowc (pwc, s, n, ps); + { +# if MBRTOWC_NULL_ARG1_BUG + wchar_t dummy; + + if (pwc == NULL) + pwc = &dummy; +# endif + + return mbrtowc (pwc, s, n, ps); + } # endif } diff --git a/m4/mbrtowc.m4 b/m4/mbrtowc.m4 --- a/m4/mbrtowc.m4 +++ b/m4/mbrtowc.m4 @@ -1,4 +1,4 @@ -# mbrtowc.m4 serial 20 +# mbrtowc.m4 serial 21 dnl Copyright (C) 2001-2002, 2004-2005, 2008-2010 Free Software Foundation, dnl Inc. dnl This file is free software; the Free Software Foundation @@ -19,12 +19,20 @@ if test $REPLACE_MBSTATE_T = 1; then REPLACE_MBRTOWC=1 else - gl_MBRTOWC_NULL_ARG + gl_MBRTOWC_NULL_ARG1 + gl_MBRTOWC_NULL_ARG2 gl_MBRTOWC_RETVAL gl_MBRTOWC_NUL_RETVAL - case "$gl_cv_func_mbrtowc_null_arg" in + case "$gl_cv_func_mbrtowc_null_arg1" in *yes) ;; - *) AC_DEFINE([MBRTOWC_NULL_ARG_BUG], [1], + *) AC_DEFINE([MBRTOWC_NULL_ARG1_BUG], [1], + [Define if the mbrtowc function has the NULL pwc argument bug.]) + REPLACE_MBRTOWC=1 + ;; + esac + case "$gl_cv_func_mbrtowc_null_arg2" in + *yes) ;; + *) AC_DEFINE([MBRTOWC_NULL_ARG2_BUG], [1], [Define if the mbrtowc function has the NULL string argument bug.]) REPLACE_MBRTOWC=1 ;; @@ -202,25 +210,95 @@ ]) ]) +dnl Test whether mbrtowc supports a NULL pwc argument correctly. +dnl Result is gl_cv_func_mbrtowc_null_arg1. + +AC_DEFUN([gl_MBRTOWC_NULL_ARG1], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([gt_LOCALE_FR_UTF8]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether mbrtowc handles a NULL pwc argument], + [gl_cv_func_mbrtowc_null_arg1], + [ + 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_mbrtowc_null_arg1="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_mbrtowc_null_arg1="guessing yes" ;; + esac +changequote([,])dnl + if test $LOCALE_FR_UTF8 != none; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +/* Tru64 with Desktop Toolkit C has a bug: must be included before + . + BSD/OS 4.0.1 has a bug: , and must be + included before . */ +#include +#include +#include +#include +int main () +{ + int result = 0; + + if (setlocale (LC_ALL, "$LOCALE_FR_UTF8") != NULL) + { + char input[] = "\303\237er"; + mbstate_t state; + wchar_t wc; + size_t ret; + + memset (&state, '\0', sizeof (mbstate_t)); + wc = (wchar_t) 0xBADFACE; + ret = mbrtowc (&wc, input, 5, &state); + if (ret != 2) + result |= 1; + if (!mbsinit (&state)) + result |= 2; + + memset (&state, '\0', sizeof (mbstate_t)); + ret = mbrtowc (NULL, input, 5, &state); + if (ret != 2) /* Solaris 7 fails here: ret is -1. */ + result |= 4; + if (!mbsinit (&state)) + result |= 8; + } + return result; +}]])], + [gl_cv_func_mbrtowc_null_arg1=yes], + [gl_cv_func_mbrtowc_null_arg1=no], + [:]) + fi + ]) +]) + dnl Test whether mbrtowc supports a NULL string argument correctly. -dnl Result is gl_cv_func_mbrtowc_null_arg. +dnl Result is gl_cv_func_mbrtowc_null_arg2. -AC_DEFUN([gl_MBRTOWC_NULL_ARG], +AC_DEFUN([gl_MBRTOWC_NULL_ARG2], [ AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([gt_LOCALE_FR_UTF8]) AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles AC_CACHE_CHECK([whether mbrtowc handles a NULL string argument], - [gl_cv_func_mbrtowc_null_arg], + [gl_cv_func_mbrtowc_null_arg2], [ dnl Initial guess, used when cross-compiling or when no suitable locale dnl is present. changequote(,)dnl case "$host_os" in # Guess no on OSF/1. - osf*) gl_cv_func_mbrtowc_null_arg="guessing no" ;; + osf*) gl_cv_func_mbrtowc_null_arg2="guessing no" ;; # Guess yes otherwise. - *) gl_cv_func_mbrtowc_null_arg="guessing yes" ;; + *) gl_cv_func_mbrtowc_null_arg2="guessing yes" ;; esac changequote([,])dnl if test $LOCALE_FR_UTF8 != none; then @@ -253,8 +331,8 @@ } return 0; }]])], - [gl_cv_func_mbrtowc_null_arg=yes], - [gl_cv_func_mbrtowc_null_arg=no], + [gl_cv_func_mbrtowc_null_arg2=yes], + [gl_cv_func_mbrtowc_null_arg2=no], [:]) fi ]) diff --git a/tests/test-mbrtowc.c b/tests/test-mbrtowc.c --- a/tests/test-mbrtowc.c +++ b/tests/test-mbrtowc.c @@ -1,5 +1,5 @@ /* Test of conversion of multibyte character to wide character. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008-2010 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 @@ -143,6 +143,11 @@ ASSERT (mbsinit (&state)); input[1] = '\0'; + /* Test support of NULL first argument. */ + ret = mbrtowc (NULL, input + 2, 3, &state); + ASSERT (ret == 1); + ASSERT (mbsinit (&state)); + wc = (wchar_t) 0xBADFACE; ret = mbrtowc (&wc, input + 2, 3, &state); ASSERT (ret == 1); @@ -192,6 +197,11 @@ ASSERT (mbsinit (&state)); input[2] = '\0'; + /* Test support of NULL first argument. */ + ret = mbrtowc (NULL, input + 3, 4, &state); + ASSERT (ret == 2); + ASSERT (mbsinit (&state)); + wc = (wchar_t) 0xBADFACE; ret = mbrtowc (&wc, input + 3, 4, &state); ASSERT (ret == 2); @@ -250,6 +260,11 @@ ASSERT (mbsinit (&state)); input[4] = '\0'; + /* Test support of NULL first argument. */ + ret = mbrtowc (NULL, input + 5, 3, &state); + ASSERT (ret == 2); + ASSERT (mbsinit (&state)); + wc = (wchar_t) 0xBADFACE; ret = mbrtowc (&wc, input + 5, 3, &state); ASSERT (ret == 2); @@ -293,6 +308,11 @@ ASSERT (mbsinit (&state)); input[2] = '\0'; + /* Test support of NULL first argument. */ + ret = mbrtowc (NULL, input + 3, 6, &state); + ASSERT (ret == 4); + ASSERT (mbsinit (&state)); + wc = (wchar_t) 0xBADFACE; ret = mbrtowc (&wc, input + 3, 6, &state); ASSERT (ret == 4);