diff options
author | Simon Josefsson <simon@josefsson.org> | 2009-02-27 09:23:52 +0100 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2009-02-27 09:23:52 +0100 |
commit | a13df3057a9d99f45a29fa874d4cc2a63bf8d7a0 (patch) | |
tree | 907c10d8576bed86fc0f1a6b78acc9c59b63b959 | |
parent | de49e9f7685d086d07f8595553c25ca2d501aeab (diff) | |
download | gnutls-a13df3057a9d99f45a29fa874d4cc2a63bf8d7a0.tar.gz |
Update gnulib files.
-rw-r--r-- | gl/m4/gnulib-comp.m4 | 3 | ||||
-rw-r--r-- | gl/m4/printf.m4 | 182 | ||||
-rw-r--r-- | gl/m4/stdint.m4 | 72 | ||||
-rw-r--r-- | gl/m4/stdlib_h.m4 | 4 | ||||
-rw-r--r-- | gl/m4/vasnprintf.m4 | 20 | ||||
-rw-r--r-- | gl/tests/Makefile.am | 4 | ||||
-rw-r--r-- | gl/tests/test-fseeko.c | 19 | ||||
-rw-r--r-- | gl/tests/test-getaddrinfo.c | 6 | ||||
-rw-r--r-- | gl/vasnprintf.c | 662 | ||||
-rw-r--r-- | lib/gl/m4/gnulib-comp.m4 | 3 | ||||
-rw-r--r-- | lib/gl/m4/printf.m4 | 182 | ||||
-rw-r--r-- | lib/gl/m4/stdint.m4 | 72 | ||||
-rw-r--r-- | lib/gl/m4/stdlib_h.m4 | 4 | ||||
-rw-r--r-- | lib/gl/m4/vasnprintf.m4 | 20 | ||||
-rw-r--r-- | lib/gl/tests/Makefile.am | 4 | ||||
-rw-r--r-- | lib/gl/tests/test-fseeko.c | 19 | ||||
-rw-r--r-- | lib/gl/vasnprintf.c | 662 |
17 files changed, 1756 insertions, 182 deletions
diff --git a/gl/m4/gnulib-comp.m4 b/gl/m4/gnulib-comp.m4 index 42a1e8dfdf..f2cc584c8a 100644 --- a/gl/m4/gnulib-comp.m4 +++ b/gl/m4/gnulib-comp.m4 @@ -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 diff --git a/gl/m4/printf.m4 b/gl/m4/printf.m4 index a1d4dadd7b..4207ace49f 100644 --- a/gl/m4/printf.m4 +++ b/gl/m4/printf.m4 @@ -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 # # # # # # . . # # . # # ? . # # # . . diff --git a/gl/m4/stdint.m4 b/gl/m4/stdint.m4 index b4194c8adc..a2e8bdd628 100644 --- a/gl/m4/stdint.m4 +++ b/gl/m4/stdint.m4 @@ -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= diff --git a/gl/m4/stdlib_h.m4 b/gl/m4/stdlib_h.m4 index 515befeb7e..b295f16b27 100644 --- a/gl/m4/stdlib_h.m4 +++ b/gl/m4/stdlib_h.m4 @@ -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 diff --git a/gl/m4/vasnprintf.m4 b/gl/m4/vasnprintf.m4 index 9e839d2bc8..01e8772f11 100644 --- a/gl/m4/vasnprintf.m4 +++ b/gl/m4/vasnprintf.m4 @@ -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 diff --git a/gl/tests/Makefile.am b/gl/tests/Makefile.am index d9cda94fe1..db02b328a8 100644 --- a/gl/tests/Makefile.am +++ b/gl/tests/Makefile.am @@ -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 diff --git a/gl/tests/test-fseeko.c b/gl/tests/test-fseeko.c index 3a1383b3d3..9c284da500 100644 --- a/gl/tests/test-fseeko.c +++ b/gl/tests/test-fseeko.c @@ -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 @@ -33,6 +33,10 @@ } \ 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. */ diff --git a/gl/tests/test-getaddrinfo.c b/gl/tests/test-getaddrinfo.c index a8b2fd5d46..5e33bb24f1 100644 --- a/gl/tests/test-getaddrinfo.c +++ b/gl/tests/test-getaddrinfo.c @@ -45,10 +45,15 @@ 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; } diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c index 93aef6f291..1b9d5ded74 100644 --- a/gl/vasnprintf.c +++ b/gl/vasnprintf.c @@ -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 @@ -117,29 +117,6 @@ # 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': diff --git a/lib/gl/m4/gnulib-comp.m4 b/lib/gl/m4/gnulib-comp.m4 index 1028323782..77ca8b8fd9 100644 --- a/lib/gl/m4/gnulib-comp.m4 +++ b/lib/gl/m4/gnulib-comp.m4 @@ -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 diff --git a/lib/gl/m4/printf.m4 b/lib/gl/m4/printf.m4 index a1d4dadd7b..4207ace49f 100644 --- a/lib/gl/m4/printf.m4 +++ b/lib/gl/m4/printf.m4 @@ -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 # # # # # # . . # # . # # ? . # # # . . diff --git a/lib/gl/m4/stdint.m4 b/lib/gl/m4/stdint.m4 index b4194c8adc..a2e8bdd628 100644 --- a/lib/gl/m4/stdint.m4 +++ b/lib/gl/m4/stdint.m4 @@ -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= diff --git a/lib/gl/m4/stdlib_h.m4 b/lib/gl/m4/stdlib_h.m4 index 515befeb7e..b295f16b27 100644 --- a/lib/gl/m4/stdlib_h.m4 +++ b/lib/gl/m4/stdlib_h.m4 @@ -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 diff --git a/lib/gl/m4/vasnprintf.m4 b/lib/gl/m4/vasnprintf.m4 index 9e839d2bc8..01e8772f11 100644 --- a/lib/gl/m4/vasnprintf.m4 +++ b/lib/gl/m4/vasnprintf.m4 @@ -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 diff --git a/lib/gl/tests/Makefile.am b/lib/gl/tests/Makefile.am index 5f42c88eea..cc663e90b1 100644 --- a/lib/gl/tests/Makefile.am +++ b/lib/gl/tests/Makefile.am @@ -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 diff --git a/lib/gl/tests/test-fseeko.c b/lib/gl/tests/test-fseeko.c index 3a1383b3d3..9c284da500 100644 --- a/lib/gl/tests/test-fseeko.c +++ b/lib/gl/tests/test-fseeko.c @@ -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 @@ -33,6 +33,10 @@ } \ 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. */ diff --git a/lib/gl/vasnprintf.c b/lib/gl/vasnprintf.c index f1e6ac65d0..f7cf309c4d 100644 --- a/lib/gl/vasnprintf.c +++ b/lib/gl/vasnprintf.c @@ -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 @@ -117,29 +117,6 @@ # 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': |