]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Update gnulib files.
authorSimon Josefsson <simon@josefsson.org>
Fri, 27 Feb 2009 08:23:52 +0000 (09:23 +0100)
committerSimon Josefsson <simon@josefsson.org>
Fri, 27 Feb 2009 08:23:52 +0000 (09:23 +0100)
17 files changed:
gl/m4/gnulib-comp.m4
gl/m4/printf.m4
gl/m4/stdint.m4
gl/m4/stdlib_h.m4
gl/m4/vasnprintf.m4
gl/tests/Makefile.am
gl/tests/test-fseeko.c
gl/tests/test-getaddrinfo.c
gl/vasnprintf.c
lib/gl/m4/gnulib-comp.m4
lib/gl/m4/printf.m4
lib/gl/m4/stdint.m4
lib/gl/m4/stdlib_h.m4
lib/gl/m4/vasnprintf.m4
lib/gl/tests/Makefile.am
lib/gl/tests/test-fseeko.c
lib/gl/vasnprintf.c

index 42a1e8dfdf252982df49a6073097ce7cecabff9d..f2cc584c8a1acc565b33b22499609ac462579bc7 100644 (file)
@@ -221,6 +221,7 @@ AC_SUBST([LTALLOCA])
   m4_pushdef([gltests_LIBSOURCES_DIR], [])
   gl_COMMON
   gl_source_base='gl/tests'
+  gl_FUNC_UNGETC_WORKS
   gl_FUNC_GETTIMEOFDAY
   AC_REQUIRE([gl_HEADER_SYS_SOCKET])
   if test "$ac_cv_header_winsock2_h" = yes; then
@@ -470,6 +471,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/sys_socket_h.m4
   m4/sys_stat_h.m4
   m4/sys_time_h.m4
+  m4/ungetc.m4
   m4/unistd_h.m4
   m4/vasnprintf.m4
   m4/warnings.m4
@@ -483,6 +485,7 @@ AC_DEFUN([gl_FILE_LIST], [
   tests/test-errno.c
   tests/test-fseeko.c
   tests/test-fseeko.sh
+  tests/test-fseeko2.sh
   tests/test-getaddrinfo.c
   tests/test-getdelim.c
   tests/test-getline.c
index a1d4dadd7bb6819e7739162482fcc0b99cfc3567..4207ace49f3972687b86130c00f0cda9d427c527 100644 (file)
@@ -1,4 +1,4 @@
-# printf.m4 serial 28
+# printf.m4 serial 31
 dnl Copyright (C) 2003, 2007-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -125,7 +125,8 @@ changequote([,])dnl
 ])
 
 dnl Test whether the *printf family of functions supports infinite and NaN
-dnl 'double' arguments in the %f, %e, %g directives. (ISO C99, POSIX:2001)
+dnl 'double' arguments and negative zero arguments in the %f, %e, %g
+dnl directives. (ISO C99, POSIX:2001)
 dnl Result is gl_cv_func_printf_infinite.
 
 AC_DEFUN([gl_PRINTF_INFINITE],
@@ -156,6 +157,13 @@ strisnan (const char *string, size_t start_index, size_t end_index)
     }
   return 0;
 }
+static int
+have_minus_zero ()
+{
+  static double plus_zero = 0.0;
+  double minus_zero = - plus_zero;
+  return memcmp (&plus_zero, &minus_zero, sizeof (double)) != 0;
+}
 static char buf[10000];
 static double zero = 0.0;
 int main ()
@@ -187,6 +195,11 @@ int main ()
   if (sprintf (buf, "%g", zero / zero) < 0
       || !strisnan (buf, 0, strlen (buf)))
     return 1;
+  /* This test fails on HP-UX 10.20.  */
+  if (have_minus_zero ())
+    if (sprintf (buf, "%g", - zero) < 0
+        || strcmp (buf, "-0") != 0)
+    return 1;
   return 0;
 }], [gl_cv_func_printf_infinite=yes], [gl_cv_func_printf_infinite=no],
       [
@@ -612,6 +625,73 @@ changequote([,])dnl
     ])
 ])
 
+dnl Test whether the *printf family of functions supports the %ls format
+dnl directive and in particular, when a precision is specified, whether
+dnl the functions stop converting the wide string argument when the number
+dnl of bytes that have been produced by this conversion equals or exceeds
+dnl the precision.
+dnl Result is gl_cv_func_printf_directive_ls.
+
+AC_DEFUN([gl_PRINTF_DIRECTIVE_LS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the 'ls' directive],
+    [gl_cv_func_printf_directive_ls],
+    [
+      AC_TRY_RUN([
+/* 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>
+#include <string.h>
+int main ()
+{
+  char buf[100];
+  /* Test whether %ls works at all.
+     This test fails on OpenBSD 4.0, IRIX 6.5, Solaris 2.6, Haiku.  */
+  {
+    static const wchar_t wstring[] = { 'a', 'b', 'c', 0 };
+    buf[0] = '\0';
+    if (sprintf (buf, "%ls", wstring) < 0
+        || strcmp (buf, "abc") != 0)
+      return 1;
+  }
+  /* Test whether precisions in %ls are supported as specified in ISO C 99
+     section 7.19.6.1:
+       "If a precision is specified, no more than that many bytes are written
+        (including shift sequences, if any), and the array shall contain a
+        null wide character if, to equal the multibyte character sequence
+        length given by the precision, the function would need to access a
+        wide character one past the end of the array."
+     This test fails on Solaris 10.  */
+  {
+    static const wchar_t wstring[] = { 'a', 'b', (wchar_t) 0xfdfdfdfd, 0 };
+    buf[0] = '\0';
+    if (sprintf (buf, "%.2ls", wstring) < 0
+        || strcmp (buf, "ab") != 0)
+      return 1;
+  }
+  return 0;
+}], [gl_cv_func_printf_directive_ls=yes], [gl_cv_func_printf_directive_ls=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+         openbsd*)        gl_cv_func_printf_directive_ls="guessing no";;
+         solaris*)        gl_cv_func_printf_directive_ls="guessing no";;
+         irix*)           gl_cv_func_printf_directive_ls="guessing no";;
+         beos* | haiku*)  gl_cv_func_printf_directive_ls="guessing no";;
+         *)               gl_cv_func_printf_directive_ls="guessing yes";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
 dnl Test whether the *printf family of functions supports POSIX/XSI format
 dnl strings with positions. (POSIX:2001)
 dnl Result is gl_cv_func_printf_positions.
@@ -1261,18 +1341,19 @@ dnl 4 = gl_PRINTF_INFINITE_LONG_DOUBLE
 dnl 5 = gl_PRINTF_DIRECTIVE_A
 dnl 6 = gl_PRINTF_DIRECTIVE_F
 dnl 7 = gl_PRINTF_DIRECTIVE_N
-dnl 8 = gl_PRINTF_POSITIONS
-dnl 9 = gl_PRINTF_FLAG_GROUPING
-dnl 10 = gl_PRINTF_FLAG_LEFTADJUST
-dnl 11 = gl_PRINTF_FLAG_ZERO
-dnl 12 = gl_PRINTF_PRECISION
-dnl 13 = gl_PRINTF_ENOMEM
-dnl 14 = gl_SNPRINTF_PRESENCE
-dnl 15 = gl_SNPRINTF_TRUNCATION_C99
-dnl 16 = gl_SNPRINTF_RETVAL_C99
-dnl 17 = gl_SNPRINTF_DIRECTIVE_N
-dnl 18 = gl_SNPRINTF_SIZE1
-dnl 19 = gl_VSNPRINTF_ZEROSIZE_C99
+dnl 8 = gl_PRINTF_DIRECTIVE_LS
+dnl 9 = gl_PRINTF_POSITIONS
+dnl 10 = gl_PRINTF_FLAG_GROUPING
+dnl 11 = gl_PRINTF_FLAG_LEFTADJUST
+dnl 12 = gl_PRINTF_FLAG_ZERO
+dnl 13 = gl_PRINTF_PRECISION
+dnl 14 = gl_PRINTF_ENOMEM
+dnl 15 = gl_SNPRINTF_PRESENCE
+dnl 16 = gl_SNPRINTF_TRUNCATION_C99
+dnl 17 = gl_SNPRINTF_RETVAL_C99
+dnl 18 = gl_SNPRINTF_DIRECTIVE_N
+dnl 19 = gl_SNPRINTF_SIZE1
+dnl 20 = gl_VSNPRINTF_ZEROSIZE_C99
 dnl
 dnl 1 = checking whether printf supports size specifiers as in C99...
 dnl 2 = checking whether printf supports 'long double' arguments...
@@ -1281,42 +1362,43 @@ dnl 4 = checking whether printf supports infinite 'long double' arguments...
 dnl 5 = checking whether printf supports the 'a' and 'A' directives...
 dnl 6 = checking whether printf supports the 'F' directive...
 dnl 7 = checking whether printf supports the 'n' directive...
-dnl 8 = checking whether printf supports POSIX/XSI format strings with positions...
-dnl 9 = checking whether printf supports the grouping flag...
-dnl 10 = checking whether printf supports the left-adjust flag correctly...
-dnl 11 = checking whether printf supports the zero flag correctly...
-dnl 12 = checking whether printf supports large precisions...
-dnl 13 = checking whether printf survives out-of-memory conditions...
-dnl 14 = checking for snprintf...
-dnl 15 = checking whether snprintf truncates the result as in C99...
-dnl 16 = checking whether snprintf returns a byte count as in C99...
-dnl 17 = checking whether snprintf fully supports the 'n' directive...
-dnl 18 = checking whether snprintf respects a size of 1...
-dnl 19 = checking whether vsnprintf respects a zero size as in C99...
+dnl 8 = checking whether printf supports the 'ls' directive...
+dnl 9 = checking whether printf supports POSIX/XSI format strings with positions...
+dnl 10 = checking whether printf supports the grouping flag...
+dnl 11 = checking whether printf supports the left-adjust flag correctly...
+dnl 12 = checking whether printf supports the zero flag correctly...
+dnl 13 = checking whether printf supports large precisions...
+dnl 14 = checking whether printf survives out-of-memory conditions...
+dnl 15 = checking for snprintf...
+dnl 16 = checking whether snprintf truncates the result as in C99...
+dnl 17 = checking whether snprintf returns a byte count as in C99...
+dnl 18 = checking whether snprintf fully supports the 'n' directive...
+dnl 19 = checking whether snprintf respects a size of 1...
+dnl 20 = checking whether vsnprintf respects a zero size as in C99...
 dnl
 dnl . = yes, # = no.
 dnl
-dnl                                  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
-dnl   glibc 2.5                      .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
-dnl   glibc 2.3.6                    .  .  .  .  #  .  .  .  .  .  .  .  .  .  .  .  .  .  .
-dnl   FreeBSD 5.4, 6.1               .  .  .  .  #  .  .  .  .  .  #  .  #  .  .  .  .  .  .
-dnl   MacOS X 10.3.9                 .  .  .  .  #  .  .  .  .  .  #  .  #  .  .  .  .  .  .
-dnl   OpenBSD 3.9, 4.0               .  .  #  #  #  #  .  .  #  .  #  .  #  .  .  .  .  .  .
-dnl   Cygwin 2007 (= Cygwin 1.5.24)  .  .  .  .  #  #  .  .  .  ?  #  ?  ?  .  .  .  .  .  .
-dnl   Cygwin 2006 (= Cygwin 1.5.19)  #  .  .  .  #  #  .  .  #  ?  #  ?  ?  .  .  .  .  .  .
-dnl   Solaris 10                     .  .  #  #  #  .  .  .  .  .  #  .  .  .  .  .  .  .  .
-dnl   Solaris 2.6 ... 9              #  .  #  #  #  #  .  .  .  .  #  .  .  .  .  .  .  .  .
-dnl   Solaris 2.5.1                  #  .  #  #  #  #  .  .  .  .  #  .  .  #  #  #  #  #  #
-dnl   AIX 5.2                        .  .  #  #  #  .  .  .  .  .  #  .  .  .  .  .  .  .  .
-dnl   AIX 4.3.2, 5.1                 #  .  #  #  #  #  .  .  .  .  #  .  .  .  .  .  .  .  .
-dnl   HP-UX 11.31                    .  .  .  .  #  .  .  .  .  .  #  .  .  .  .  #  #  .  .
-dnl   HP-UX 11.{00,11,23}            #  .  .  .  #  #  .  .  .  .  #  .  .  .  .  #  #  .  #
-dnl   HP-UX 10.20                    #  .  .  .  #  #  .  .  .  #  #  .  .  .  .  #  #  ?  #
-dnl   IRIX 6.5                       #  .  #  #  #  #  .  .  .  .  #  .  .  .  .  #  .  .  .
-dnl   OSF/1 5.1                      #  .  #  #  #  #  .  .  .  .  #  .  .  .  .  #  .  .  #
-dnl   OSF/1 4.0d                     #  .  #  #  #  #  .  .  .  .  #  .  .  #  #  #  #  #  #
-dnl   NetBSD 4.0                     .  ?  ?  ?  ?  ?  .  .  ?  ?  ?  ?  ?  .  .  .  ?  ?  ?
-dnl   NetBSD 3.0                     .  .  .  .  #  #  .  #  #  ?  #  .  #  .  .  .  .  .  .
-dnl   Haiku                          .  .  .  #  #  #  .  .  .  .  .  .  ?  .  .  .  .  .  .
-dnl   BeOS                           #  #  .  #  #  #  .  #  .  ?  .  #  ?  .  .  .  .  .  .
-dnl   mingw                          #  #  #  #  #  #  .  #  #  .  #  #  ?  .  #  #  #  .  .
+dnl                                  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
+dnl   glibc 2.5                      .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
+dnl   glibc 2.3.6                    .  .  .  .  #  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
+dnl   FreeBSD 5.4, 6.1               .  .  .  .  #  .  .  .  .  .  .  #  .  #  .  .  .  .  .  .
+dnl   MacOS X 10.3.9                 .  .  .  .  #  .  .  .  .  .  .  #  .  #  .  .  .  .  .  .
+dnl   OpenBSD 3.9, 4.0               .  .  #  #  #  #  .  #  .  #  .  #  .  #  .  .  .  .  .  .
+dnl   Cygwin 2007 (= Cygwin 1.5.24)  .  .  .  .  #  #  .  .  .  .  ?  #  ?  ?  .  .  .  .  .  .
+dnl   Cygwin 2006 (= Cygwin 1.5.19)  #  .  .  .  #  #  .  ?  .  #  ?  #  ?  ?  .  .  .  .  .  .
+dnl   Solaris 10                     .  .  #  #  #  .  .  #  .  .  .  #  .  .  .  .  .  .  .  .
+dnl   Solaris 2.6 ... 9              #  .  #  #  #  #  .  #  .  .  .  #  .  .  .  .  .  .  .  .
+dnl   Solaris 2.5.1                  #  .  #  #  #  #  .  #  .  .  .  #  .  .  #  #  #  #  #  #
+dnl   AIX 5.2                        .  .  #  #  #  .  .  .  .  .  .  #  .  .  .  .  .  .  .  .
+dnl   AIX 4.3.2, 5.1                 #  .  #  #  #  #  .  .  .  .  .  #  .  .  .  .  .  .  .  .
+dnl   HP-UX 11.31                    .  .  .  .  #  .  .  .  .  .  .  #  .  .  .  .  #  #  .  .
+dnl   HP-UX 11.{00,11,23}            #  .  .  .  #  #  .  .  .  .  .  #  .  .  .  .  #  #  .  #
+dnl   HP-UX 10.20                    #  .  #  .  #  #  .  ?  .  .  #  #  .  .  .  .  #  #  ?  #
+dnl   IRIX 6.5                       #  .  #  #  #  #  .  #  .  .  .  #  .  .  .  .  #  .  .  .
+dnl   OSF/1 5.1                      #  .  #  #  #  #  .  .  .  .  .  #  .  .  .  .  #  .  .  #
+dnl   OSF/1 4.0d                     #  .  #  #  #  #  .  .  .  .  .  #  .  .  #  #  #  #  #  #
+dnl   NetBSD 4.0                     .  ?  ?  ?  ?  ?  .  ?  .  ?  ?  ?  ?  ?  .  .  .  ?  ?  ?
+dnl   NetBSD 3.0                     .  .  .  .  #  #  .  ?  #  #  ?  #  .  #  .  .  .  .  .  .
+dnl   Haiku                          .  .  .  #  #  #  .  #  .  .  .  .  .  ?  .  .  .  .  .  .
+dnl   BeOS                           #  #  .  #  #  #  .  ?  #  .  ?  .  #  ?  .  .  .  .  .  .
+dnl   mingw                          #  #  #  #  #  #  .  .  #  #  .  #  #  ?  .  #  #  #  .  .
index b4194c8adc129667a648e882d2381a8b971a9dd6..a2e8bdd62814a97e7be2875fd8f3cbf3b4c4ba8f 100644 (file)
@@ -1,4 +1,4 @@
-# stdint.m4 serial 33
+# stdint.m4 serial 34
 dnl Copyright (C) 2001-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -201,7 +201,75 @@ struct s {
   int check_size: (size_t) -1 == SIZE_MAX ? 1 : -1;
 };
          ]])],
-         [gl_cv_header_working_stdint_h=yes])])
+         [dnl Determine whether the various *_MIN, *_MAX macros are usable
+          dnl in preprocessor expression. We could do it by compiling a test
+          dnl program for each of these macros. It is faster to run a program
+          dnl that inspects the macro expansion.
+          dnl This detects a bug on HP-UX 11.23/ia64.
+          AC_RUN_IFELSE([
+            AC_LANG_PROGRAM([[
+#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */
+#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */
+#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */
+#include <stdint.h>
+]
+gl_STDINT_INCLUDES
+[
+#include <stdio.h>
+#include <string.h>
+#define MVAL(macro) MVAL1(macro)
+#define MVAL1(expression) #expression
+static const char *macro_values[] =
+  {
+#ifdef INT8_MAX
+    MVAL (INT8_MAX),
+#endif
+#ifdef INT16_MAX
+    MVAL (INT16_MAX),
+#endif
+#ifdef INT32_MAX
+    MVAL (INT32_MAX),
+#endif
+#ifdef INT64_MAX
+    MVAL (INT64_MAX),
+#endif
+#ifdef UINT8_MAX
+    MVAL (UINT8_MAX),
+#endif
+#ifdef UINT16_MAX
+    MVAL (UINT16_MAX),
+#endif
+#ifdef UINT32_MAX
+    MVAL (UINT32_MAX),
+#endif
+#ifdef UINT64_MAX
+    MVAL (UINT64_MAX),
+#endif
+    NULL
+  };
+]], [[
+  const char **mv;
+  for (mv = macro_values; *mv != NULL; mv++)
+    {
+      const char *value = *mv;
+      /* Test whether it looks like a cast expression.  */
+      if (strncmp (value, "((unsigned int)"/*)*/, 15) == 0
+          || strncmp (value, "((unsigned short)"/*)*/, 17) == 0
+          || strncmp (value, "((unsigned char)"/*)*/, 16) == 0
+          || strncmp (value, "((int)"/*)*/, 6) == 0
+          || strncmp (value, "((signed short)"/*)*/, 15) == 0
+          || strncmp (value, "((signed char)"/*)*/, 14) == 0)
+        return 1;
+    }
+  return 0;
+]])],
+              [gl_cv_header_working_stdint_h=yes],
+              [],
+              [dnl When cross-compiling, assume it works.
+               gl_cv_header_working_stdint_h=yes
+              ])
+         ])
+      ])
   fi
   if test "$gl_cv_header_working_stdint_h" = yes; then
     STDINT_H=
index 515befeb7e962adf71c50171bf854d0a3402ca1e..b295f16b2797a03bdd21abd9dbd0d25fc57c0ffa 100644 (file)
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 14
+# stdlib_h.m4 serial 15
 dnl Copyright (C) 2007-2009 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,7 @@ AC_DEFUN([gl_STDLIB_H],
 [
   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
   gl_CHECK_NEXT_HEADERS([stdlib.h])
-  AC_CHECK_HEADERS([random.h])
+  AC_CHECK_HEADERS([random.h], [], [], [AC_INCLUDES_DEFAULT])
   if test $ac_cv_header_random_h = yes; then
     HAVE_RANDOM_H=1
   else
index 9e839d2bc8d096080b8e5f0c364a1ec70eb10869..01e8772f11c086dd435aed60b65d930d48875826 100644 (file)
@@ -1,4 +1,4 @@
-# vasnprintf.m4 serial 26
+# vasnprintf.m4 serial 28
 dnl Copyright (C) 2002-2004, 2006-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -58,7 +58,7 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF],
   AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
   AC_REQUIRE([gt_TYPE_WCHAR_T])
   AC_REQUIRE([gt_TYPE_WINT_T])
-  AC_CHECK_FUNCS([snprintf wcslen])
+  AC_CHECK_FUNCS([snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb])
   dnl Use the _snprintf function only if it is declared (because on NetBSD it
   dnl is defined as a weak alias of snprintf; we prefer to use the latter).
   AC_CHECK_DECLS([_snprintf], , , [#include <stdio.h>])
@@ -150,6 +150,21 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_F],
   esac
 ])
 
+# Extra prerequisites of lib/vasnprintf.c for supporting the 'ls' directive.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_LS],
+[
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS])
+  case "$gl_cv_func_printf_directive_ls" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_DIRECTIVE_LS], [1],
+        [Define if the vasnprintf implementation needs special code for
+         the 'ls' directive.])
+      ;;
+  esac
+])
+
 # Extra prerequisites of lib/vasnprintf.c for supporting the ' flag.
 AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_GROUPING],
 [
@@ -247,6 +262,7 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS],
   gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE
   gl_PREREQ_VASNPRINTF_DIRECTIVE_A
   gl_PREREQ_VASNPRINTF_DIRECTIVE_F
+  gl_PREREQ_VASNPRINTF_DIRECTIVE_LS
   gl_PREREQ_VASNPRINTF_FLAG_GROUPING
   gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST
   gl_PREREQ_VASNPRINTF_FLAG_ZERO
index d9cda94fe19dee376ad798650f480600fc54ea9e..db02b328a8a210e46073974eaebd932fdffcfb83 100644 (file)
@@ -80,10 +80,10 @@ EXTRA_DIST += test-errno.c
 
 ## begin gnulib module fseeko-tests
 
-TESTS += test-fseeko.sh
+TESTS += test-fseeko.sh test-fseeko2.sh
 TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'
 check_PROGRAMS += test-fseeko
-EXTRA_DIST += test-fseeko.c test-fseeko.sh
+EXTRA_DIST += test-fseeko.c test-fseeko.sh test-fseeko2.sh
 
 ## end   gnulib module fseeko-tests
 
index 3a1383b3d335ac31a23d89485402b9684aba1cb1..9c284da50061d8b12c64dad672f38a301a38d131 100644 (file)
@@ -1,5 +1,5 @@
 /* Test of fseeko() function.
-   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008, 2009 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
     }                                                                       \
   while (0)
 
+#ifndef FUNC_UNGETC_BROKEN
+# define FUNC_UNGETC_BROKEN 0
+#endif
+
 int
 main (int argc, char **argv)
 {
@@ -50,10 +54,19 @@ main (int argc, char **argv)
       ASSERT (ch == '#');
       ASSERT (ungetc (ch, stdin) == ch);
       ASSERT (fseeko (stdin, 2, SEEK_SET) == 0);
-      /* Test that fseek discards random ungetc data.  */
       ch = fgetc (stdin);
       ASSERT (ch == '/');
-      ASSERT (ungetc (ch ^ 0xff, stdin) == (ch ^ 0xff));
+      if (2 < argc)
+        {
+          if (FUNC_UNGETC_BROKEN)
+            {
+              fputs ("Skipping test: ungetc cannot handle arbitrary bytes\n",
+                     stderr);
+              return 77;
+            }
+          /* Test that fseek discards random ungetc data.  */
+          ASSERT (ungetc (ch ^ 0xff, stdin) == (ch ^ 0xff));
+        }
       ASSERT (fseeko (stdin, 0, SEEK_END) == 0);
       ASSERT (fgetc (stdin) == EOF);
       /* Test that fseek resets end-of-file marker.  */
index a8b2fd5d4615cb2166061b05fe3a4e0f46d64df9..5e33bb24f18260be25736c15bcf034e14e8ccb49 100644 (file)
 int simple (char *host, char *service)
 {
   char buf[BUFSIZ];
+  static int skip = 0;
   struct addrinfo hints;
   struct addrinfo *ai0, *ai;
   int res;
 
+  /* Once we skipped the test, do not try anything else */
+  if (skip)
+    return 0;
+
   dbgprintf ("Finding %s service %s...\n", host, service);
 
   /* This initializes "hints" but does not use it.  Is there a reason
@@ -69,6 +74,7 @@ int simple (char *host, char *service)
         in-law's farm. */
       if (res == EAI_AGAIN)
        {
+         skip++;
          fprintf (stderr, "skipping getaddrinfo test: no network?\n");
          return 77;
        }
index 93aef6f291f5fb98dffb3f35cda16946f8c78af4..1b9d5ded743770dde225428199e6e47e9c270a73 100644 (file)
@@ -1,5 +1,5 @@
 /* vsprintf with automatic memory allocation.
-   Copyright (C) 1999, 2002-2008 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002-2009 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
 # include "fpucw.h"
 #endif
 
-#if HAVE_WCHAR_T
-# if HAVE_WCSLEN
-#  define local_wcslen wcslen
-# else
-   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
-      a dependency towards this library, here is a local substitute.
-      Define this substitute only once, even if this file is included
-      twice in the same compilation unit.  */
-#  ifndef local_wcslen_defined
-#   define local_wcslen_defined 1
-static size_t
-local_wcslen (const wchar_t *s)
-{
-  const wchar_t *ptr;
-
-  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
-    ;
-  return ptr - s;
-}
-#  endif
-# endif
-#endif
-
 /* Default parameters.  */
 #ifndef VASNPRINTF
 # if WIDE_CHAR_VERSION
@@ -152,6 +129,7 @@ local_wcslen (const wchar_t *s)
 #  define DIRECTIVES wchar_t_directives
 #  define PRINTF_PARSE wprintf_parse
 #  define DCHAR_CPY wmemcpy
+#  define DCHAR_SET wmemset
 # else
 #  define VASNPRINTF vasnprintf
 #  define FCHAR_T char
@@ -162,6 +140,7 @@ local_wcslen (const wchar_t *s)
 #  define DIRECTIVES char_directives
 #  define PRINTF_PARSE printf_parse
 #  define DCHAR_CPY memcpy
+#  define DCHAR_SET memset
 # endif
 #endif
 #if WIDE_CHAR_VERSION
@@ -215,6 +194,64 @@ local_wcslen (const wchar_t *s)
 #undef remainder
 #define remainder rem
 
+#if !USE_SNPRINTF && !WIDE_CHAR_VERSION
+# if (HAVE_STRNLEN && !defined _AIX)
+#  define local_strnlen strnlen
+# else
+#  ifndef local_strnlen_defined
+#   define local_strnlen_defined 1
+static size_t
+local_strnlen (const char *string, size_t maxlen)
+{
+  const char *end = memchr (string, '\0', maxlen);
+  return end ? (size_t) (end - string) : maxlen;
+}
+#  endif
+# endif
+#endif
+
+#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T && (WIDE_CHAR_VERSION || DCHAR_IS_TCHAR)
+# if HAVE_WCSLEN
+#  define local_wcslen wcslen
+# else
+   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
+      a dependency towards this library, here is a local substitute.
+      Define this substitute only once, even if this file is included
+      twice in the same compilation unit.  */
+#  ifndef local_wcslen_defined
+#   define local_wcslen_defined 1
+static size_t
+local_wcslen (const wchar_t *s)
+{
+  const wchar_t *ptr;
+
+  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
+    ;
+  return ptr - s;
+}
+#  endif
+# endif
+#endif
+
+#if !USE_SNPRINTF && HAVE_WCHAR_T && WIDE_CHAR_VERSION
+# if HAVE_WCSNLEN
+#  define local_wcsnlen wcsnlen
+# else
+#  ifndef local_wcsnlen_defined
+#   define local_wcsnlen_defined 1
+static size_t
+local_wcsnlen (const wchar_t *s, size_t maxlen)
+{
+  const wchar_t *ptr;
+
+  for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
+    ;
+  return ptr - s;
+}
+#  endif
+# endif
+#endif
+
 #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
 /* Determine the decimal-point character according to the current locale.  */
 # ifndef decimal_point_char_defined
@@ -2066,6 +2103,523 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                  }
              }
 #endif
+#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
+           else if (dp->conversion == 's'
+# if WIDE_CHAR_VERSION
+                    && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
+# else
+                    && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
+# endif
+                   )
+             {
+               /* The normal handling of the 's' directive below requires
+                  allocating a temporary buffer.  The determination of its
+                  length (tmp_length), in the case when a precision is
+                  specified, below requires a conversion between a char[]
+                  string and a wchar_t[] wide string.  It could be done, but
+                  we have no guarantee that the implementation of sprintf will
+                  use the exactly same algorithm.  Without this guarantee, it
+                  is possible to have buffer overrun bugs.  In order to avoid
+                  such bugs, we implement the entire processing of the 's'
+                  directive ourselves.  */
+               int flags = dp->flags;
+               int has_width;
+               size_t width;
+               int has_precision;
+               size_t precision;
+
+               has_width = 0;
+               width = 0;
+               if (dp->width_start != dp->width_end)
+                 {
+                   if (dp->width_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->width_arg_index].a.a_int;
+                       if (arg < 0)
+                         {
+                           /* "A negative field width is taken as a '-' flag
+                               followed by a positive field width."  */
+                           flags |= FLAG_LEFT;
+                           width = (unsigned int) (-arg);
+                         }
+                       else
+                         width = arg;
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->width_start;
+
+                       do
+                         width = xsum (xtimes (width, 10), *digitp++ - '0');
+                       while (digitp != dp->width_end);
+                     }
+                   has_width = 1;
+                 }
+
+               has_precision = 0;
+               precision = 6;
+               if (dp->precision_start != dp->precision_end)
+                 {
+                   if (dp->precision_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->precision_arg_index].a.a_int;
+                       /* "A negative precision is taken as if the precision
+                           were omitted."  */
+                       if (arg >= 0)
+                         {
+                           precision = arg;
+                           has_precision = 1;
+                         }
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->precision_start + 1;
+
+                       precision = 0;
+                       while (digitp != dp->precision_end)
+                         precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+                       has_precision = 1;
+                     }
+                 }
+
+# if WIDE_CHAR_VERSION
+               /* %s in vasnwprintf.  See the specification of fwprintf.  */
+               {
+                 const char *arg = a.arg[dp->arg_index].a.a_string;
+                 const char *arg_end;
+                 size_t characters;
+
+                 if (has_precision)
+                   {
+                     /* Use only as many bytes as needed to produce PRECISION
+                        wide characters, from the left.  */
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     for (; precision > 0; precision--)
+                       {
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrlen (arg_end, MB_CUR_MAX, &state);
+#  else
+                         count = mblen (arg_end, MB_CUR_MAX);
+#  endif
+                         if (count == 0)
+                           /* Found the terminating NUL.  */
+                           break;
+                         if (count < 0)
+                           {
+                             /* Invalid or incomplete multibyte character.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         arg_end += count;
+                         characters++;
+                       }
+                   }
+                 else if (has_width)
+                   {
+                     /* Use the entire string, and count the number of wide
+                        characters.  */
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     for (;;)
+                       {
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrlen (arg_end, MB_CUR_MAX, &state);
+#  else
+                         count = mblen (arg_end, MB_CUR_MAX);
+#  endif
+                         if (count == 0)
+                           /* Found the terminating NUL.  */
+                           break;
+                         if (count < 0)
+                           {
+                             /* Invalid or incomplete multibyte character.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         arg_end += count;
+                         characters++;
+                       }
+                   }
+                 else
+                   {
+                     /* Use the entire string.  */
+                     arg_end = arg + strlen (arg);
+                     /* The number of characters doesn't matter.  */
+                     characters = 0;
+                   }
+
+                 if (has_width && width > characters
+                     && !(dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - characters;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+
+                 if (has_precision || has_width)
+                   {
+                     /* We know the number of wide characters in advance.  */
+                     size_t remaining;
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     ENSURE_ALLOCATION (xsum (length, characters));
+                     for (remaining = characters; remaining > 0; remaining--)
+                       {
+                         wchar_t wc;
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrtowc (&wc, arg, arg_end - arg, &state);
+#  else
+                         count = mbtowc (&wc, arg, arg_end - arg);
+#  endif
+                         if (count <= 0)
+                           /* mbrtowc not consistent with mbrlen, or mbtowc
+                              not consistent with mblen.  */
+                           abort ();
+                         result[length++] = wc;
+                         arg += count;
+                       }
+                     if (!(arg == arg_end))
+                       abort ();
+                   }
+                 else
+                   {
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     while (arg < arg_end)
+                       {
+                         wchar_t wc;
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrtowc (&wc, arg, arg_end - arg, &state);
+#  else
+                         count = mbtowc (&wc, arg, arg_end - arg);
+#  endif
+                         if (count <= 0)
+                           /* mbrtowc not consistent with mbrlen, or mbtowc
+                              not consistent with mblen.  */
+                           abort ();
+                         ENSURE_ALLOCATION (xsum (length, 1));
+                         result[length++] = wc;
+                         arg += count;
+                       }
+                   }
+
+                 if (has_width && width > characters
+                     && (dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - characters;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+               }
+# else
+               /* %ls in vasnprintf.  See the specification of fprintf.  */
+               {
+                 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
+                 const wchar_t *arg_end;
+                 size_t characters;
+#  if !DCHAR_IS_TCHAR
+                 /* This code assumes that TCHAR_T is 'char'.  */
+                 typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1];
+                 TCHAR_T *tmpsrc;
+                 DCHAR_T *tmpdst;
+                 size_t tmpdst_len;
+#  endif
+                 size_t w;
+
+                 if (has_precision)
+                   {
+                     /* Use only as many wide characters as needed to produce
+                        at most PRECISION bytes, from the left.  */
+#  if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     while (precision > 0)
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg_end == 0)
+                           /* Found the terminating null wide character.  */
+                           break;
+#  if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg_end, &state);
+#  else
+                         count = wctomb (buf, *arg_end);
+#  endif
+                         if (count < 0)
+                           {
+                             /* Cannot convert.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         if (precision < count)
+                           break;
+                         arg_end++;
+                         characters += count;
+                         precision -= count;
+                       }
+                   }
+#  if DCHAR_IS_TCHAR
+                 else if (has_width)
+#  else
+                 else
+#  endif
+                   {
+                     /* Use the entire string, and count the number of
+                        bytes.  */
+#  if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     for (;;)
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg_end == 0)
+                           /* Found the terminating null wide character.  */
+                           break;
+#  if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg_end, &state);
+#  else
+                         count = wctomb (buf, *arg_end);
+#  endif
+                         if (count < 0)
+                           {
+                             /* Cannot convert.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         arg_end++;
+                         characters += count;
+                       }
+                   }
+#  if DCHAR_IS_TCHAR
+                 else
+                   {
+                     /* Use the entire string.  */
+                     arg_end = arg + local_wcslen (arg);
+                     /* The number of bytes doesn't matter.  */
+                     characters = 0;
+                   }
+#  endif
+
+#  if !DCHAR_IS_TCHAR
+                 /* Convert the string into a piece of temporary memory.  */
+                 tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
+                 if (tmpsrc == NULL)
+                   goto out_of_memory;
+                 {
+                   TCHAR_T *tmpptr = tmpsrc;
+                   size_t remaining;
+#   if HAVE_WCRTOMB
+                   mbstate_t state;
+                   memset (&state, '\0', sizeof (mbstate_t));
+#   endif
+                   for (remaining = characters; remaining > 0; )
+                     {
+                       char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                       int count;
+
+                       if (*arg == 0)
+                         abort ();
+#   if HAVE_WCRTOMB
+                       count = wcrtomb (buf, *arg, &state);
+#   else
+                       count = wctomb (buf, *arg);
+#   endif
+                       if (count <= 0)
+                         /* Inconsistency.  */
+                         abort ();
+                       memcpy (tmpptr, buf, count);
+                       tmpptr += count;
+                       arg++;
+                       remaining -= count;
+                     }
+                   if (!(arg == arg_end))
+                     abort ();
+                 }
+
+                 /* Convert from TCHAR_T[] to DCHAR_T[].  */
+                 tmpdst = NULL;
+                 tmpdst_len = 0;
+                 if (DCHAR_CONV_FROM_ENCODING (locale_charset (),
+                                               iconveh_question_mark,
+                                               tmpsrc, characters,
+                                               NULL,
+                                               &tmpdst, &tmpdst_len)
+                     < 0)
+                   {
+                     int saved_errno = errno;
+                     free (tmpsrc);
+                     if (!(result == resultbuf || result == NULL))
+                       free (result);
+                     if (buf_malloced != NULL)
+                       free (buf_malloced);
+                     CLEANUP ();
+                     errno = saved_errno;
+                     return NULL;
+                   }
+                 free (tmpsrc);
+#  endif
+
+                 if (has_width)
+                   {
+#  if ENABLE_UNISTDIO
+                     /* Outside POSIX, it's preferrable to compare the width
+                        against the number of _characters_ of the converted
+                        value.  */
+                     w = DCHAR_MBSNLEN (result + length, characters);
+#  else
+                     /* The width is compared against the number of _bytes_
+                        of the converted value, says POSIX.  */
+                     w = characters;
+#  endif
+                   }
+                 else
+                   /* w doesn't matter.  */
+                   w = 0;
+
+                 if (has_width && width > w
+                     && !(dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - w;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+
+#  if DCHAR_IS_TCHAR
+                 if (has_precision || has_width)
+                   {
+                     /* We know the number of bytes in advance.  */
+                     size_t remaining;
+#   if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#   endif
+                     ENSURE_ALLOCATION (xsum (length, characters));
+                     for (remaining = characters; remaining > 0; )
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg == 0)
+                           abort ();
+#   if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg, &state);
+#   else
+                         count = wctomb (buf, *arg);
+#   endif
+                         if (count <= 0)
+                           /* Inconsistency.  */
+                           abort ();
+                         memcpy (result + length, buf, count);
+                         length += count;
+                         arg++;
+                         remaining -= count;
+                       }
+                     if (!(arg == arg_end))
+                       abort ();
+                   }
+                 else
+                   {
+#   if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#   endif
+                     while (arg < arg_end)
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg == 0)
+                           abort ();
+#   if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg, &state);
+#   else
+                         count = wctomb (buf, *arg);
+#   endif
+                         if (count <= 0)
+                           /* Inconsistency.  */
+                           abort ();
+                         ENSURE_ALLOCATION (xsum (length, count));
+                         memcpy (result + length, buf, count);
+                         length += count;
+                         arg++;
+                       }
+                   }
+#  else
+                 ENSURE_ALLOCATION (xsum (length, tmpdst_len));
+                 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
+                 free (tmpdst);
+                 length += tmpdst_len;
+#  endif
+
+                 if (has_width && width > w
+                     && (dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - w;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+               }
+             }
+# endif
+#endif
 #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
            else if ((dp->conversion == 'a' || dp->conversion == 'A')
 # if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
@@ -4032,16 +4586,64 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 # if HAVE_WCHAR_T
                      if (type == TYPE_WIDE_STRING)
                        {
-                         tmp_length =
-                           local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
-
-#  if !WIDE_CHAR_VERSION
-                         tmp_length = xtimes (tmp_length, MB_CUR_MAX);
+#  if WIDE_CHAR_VERSION
+                         /* ISO C says about %ls in fwprintf:
+                              "If the precision is not specified or is greater
+                               than the size of the array, the array shall
+                               contain a null wide character."
+                            So if there is a precision, we must not use
+                            wcslen.  */
+                         const wchar_t *arg =
+                           a.arg[dp->arg_index].a.a_wide_string;
+
+                         if (has_precision)
+                           tmp_length = local_wcsnlen (arg, precision);
+                         else
+                           tmp_length = local_wcslen (arg);
+#  else
+                         /* ISO C says about %ls in fprintf:
+                              "If a precision is specified, no more than that
+                               many bytes are written (including shift
+                               sequences, if any), and the array shall contain
+                               a null wide character if, to equal the
+                               multibyte character sequence length given by
+                               the precision, the function would need to
+                               access a wide character one past the end of the
+                               array."
+                            So if there is a precision, we must not use
+                            wcslen.  */
+                         /* This case has already been handled above.  */
+                         abort ();
 #  endif
                        }
                      else
 # endif
-                       tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
+                       {
+# if WIDE_CHAR_VERSION
+                         /* ISO C says about %s in fwprintf:
+                              "If the precision is not specified or is greater
+                               than the size of the converted array, the
+                               converted array shall contain a null wide
+                               character."
+                            So if there is a precision, we must not use
+                            strlen.  */
+                         /* This case has already been handled above.  */
+                         abort ();
+# else
+                         /* ISO C says about %s in fprintf:
+                              "If the precision is not specified or greater
+                               than the size of the array, the array shall
+                               contain a null character."
+                            So if there is a precision, we must not use
+                            strlen.  */
+                         const char *arg = a.arg[dp->arg_index].a.a_string;
+
+                         if (has_precision)
+                           tmp_length = local_strnlen (arg, precision);
+                         else
+                           tmp_length = strlen (arg);
+# endif
+                       }
                      break;
 
                    case 'p':
index 10283237821bf9eb7e0577f3d8879e0f80938023..77ca8b8fd914db0e92b2f34f2a239c9a67ae5d80 100644 (file)
@@ -133,6 +133,7 @@ AC_DEFUN([lgl_INIT],
   m4_pushdef([lgltests_LIBSOURCES_DIR], [])
   gl_COMMON
   gl_source_base='lib/gl/tests'
+  gl_FUNC_UNGETC_WORKS
   gt_TYPE_WCHAR_T
   gt_TYPE_WINT_T
   AC_CHECK_FUNCS([shutdown])
@@ -341,6 +342,7 @@ AC_DEFUN([lgl_FILE_LIST], [
   m4/time_h.m4
   m4/time_r.m4
   m4/uintmax_t.m4
+  m4/ungetc.m4
   m4/unistd_h.m4
   m4/vasnprintf.m4
   m4/vasprintf.m4
@@ -355,6 +357,7 @@ AC_DEFUN([lgl_FILE_LIST], [
   tests/test-errno.c
   tests/test-fseeko.c
   tests/test-fseeko.sh
+  tests/test-fseeko2.sh
   tests/test-func.c
   tests/test-lseek.c
   tests/test-lseek.sh
index a1d4dadd7bb6819e7739162482fcc0b99cfc3567..4207ace49f3972687b86130c00f0cda9d427c527 100644 (file)
@@ -1,4 +1,4 @@
-# printf.m4 serial 28
+# printf.m4 serial 31
 dnl Copyright (C) 2003, 2007-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -125,7 +125,8 @@ changequote([,])dnl
 ])
 
 dnl Test whether the *printf family of functions supports infinite and NaN
-dnl 'double' arguments in the %f, %e, %g directives. (ISO C99, POSIX:2001)
+dnl 'double' arguments and negative zero arguments in the %f, %e, %g
+dnl directives. (ISO C99, POSIX:2001)
 dnl Result is gl_cv_func_printf_infinite.
 
 AC_DEFUN([gl_PRINTF_INFINITE],
@@ -156,6 +157,13 @@ strisnan (const char *string, size_t start_index, size_t end_index)
     }
   return 0;
 }
+static int
+have_minus_zero ()
+{
+  static double plus_zero = 0.0;
+  double minus_zero = - plus_zero;
+  return memcmp (&plus_zero, &minus_zero, sizeof (double)) != 0;
+}
 static char buf[10000];
 static double zero = 0.0;
 int main ()
@@ -187,6 +195,11 @@ int main ()
   if (sprintf (buf, "%g", zero / zero) < 0
       || !strisnan (buf, 0, strlen (buf)))
     return 1;
+  /* This test fails on HP-UX 10.20.  */
+  if (have_minus_zero ())
+    if (sprintf (buf, "%g", - zero) < 0
+        || strcmp (buf, "-0") != 0)
+    return 1;
   return 0;
 }], [gl_cv_func_printf_infinite=yes], [gl_cv_func_printf_infinite=no],
       [
@@ -612,6 +625,73 @@ changequote([,])dnl
     ])
 ])
 
+dnl Test whether the *printf family of functions supports the %ls format
+dnl directive and in particular, when a precision is specified, whether
+dnl the functions stop converting the wide string argument when the number
+dnl of bytes that have been produced by this conversion equals or exceeds
+dnl the precision.
+dnl Result is gl_cv_func_printf_directive_ls.
+
+AC_DEFUN([gl_PRINTF_DIRECTIVE_LS],
+[
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CACHE_CHECK([whether printf supports the 'ls' directive],
+    [gl_cv_func_printf_directive_ls],
+    [
+      AC_TRY_RUN([
+/* 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>
+#include <string.h>
+int main ()
+{
+  char buf[100];
+  /* Test whether %ls works at all.
+     This test fails on OpenBSD 4.0, IRIX 6.5, Solaris 2.6, Haiku.  */
+  {
+    static const wchar_t wstring[] = { 'a', 'b', 'c', 0 };
+    buf[0] = '\0';
+    if (sprintf (buf, "%ls", wstring) < 0
+        || strcmp (buf, "abc") != 0)
+      return 1;
+  }
+  /* Test whether precisions in %ls are supported as specified in ISO C 99
+     section 7.19.6.1:
+       "If a precision is specified, no more than that many bytes are written
+        (including shift sequences, if any), and the array shall contain a
+        null wide character if, to equal the multibyte character sequence
+        length given by the precision, the function would need to access a
+        wide character one past the end of the array."
+     This test fails on Solaris 10.  */
+  {
+    static const wchar_t wstring[] = { 'a', 'b', (wchar_t) 0xfdfdfdfd, 0 };
+    buf[0] = '\0';
+    if (sprintf (buf, "%.2ls", wstring) < 0
+        || strcmp (buf, "ab") != 0)
+      return 1;
+  }
+  return 0;
+}], [gl_cv_func_printf_directive_ls=yes], [gl_cv_func_printf_directive_ls=no],
+      [
+changequote(,)dnl
+       case "$host_os" in
+         openbsd*)        gl_cv_func_printf_directive_ls="guessing no";;
+         solaris*)        gl_cv_func_printf_directive_ls="guessing no";;
+         irix*)           gl_cv_func_printf_directive_ls="guessing no";;
+         beos* | haiku*)  gl_cv_func_printf_directive_ls="guessing no";;
+         *)               gl_cv_func_printf_directive_ls="guessing yes";;
+       esac
+changequote([,])dnl
+      ])
+    ])
+])
+
 dnl Test whether the *printf family of functions supports POSIX/XSI format
 dnl strings with positions. (POSIX:2001)
 dnl Result is gl_cv_func_printf_positions.
@@ -1261,18 +1341,19 @@ dnl 4 = gl_PRINTF_INFINITE_LONG_DOUBLE
 dnl 5 = gl_PRINTF_DIRECTIVE_A
 dnl 6 = gl_PRINTF_DIRECTIVE_F
 dnl 7 = gl_PRINTF_DIRECTIVE_N
-dnl 8 = gl_PRINTF_POSITIONS
-dnl 9 = gl_PRINTF_FLAG_GROUPING
-dnl 10 = gl_PRINTF_FLAG_LEFTADJUST
-dnl 11 = gl_PRINTF_FLAG_ZERO
-dnl 12 = gl_PRINTF_PRECISION
-dnl 13 = gl_PRINTF_ENOMEM
-dnl 14 = gl_SNPRINTF_PRESENCE
-dnl 15 = gl_SNPRINTF_TRUNCATION_C99
-dnl 16 = gl_SNPRINTF_RETVAL_C99
-dnl 17 = gl_SNPRINTF_DIRECTIVE_N
-dnl 18 = gl_SNPRINTF_SIZE1
-dnl 19 = gl_VSNPRINTF_ZEROSIZE_C99
+dnl 8 = gl_PRINTF_DIRECTIVE_LS
+dnl 9 = gl_PRINTF_POSITIONS
+dnl 10 = gl_PRINTF_FLAG_GROUPING
+dnl 11 = gl_PRINTF_FLAG_LEFTADJUST
+dnl 12 = gl_PRINTF_FLAG_ZERO
+dnl 13 = gl_PRINTF_PRECISION
+dnl 14 = gl_PRINTF_ENOMEM
+dnl 15 = gl_SNPRINTF_PRESENCE
+dnl 16 = gl_SNPRINTF_TRUNCATION_C99
+dnl 17 = gl_SNPRINTF_RETVAL_C99
+dnl 18 = gl_SNPRINTF_DIRECTIVE_N
+dnl 19 = gl_SNPRINTF_SIZE1
+dnl 20 = gl_VSNPRINTF_ZEROSIZE_C99
 dnl
 dnl 1 = checking whether printf supports size specifiers as in C99...
 dnl 2 = checking whether printf supports 'long double' arguments...
@@ -1281,42 +1362,43 @@ dnl 4 = checking whether printf supports infinite 'long double' arguments...
 dnl 5 = checking whether printf supports the 'a' and 'A' directives...
 dnl 6 = checking whether printf supports the 'F' directive...
 dnl 7 = checking whether printf supports the 'n' directive...
-dnl 8 = checking whether printf supports POSIX/XSI format strings with positions...
-dnl 9 = checking whether printf supports the grouping flag...
-dnl 10 = checking whether printf supports the left-adjust flag correctly...
-dnl 11 = checking whether printf supports the zero flag correctly...
-dnl 12 = checking whether printf supports large precisions...
-dnl 13 = checking whether printf survives out-of-memory conditions...
-dnl 14 = checking for snprintf...
-dnl 15 = checking whether snprintf truncates the result as in C99...
-dnl 16 = checking whether snprintf returns a byte count as in C99...
-dnl 17 = checking whether snprintf fully supports the 'n' directive...
-dnl 18 = checking whether snprintf respects a size of 1...
-dnl 19 = checking whether vsnprintf respects a zero size as in C99...
+dnl 8 = checking whether printf supports the 'ls' directive...
+dnl 9 = checking whether printf supports POSIX/XSI format strings with positions...
+dnl 10 = checking whether printf supports the grouping flag...
+dnl 11 = checking whether printf supports the left-adjust flag correctly...
+dnl 12 = checking whether printf supports the zero flag correctly...
+dnl 13 = checking whether printf supports large precisions...
+dnl 14 = checking whether printf survives out-of-memory conditions...
+dnl 15 = checking for snprintf...
+dnl 16 = checking whether snprintf truncates the result as in C99...
+dnl 17 = checking whether snprintf returns a byte count as in C99...
+dnl 18 = checking whether snprintf fully supports the 'n' directive...
+dnl 19 = checking whether snprintf respects a size of 1...
+dnl 20 = checking whether vsnprintf respects a zero size as in C99...
 dnl
 dnl . = yes, # = no.
 dnl
-dnl                                  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
-dnl   glibc 2.5                      .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
-dnl   glibc 2.3.6                    .  .  .  .  #  .  .  .  .  .  .  .  .  .  .  .  .  .  .
-dnl   FreeBSD 5.4, 6.1               .  .  .  .  #  .  .  .  .  .  #  .  #  .  .  .  .  .  .
-dnl   MacOS X 10.3.9                 .  .  .  .  #  .  .  .  .  .  #  .  #  .  .  .  .  .  .
-dnl   OpenBSD 3.9, 4.0               .  .  #  #  #  #  .  .  #  .  #  .  #  .  .  .  .  .  .
-dnl   Cygwin 2007 (= Cygwin 1.5.24)  .  .  .  .  #  #  .  .  .  ?  #  ?  ?  .  .  .  .  .  .
-dnl   Cygwin 2006 (= Cygwin 1.5.19)  #  .  .  .  #  #  .  .  #  ?  #  ?  ?  .  .  .  .  .  .
-dnl   Solaris 10                     .  .  #  #  #  .  .  .  .  .  #  .  .  .  .  .  .  .  .
-dnl   Solaris 2.6 ... 9              #  .  #  #  #  #  .  .  .  .  #  .  .  .  .  .  .  .  .
-dnl   Solaris 2.5.1                  #  .  #  #  #  #  .  .  .  .  #  .  .  #  #  #  #  #  #
-dnl   AIX 5.2                        .  .  #  #  #  .  .  .  .  .  #  .  .  .  .  .  .  .  .
-dnl   AIX 4.3.2, 5.1                 #  .  #  #  #  #  .  .  .  .  #  .  .  .  .  .  .  .  .
-dnl   HP-UX 11.31                    .  .  .  .  #  .  .  .  .  .  #  .  .  .  .  #  #  .  .
-dnl   HP-UX 11.{00,11,23}            #  .  .  .  #  #  .  .  .  .  #  .  .  .  .  #  #  .  #
-dnl   HP-UX 10.20                    #  .  .  .  #  #  .  .  .  #  #  .  .  .  .  #  #  ?  #
-dnl   IRIX 6.5                       #  .  #  #  #  #  .  .  .  .  #  .  .  .  .  #  .  .  .
-dnl   OSF/1 5.1                      #  .  #  #  #  #  .  .  .  .  #  .  .  .  .  #  .  .  #
-dnl   OSF/1 4.0d                     #  .  #  #  #  #  .  .  .  .  #  .  .  #  #  #  #  #  #
-dnl   NetBSD 4.0                     .  ?  ?  ?  ?  ?  .  .  ?  ?  ?  ?  ?  .  .  .  ?  ?  ?
-dnl   NetBSD 3.0                     .  .  .  .  #  #  .  #  #  ?  #  .  #  .  .  .  .  .  .
-dnl   Haiku                          .  .  .  #  #  #  .  .  .  .  .  .  ?  .  .  .  .  .  .
-dnl   BeOS                           #  #  .  #  #  #  .  #  .  ?  .  #  ?  .  .  .  .  .  .
-dnl   mingw                          #  #  #  #  #  #  .  #  #  .  #  #  ?  .  #  #  #  .  .
+dnl                                  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
+dnl   glibc 2.5                      .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
+dnl   glibc 2.3.6                    .  .  .  .  #  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
+dnl   FreeBSD 5.4, 6.1               .  .  .  .  #  .  .  .  .  .  .  #  .  #  .  .  .  .  .  .
+dnl   MacOS X 10.3.9                 .  .  .  .  #  .  .  .  .  .  .  #  .  #  .  .  .  .  .  .
+dnl   OpenBSD 3.9, 4.0               .  .  #  #  #  #  .  #  .  #  .  #  .  #  .  .  .  .  .  .
+dnl   Cygwin 2007 (= Cygwin 1.5.24)  .  .  .  .  #  #  .  .  .  .  ?  #  ?  ?  .  .  .  .  .  .
+dnl   Cygwin 2006 (= Cygwin 1.5.19)  #  .  .  .  #  #  .  ?  .  #  ?  #  ?  ?  .  .  .  .  .  .
+dnl   Solaris 10                     .  .  #  #  #  .  .  #  .  .  .  #  .  .  .  .  .  .  .  .
+dnl   Solaris 2.6 ... 9              #  .  #  #  #  #  .  #  .  .  .  #  .  .  .  .  .  .  .  .
+dnl   Solaris 2.5.1                  #  .  #  #  #  #  .  #  .  .  .  #  .  .  #  #  #  #  #  #
+dnl   AIX 5.2                        .  .  #  #  #  .  .  .  .  .  .  #  .  .  .  .  .  .  .  .
+dnl   AIX 4.3.2, 5.1                 #  .  #  #  #  #  .  .  .  .  .  #  .  .  .  .  .  .  .  .
+dnl   HP-UX 11.31                    .  .  .  .  #  .  .  .  .  .  .  #  .  .  .  .  #  #  .  .
+dnl   HP-UX 11.{00,11,23}            #  .  .  .  #  #  .  .  .  .  .  #  .  .  .  .  #  #  .  #
+dnl   HP-UX 10.20                    #  .  #  .  #  #  .  ?  .  .  #  #  .  .  .  .  #  #  ?  #
+dnl   IRIX 6.5                       #  .  #  #  #  #  .  #  .  .  .  #  .  .  .  .  #  .  .  .
+dnl   OSF/1 5.1                      #  .  #  #  #  #  .  .  .  .  .  #  .  .  .  .  #  .  .  #
+dnl   OSF/1 4.0d                     #  .  #  #  #  #  .  .  .  .  .  #  .  .  #  #  #  #  #  #
+dnl   NetBSD 4.0                     .  ?  ?  ?  ?  ?  .  ?  .  ?  ?  ?  ?  ?  .  .  .  ?  ?  ?
+dnl   NetBSD 3.0                     .  .  .  .  #  #  .  ?  #  #  ?  #  .  #  .  .  .  .  .  .
+dnl   Haiku                          .  .  .  #  #  #  .  #  .  .  .  .  .  ?  .  .  .  .  .  .
+dnl   BeOS                           #  #  .  #  #  #  .  ?  #  .  ?  .  #  ?  .  .  .  .  .  .
+dnl   mingw                          #  #  #  #  #  #  .  .  #  #  .  #  #  ?  .  #  #  #  .  .
index b4194c8adc129667a648e882d2381a8b971a9dd6..a2e8bdd62814a97e7be2875fd8f3cbf3b4c4ba8f 100644 (file)
@@ -1,4 +1,4 @@
-# stdint.m4 serial 33
+# stdint.m4 serial 34
 dnl Copyright (C) 2001-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -201,7 +201,75 @@ struct s {
   int check_size: (size_t) -1 == SIZE_MAX ? 1 : -1;
 };
          ]])],
-         [gl_cv_header_working_stdint_h=yes])])
+         [dnl Determine whether the various *_MIN, *_MAX macros are usable
+          dnl in preprocessor expression. We could do it by compiling a test
+          dnl program for each of these macros. It is faster to run a program
+          dnl that inspects the macro expansion.
+          dnl This detects a bug on HP-UX 11.23/ia64.
+          AC_RUN_IFELSE([
+            AC_LANG_PROGRAM([[
+#define __STDC_LIMIT_MACROS 1 /* to make it work also in C++ mode */
+#define __STDC_CONSTANT_MACROS 1 /* to make it work also in C++ mode */
+#define _GL_JUST_INCLUDE_SYSTEM_STDINT_H 1 /* work if build isn't clean */
+#include <stdint.h>
+]
+gl_STDINT_INCLUDES
+[
+#include <stdio.h>
+#include <string.h>
+#define MVAL(macro) MVAL1(macro)
+#define MVAL1(expression) #expression
+static const char *macro_values[] =
+  {
+#ifdef INT8_MAX
+    MVAL (INT8_MAX),
+#endif
+#ifdef INT16_MAX
+    MVAL (INT16_MAX),
+#endif
+#ifdef INT32_MAX
+    MVAL (INT32_MAX),
+#endif
+#ifdef INT64_MAX
+    MVAL (INT64_MAX),
+#endif
+#ifdef UINT8_MAX
+    MVAL (UINT8_MAX),
+#endif
+#ifdef UINT16_MAX
+    MVAL (UINT16_MAX),
+#endif
+#ifdef UINT32_MAX
+    MVAL (UINT32_MAX),
+#endif
+#ifdef UINT64_MAX
+    MVAL (UINT64_MAX),
+#endif
+    NULL
+  };
+]], [[
+  const char **mv;
+  for (mv = macro_values; *mv != NULL; mv++)
+    {
+      const char *value = *mv;
+      /* Test whether it looks like a cast expression.  */
+      if (strncmp (value, "((unsigned int)"/*)*/, 15) == 0
+          || strncmp (value, "((unsigned short)"/*)*/, 17) == 0
+          || strncmp (value, "((unsigned char)"/*)*/, 16) == 0
+          || strncmp (value, "((int)"/*)*/, 6) == 0
+          || strncmp (value, "((signed short)"/*)*/, 15) == 0
+          || strncmp (value, "((signed char)"/*)*/, 14) == 0)
+        return 1;
+    }
+  return 0;
+]])],
+              [gl_cv_header_working_stdint_h=yes],
+              [],
+              [dnl When cross-compiling, assume it works.
+               gl_cv_header_working_stdint_h=yes
+              ])
+         ])
+      ])
   fi
   if test "$gl_cv_header_working_stdint_h" = yes; then
     STDINT_H=
index 515befeb7e962adf71c50171bf854d0a3402ca1e..b295f16b2797a03bdd21abd9dbd0d25fc57c0ffa 100644 (file)
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 14
+# stdlib_h.m4 serial 15
 dnl Copyright (C) 2007-2009 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,7 @@ AC_DEFUN([gl_STDLIB_H],
 [
   AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
   gl_CHECK_NEXT_HEADERS([stdlib.h])
-  AC_CHECK_HEADERS([random.h])
+  AC_CHECK_HEADERS([random.h], [], [], [AC_INCLUDES_DEFAULT])
   if test $ac_cv_header_random_h = yes; then
     HAVE_RANDOM_H=1
   else
index 9e839d2bc8d096080b8e5f0c364a1ec70eb10869..01e8772f11c086dd435aed60b65d930d48875826 100644 (file)
@@ -1,4 +1,4 @@
-# vasnprintf.m4 serial 26
+# vasnprintf.m4 serial 28
 dnl Copyright (C) 2002-2004, 2006-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -58,7 +58,7 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF],
   AC_REQUIRE([AC_TYPE_LONG_LONG_INT])
   AC_REQUIRE([gt_TYPE_WCHAR_T])
   AC_REQUIRE([gt_TYPE_WINT_T])
-  AC_CHECK_FUNCS([snprintf wcslen])
+  AC_CHECK_FUNCS([snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb])
   dnl Use the _snprintf function only if it is declared (because on NetBSD it
   dnl is defined as a weak alias of snprintf; we prefer to use the latter).
   AC_CHECK_DECLS([_snprintf], , , [#include <stdio.h>])
@@ -150,6 +150,21 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_F],
   esac
 ])
 
+# Extra prerequisites of lib/vasnprintf.c for supporting the 'ls' directive.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_DIRECTIVE_LS],
+[
+  AC_REQUIRE([gl_PRINTF_DIRECTIVE_LS])
+  case "$gl_cv_func_printf_directive_ls" in
+    *yes)
+      ;;
+    *)
+      AC_DEFINE([NEED_PRINTF_DIRECTIVE_LS], [1],
+        [Define if the vasnprintf implementation needs special code for
+         the 'ls' directive.])
+      ;;
+  esac
+])
+
 # Extra prerequisites of lib/vasnprintf.c for supporting the ' flag.
 AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_GROUPING],
 [
@@ -247,6 +262,7 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS],
   gl_PREREQ_VASNPRINTF_INFINITE_LONG_DOUBLE
   gl_PREREQ_VASNPRINTF_DIRECTIVE_A
   gl_PREREQ_VASNPRINTF_DIRECTIVE_F
+  gl_PREREQ_VASNPRINTF_DIRECTIVE_LS
   gl_PREREQ_VASNPRINTF_FLAG_GROUPING
   gl_PREREQ_VASNPRINTF_FLAG_LEFTADJUST
   gl_PREREQ_VASNPRINTF_FLAG_ZERO
index 5f42c88eea14f78034d0dd47167f6a4a74eb613d..cc663e90b1f31c80bd3993c087d958c868c560a4 100644 (file)
@@ -80,10 +80,10 @@ EXTRA_DIST += test-errno.c
 
 ## begin gnulib module fseeko-tests
 
-TESTS += test-fseeko.sh
+TESTS += test-fseeko.sh test-fseeko2.sh
 TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'
 check_PROGRAMS += test-fseeko
-EXTRA_DIST += test-fseeko.c test-fseeko.sh
+EXTRA_DIST += test-fseeko.c test-fseeko.sh test-fseeko2.sh
 
 ## end   gnulib module fseeko-tests
 
index 3a1383b3d335ac31a23d89485402b9684aba1cb1..9c284da50061d8b12c64dad672f38a301a38d131 100644 (file)
@@ -1,5 +1,5 @@
 /* Test of fseeko() function.
-   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008, 2009 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
     }                                                                       \
   while (0)
 
+#ifndef FUNC_UNGETC_BROKEN
+# define FUNC_UNGETC_BROKEN 0
+#endif
+
 int
 main (int argc, char **argv)
 {
@@ -50,10 +54,19 @@ main (int argc, char **argv)
       ASSERT (ch == '#');
       ASSERT (ungetc (ch, stdin) == ch);
       ASSERT (fseeko (stdin, 2, SEEK_SET) == 0);
-      /* Test that fseek discards random ungetc data.  */
       ch = fgetc (stdin);
       ASSERT (ch == '/');
-      ASSERT (ungetc (ch ^ 0xff, stdin) == (ch ^ 0xff));
+      if (2 < argc)
+        {
+          if (FUNC_UNGETC_BROKEN)
+            {
+              fputs ("Skipping test: ungetc cannot handle arbitrary bytes\n",
+                     stderr);
+              return 77;
+            }
+          /* Test that fseek discards random ungetc data.  */
+          ASSERT (ungetc (ch ^ 0xff, stdin) == (ch ^ 0xff));
+        }
       ASSERT (fseeko (stdin, 0, SEEK_END) == 0);
       ASSERT (fgetc (stdin) == EOF);
       /* Test that fseek resets end-of-file marker.  */
index f1e6ac65d09b50acdbab3854069fafd53097b9cf..f7cf309c4df952c6b6b688c1ae39cfcbc49da20c 100644 (file)
@@ -1,5 +1,5 @@
 /* vsprintf with automatic memory allocation.
-   Copyright (C) 1999, 2002-2008 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2002-2009 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
 # include "fpucw.h"
 #endif
 
-#if HAVE_WCHAR_T
-# if HAVE_WCSLEN
-#  define local_wcslen wcslen
-# else
-   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
-      a dependency towards this library, here is a local substitute.
-      Define this substitute only once, even if this file is included
-      twice in the same compilation unit.  */
-#  ifndef local_wcslen_defined
-#   define local_wcslen_defined 1
-static size_t
-local_wcslen (const wchar_t *s)
-{
-  const wchar_t *ptr;
-
-  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
-    ;
-  return ptr - s;
-}
-#  endif
-# endif
-#endif
-
 /* Default parameters.  */
 #ifndef VASNPRINTF
 # if WIDE_CHAR_VERSION
@@ -152,6 +129,7 @@ local_wcslen (const wchar_t *s)
 #  define DIRECTIVES wchar_t_directives
 #  define PRINTF_PARSE wprintf_parse
 #  define DCHAR_CPY wmemcpy
+#  define DCHAR_SET wmemset
 # else
 #  define VASNPRINTF vasnprintf
 #  define FCHAR_T char
@@ -162,6 +140,7 @@ local_wcslen (const wchar_t *s)
 #  define DIRECTIVES char_directives
 #  define PRINTF_PARSE printf_parse
 #  define DCHAR_CPY memcpy
+#  define DCHAR_SET memset
 # endif
 #endif
 #if WIDE_CHAR_VERSION
@@ -215,6 +194,64 @@ local_wcslen (const wchar_t *s)
 #undef remainder
 #define remainder rem
 
+#if !USE_SNPRINTF && !WIDE_CHAR_VERSION
+# if (HAVE_STRNLEN && !defined _AIX)
+#  define local_strnlen strnlen
+# else
+#  ifndef local_strnlen_defined
+#   define local_strnlen_defined 1
+static size_t
+local_strnlen (const char *string, size_t maxlen)
+{
+  const char *end = memchr (string, '\0', maxlen);
+  return end ? (size_t) (end - string) : maxlen;
+}
+#  endif
+# endif
+#endif
+
+#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T && (WIDE_CHAR_VERSION || DCHAR_IS_TCHAR)
+# if HAVE_WCSLEN
+#  define local_wcslen wcslen
+# else
+   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
+      a dependency towards this library, here is a local substitute.
+      Define this substitute only once, even if this file is included
+      twice in the same compilation unit.  */
+#  ifndef local_wcslen_defined
+#   define local_wcslen_defined 1
+static size_t
+local_wcslen (const wchar_t *s)
+{
+  const wchar_t *ptr;
+
+  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
+    ;
+  return ptr - s;
+}
+#  endif
+# endif
+#endif
+
+#if !USE_SNPRINTF && HAVE_WCHAR_T && WIDE_CHAR_VERSION
+# if HAVE_WCSNLEN
+#  define local_wcsnlen wcsnlen
+# else
+#  ifndef local_wcsnlen_defined
+#   define local_wcsnlen_defined 1
+static size_t
+local_wcsnlen (const wchar_t *s, size_t maxlen)
+{
+  const wchar_t *ptr;
+
+  for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
+    ;
+  return ptr - s;
+}
+#  endif
+# endif
+#endif
+
 #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
 /* Determine the decimal-point character according to the current locale.  */
 # ifndef decimal_point_char_defined
@@ -2066,6 +2103,523 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                  }
              }
 #endif
+#if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
+           else if (dp->conversion == 's'
+# if WIDE_CHAR_VERSION
+                    && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
+# else
+                    && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
+# endif
+                   )
+             {
+               /* The normal handling of the 's' directive below requires
+                  allocating a temporary buffer.  The determination of its
+                  length (tmp_length), in the case when a precision is
+                  specified, below requires a conversion between a char[]
+                  string and a wchar_t[] wide string.  It could be done, but
+                  we have no guarantee that the implementation of sprintf will
+                  use the exactly same algorithm.  Without this guarantee, it
+                  is possible to have buffer overrun bugs.  In order to avoid
+                  such bugs, we implement the entire processing of the 's'
+                  directive ourselves.  */
+               int flags = dp->flags;
+               int has_width;
+               size_t width;
+               int has_precision;
+               size_t precision;
+
+               has_width = 0;
+               width = 0;
+               if (dp->width_start != dp->width_end)
+                 {
+                   if (dp->width_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->width_arg_index].a.a_int;
+                       if (arg < 0)
+                         {
+                           /* "A negative field width is taken as a '-' flag
+                               followed by a positive field width."  */
+                           flags |= FLAG_LEFT;
+                           width = (unsigned int) (-arg);
+                         }
+                       else
+                         width = arg;
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->width_start;
+
+                       do
+                         width = xsum (xtimes (width, 10), *digitp++ - '0');
+                       while (digitp != dp->width_end);
+                     }
+                   has_width = 1;
+                 }
+
+               has_precision = 0;
+               precision = 6;
+               if (dp->precision_start != dp->precision_end)
+                 {
+                   if (dp->precision_arg_index != ARG_NONE)
+                     {
+                       int arg;
+
+                       if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+                         abort ();
+                       arg = a.arg[dp->precision_arg_index].a.a_int;
+                       /* "A negative precision is taken as if the precision
+                           were omitted."  */
+                       if (arg >= 0)
+                         {
+                           precision = arg;
+                           has_precision = 1;
+                         }
+                     }
+                   else
+                     {
+                       const FCHAR_T *digitp = dp->precision_start + 1;
+
+                       precision = 0;
+                       while (digitp != dp->precision_end)
+                         precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+                       has_precision = 1;
+                     }
+                 }
+
+# if WIDE_CHAR_VERSION
+               /* %s in vasnwprintf.  See the specification of fwprintf.  */
+               {
+                 const char *arg = a.arg[dp->arg_index].a.a_string;
+                 const char *arg_end;
+                 size_t characters;
+
+                 if (has_precision)
+                   {
+                     /* Use only as many bytes as needed to produce PRECISION
+                        wide characters, from the left.  */
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     for (; precision > 0; precision--)
+                       {
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrlen (arg_end, MB_CUR_MAX, &state);
+#  else
+                         count = mblen (arg_end, MB_CUR_MAX);
+#  endif
+                         if (count == 0)
+                           /* Found the terminating NUL.  */
+                           break;
+                         if (count < 0)
+                           {
+                             /* Invalid or incomplete multibyte character.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         arg_end += count;
+                         characters++;
+                       }
+                   }
+                 else if (has_width)
+                   {
+                     /* Use the entire string, and count the number of wide
+                        characters.  */
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     for (;;)
+                       {
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrlen (arg_end, MB_CUR_MAX, &state);
+#  else
+                         count = mblen (arg_end, MB_CUR_MAX);
+#  endif
+                         if (count == 0)
+                           /* Found the terminating NUL.  */
+                           break;
+                         if (count < 0)
+                           {
+                             /* Invalid or incomplete multibyte character.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         arg_end += count;
+                         characters++;
+                       }
+                   }
+                 else
+                   {
+                     /* Use the entire string.  */
+                     arg_end = arg + strlen (arg);
+                     /* The number of characters doesn't matter.  */
+                     characters = 0;
+                   }
+
+                 if (has_width && width > characters
+                     && !(dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - characters;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+
+                 if (has_precision || has_width)
+                   {
+                     /* We know the number of wide characters in advance.  */
+                     size_t remaining;
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     ENSURE_ALLOCATION (xsum (length, characters));
+                     for (remaining = characters; remaining > 0; remaining--)
+                       {
+                         wchar_t wc;
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrtowc (&wc, arg, arg_end - arg, &state);
+#  else
+                         count = mbtowc (&wc, arg, arg_end - arg);
+#  endif
+                         if (count <= 0)
+                           /* mbrtowc not consistent with mbrlen, or mbtowc
+                              not consistent with mblen.  */
+                           abort ();
+                         result[length++] = wc;
+                         arg += count;
+                       }
+                     if (!(arg == arg_end))
+                       abort ();
+                   }
+                 else
+                   {
+#  if HAVE_MBRTOWC
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     while (arg < arg_end)
+                       {
+                         wchar_t wc;
+                         int count;
+#  if HAVE_MBRTOWC
+                         count = mbrtowc (&wc, arg, arg_end - arg, &state);
+#  else
+                         count = mbtowc (&wc, arg, arg_end - arg);
+#  endif
+                         if (count <= 0)
+                           /* mbrtowc not consistent with mbrlen, or mbtowc
+                              not consistent with mblen.  */
+                           abort ();
+                         ENSURE_ALLOCATION (xsum (length, 1));
+                         result[length++] = wc;
+                         arg += count;
+                       }
+                   }
+
+                 if (has_width && width > characters
+                     && (dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - characters;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+               }
+# else
+               /* %ls in vasnprintf.  See the specification of fprintf.  */
+               {
+                 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
+                 const wchar_t *arg_end;
+                 size_t characters;
+#  if !DCHAR_IS_TCHAR
+                 /* This code assumes that TCHAR_T is 'char'.  */
+                 typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1];
+                 TCHAR_T *tmpsrc;
+                 DCHAR_T *tmpdst;
+                 size_t tmpdst_len;
+#  endif
+                 size_t w;
+
+                 if (has_precision)
+                   {
+                     /* Use only as many wide characters as needed to produce
+                        at most PRECISION bytes, from the left.  */
+#  if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     while (precision > 0)
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg_end == 0)
+                           /* Found the terminating null wide character.  */
+                           break;
+#  if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg_end, &state);
+#  else
+                         count = wctomb (buf, *arg_end);
+#  endif
+                         if (count < 0)
+                           {
+                             /* Cannot convert.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         if (precision < count)
+                           break;
+                         arg_end++;
+                         characters += count;
+                         precision -= count;
+                       }
+                   }
+#  if DCHAR_IS_TCHAR
+                 else if (has_width)
+#  else
+                 else
+#  endif
+                   {
+                     /* Use the entire string, and count the number of
+                        bytes.  */
+#  if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#  endif
+                     arg_end = arg;
+                     characters = 0;
+                     for (;;)
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg_end == 0)
+                           /* Found the terminating null wide character.  */
+                           break;
+#  if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg_end, &state);
+#  else
+                         count = wctomb (buf, *arg_end);
+#  endif
+                         if (count < 0)
+                           {
+                             /* Cannot convert.  */
+                             if (!(result == resultbuf || result == NULL))
+                               free (result);
+                             if (buf_malloced != NULL)
+                               free (buf_malloced);
+                             CLEANUP ();
+                             errno = EILSEQ;
+                             return NULL;
+                           }
+                         arg_end++;
+                         characters += count;
+                       }
+                   }
+#  if DCHAR_IS_TCHAR
+                 else
+                   {
+                     /* Use the entire string.  */
+                     arg_end = arg + local_wcslen (arg);
+                     /* The number of bytes doesn't matter.  */
+                     characters = 0;
+                   }
+#  endif
+
+#  if !DCHAR_IS_TCHAR
+                 /* Convert the string into a piece of temporary memory.  */
+                 tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
+                 if (tmpsrc == NULL)
+                   goto out_of_memory;
+                 {
+                   TCHAR_T *tmpptr = tmpsrc;
+                   size_t remaining;
+#   if HAVE_WCRTOMB
+                   mbstate_t state;
+                   memset (&state, '\0', sizeof (mbstate_t));
+#   endif
+                   for (remaining = characters; remaining > 0; )
+                     {
+                       char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                       int count;
+
+                       if (*arg == 0)
+                         abort ();
+#   if HAVE_WCRTOMB
+                       count = wcrtomb (buf, *arg, &state);
+#   else
+                       count = wctomb (buf, *arg);
+#   endif
+                       if (count <= 0)
+                         /* Inconsistency.  */
+                         abort ();
+                       memcpy (tmpptr, buf, count);
+                       tmpptr += count;
+                       arg++;
+                       remaining -= count;
+                     }
+                   if (!(arg == arg_end))
+                     abort ();
+                 }
+
+                 /* Convert from TCHAR_T[] to DCHAR_T[].  */
+                 tmpdst = NULL;
+                 tmpdst_len = 0;
+                 if (DCHAR_CONV_FROM_ENCODING (locale_charset (),
+                                               iconveh_question_mark,
+                                               tmpsrc, characters,
+                                               NULL,
+                                               &tmpdst, &tmpdst_len)
+                     < 0)
+                   {
+                     int saved_errno = errno;
+                     free (tmpsrc);
+                     if (!(result == resultbuf || result == NULL))
+                       free (result);
+                     if (buf_malloced != NULL)
+                       free (buf_malloced);
+                     CLEANUP ();
+                     errno = saved_errno;
+                     return NULL;
+                   }
+                 free (tmpsrc);
+#  endif
+
+                 if (has_width)
+                   {
+#  if ENABLE_UNISTDIO
+                     /* Outside POSIX, it's preferrable to compare the width
+                        against the number of _characters_ of the converted
+                        value.  */
+                     w = DCHAR_MBSNLEN (result + length, characters);
+#  else
+                     /* The width is compared against the number of _bytes_
+                        of the converted value, says POSIX.  */
+                     w = characters;
+#  endif
+                   }
+                 else
+                   /* w doesn't matter.  */
+                   w = 0;
+
+                 if (has_width && width > w
+                     && !(dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - w;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+
+#  if DCHAR_IS_TCHAR
+                 if (has_precision || has_width)
+                   {
+                     /* We know the number of bytes in advance.  */
+                     size_t remaining;
+#   if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#   endif
+                     ENSURE_ALLOCATION (xsum (length, characters));
+                     for (remaining = characters; remaining > 0; )
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg == 0)
+                           abort ();
+#   if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg, &state);
+#   else
+                         count = wctomb (buf, *arg);
+#   endif
+                         if (count <= 0)
+                           /* Inconsistency.  */
+                           abort ();
+                         memcpy (result + length, buf, count);
+                         length += count;
+                         arg++;
+                         remaining -= count;
+                       }
+                     if (!(arg == arg_end))
+                       abort ();
+                   }
+                 else
+                   {
+#   if HAVE_WCRTOMB
+                     mbstate_t state;
+                     memset (&state, '\0', sizeof (mbstate_t));
+#   endif
+                     while (arg < arg_end)
+                       {
+                         char buf[64]; /* Assume MB_CUR_MAX <= 64.  */
+                         int count;
+
+                         if (*arg == 0)
+                           abort ();
+#   if HAVE_WCRTOMB
+                         count = wcrtomb (buf, *arg, &state);
+#   else
+                         count = wctomb (buf, *arg);
+#   endif
+                         if (count <= 0)
+                           /* Inconsistency.  */
+                           abort ();
+                         ENSURE_ALLOCATION (xsum (length, count));
+                         memcpy (result + length, buf, count);
+                         length += count;
+                         arg++;
+                       }
+                   }
+#  else
+                 ENSURE_ALLOCATION (xsum (length, tmpdst_len));
+                 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
+                 free (tmpdst);
+                 length += tmpdst_len;
+#  endif
+
+                 if (has_width && width > w
+                     && (dp->flags & FLAG_LEFT))
+                   {
+                     size_t n = width - w;
+                     ENSURE_ALLOCATION (xsum (length, n));
+                     DCHAR_SET (result + length, ' ', n);
+                     length += n;
+                   }
+               }
+             }
+# endif
+#endif
 #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
            else if ((dp->conversion == 'a' || dp->conversion == 'A')
 # if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
@@ -4032,16 +4586,64 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 # if HAVE_WCHAR_T
                      if (type == TYPE_WIDE_STRING)
                        {
-                         tmp_length =
-                           local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
-
-#  if !WIDE_CHAR_VERSION
-                         tmp_length = xtimes (tmp_length, MB_CUR_MAX);
+#  if WIDE_CHAR_VERSION
+                         /* ISO C says about %ls in fwprintf:
+                              "If the precision is not specified or is greater
+                               than the size of the array, the array shall
+                               contain a null wide character."
+                            So if there is a precision, we must not use
+                            wcslen.  */
+                         const wchar_t *arg =
+                           a.arg[dp->arg_index].a.a_wide_string;
+
+                         if (has_precision)
+                           tmp_length = local_wcsnlen (arg, precision);
+                         else
+                           tmp_length = local_wcslen (arg);
+#  else
+                         /* ISO C says about %ls in fprintf:
+                              "If a precision is specified, no more than that
+                               many bytes are written (including shift
+                               sequences, if any), and the array shall contain
+                               a null wide character if, to equal the
+                               multibyte character sequence length given by
+                               the precision, the function would need to
+                               access a wide character one past the end of the
+                               array."
+                            So if there is a precision, we must not use
+                            wcslen.  */
+                         /* This case has already been handled above.  */
+                         abort ();
 #  endif
                        }
                      else
 # endif
-                       tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
+                       {
+# if WIDE_CHAR_VERSION
+                         /* ISO C says about %s in fwprintf:
+                              "If the precision is not specified or is greater
+                               than the size of the converted array, the
+                               converted array shall contain a null wide
+                               character."
+                            So if there is a precision, we must not use
+                            strlen.  */
+                         /* This case has already been handled above.  */
+                         abort ();
+# else
+                         /* ISO C says about %s in fprintf:
+                              "If the precision is not specified or greater
+                               than the size of the array, the array shall
+                               contain a null character."
+                            So if there is a precision, we must not use
+                            strlen.  */
+                         const char *arg = a.arg[dp->arg_index].a.a_string;
+
+                         if (has_precision)
+                           tmp_length = local_strnlen (arg, precision);
+                         else
+                           tmp_length = strlen (arg);
+# endif
+                       }
                      break;
 
                    case 'p':