diff options
author | Simon Josefsson <simon@josefsson.org> | 2007-12-09 22:41:36 +0100 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2007-12-09 22:41:36 +0100 |
commit | 28d95172009ac844566e0dfdb63505832cbf05d9 (patch) | |
tree | fa11062be1df5e00405385d3b5cebd71b73ac1b4 /lgl | |
parent | 3d5af6621fb49e326be35b99cec8556d8c8315ca (diff) | |
download | gnutls-28d95172009ac844566e0dfdb63505832cbf05d9.tar.gz |
Update gnulib.
Diffstat (limited to 'lgl')
-rw-r--r-- | lgl/Makefile.am | 8 | ||||
-rw-r--r-- | lgl/m4/gettext.m4 | 4 | ||||
-rw-r--r-- | lgl/m4/gnulib-comp.m4 | 3 | ||||
-rw-r--r-- | lgl/m4/iconv.m4 | 2 | ||||
-rw-r--r-- | lgl/m4/intdiv0.m4 | 2 | ||||
-rw-r--r-- | lgl/m4/intl.m4 | 20 | ||||
-rw-r--r-- | lgl/m4/intlmacosx.m4 | 2 | ||||
-rw-r--r-- | lgl/m4/intmax_t.m4 | 12 | ||||
-rw-r--r-- | lgl/m4/lib-link.m4 | 2 | ||||
-rw-r--r-- | lgl/m4/lock.m4 | 2 | ||||
-rw-r--r-- | lgl/m4/longlong.m4 | 75 | ||||
-rw-r--r-- | lgl/m4/po.m4 | 25 | ||||
-rw-r--r-- | lgl/m4/printf-posix.m4 | 2 | ||||
-rw-r--r-- | lgl/m4/stdio_h.m4 | 15 | ||||
-rw-r--r-- | lgl/m4/stdlib_h.m4 | 4 | ||||
-rw-r--r-- | lgl/m4/string_h.m4 | 2 | ||||
-rw-r--r-- | lgl/m4/uintmax_t.m4 | 8 | ||||
-rw-r--r-- | lgl/m4/ulonglong.m4 | 51 | ||||
-rw-r--r-- | lgl/m4/unistd_h.m4 | 6 | ||||
-rw-r--r-- | lgl/m4/vasnprintf.m4 | 52 | ||||
-rw-r--r-- | lgl/m4/wint_t.m4 | 2 | ||||
-rw-r--r-- | lgl/printf-parse.c | 23 | ||||
-rw-r--r-- | lgl/realloc.c | 33 | ||||
-rw-r--r-- | lgl/stdlib.in.h | 9 | ||||
-rw-r--r-- | lgl/string.in.h | 45 | ||||
-rw-r--r-- | lgl/unistd.in.h | 55 | ||||
-rw-r--r-- | lgl/vasnprintf.c | 888 |
27 files changed, 1090 insertions, 262 deletions
diff --git a/lgl/Makefile.am b/lgl/Makefile.am index c71919e1f6..af1d330ac0 100644 --- a/lgl/Makefile.am +++ b/lgl/Makefile.am @@ -423,12 +423,14 @@ stdlib.h: stdlib.in.h -e 's|@''GNULIB_GETSUBOPT''@|$(GNULIB_GETSUBOPT)|g' \ -e 's|@''GNULIB_MKDTEMP''@|$(GNULIB_MKDTEMP)|g' \ -e 's|@''GNULIB_MKSTEMP''@|$(GNULIB_MKSTEMP)|g' \ + -e 's|@''GNULIB_PUTENV''@|$(GNULIB_PUTENV)|g' \ -e 's|@''HAVE_CALLOC_POSIX''@|$(HAVE_CALLOC_POSIX)|g' \ -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \ -e 's|@''HAVE_MALLOC_POSIX''@|$(HAVE_MALLOC_POSIX)|g' \ -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \ -e 's|@''HAVE_REALLOC_POSIX''@|$(HAVE_REALLOC_POSIX)|g' \ -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \ + -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \ < $(srcdir)/stdlib.in.h; \ } > $@-t @@ -483,8 +485,6 @@ string.h: string.in.h -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \ -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \ -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \ - -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \ - -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \ -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \ -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \ -e 's|@''HAVE_STRNDUP''@|$(HAVE_STRNDUP)|g' \ @@ -617,15 +617,19 @@ unistd.h: unistd.in.h -e 's|@''GNULIB_FTRUNCATE''@|$(GNULIB_FTRUNCATE)|g' \ -e 's|@''GNULIB_GETCWD''@|$(GNULIB_GETCWD)|g' \ -e 's|@''GNULIB_GETLOGIN_R''@|$(GNULIB_GETLOGIN_R)|g' \ + -e 's|@''GNULIB_GETPAGESIZE''@|$(GNULIB_GETPAGESIZE)|g' \ -e 's|@''GNULIB_LCHOWN''@|$(GNULIB_LCHOWN)|g' \ -e 's|@''GNULIB_LSEEK''@|$(GNULIB_LSEEK)|g' \ -e 's|@''GNULIB_READLINK''@|$(GNULIB_READLINK)|g' \ -e 's|@''GNULIB_SLEEP''@|$(GNULIB_SLEEP)|g' \ -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \ -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \ + -e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \ -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \ + -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \ + -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \ -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \ -e 's|@''REPLACE_FCHDIR''@|$(REPLACE_FCHDIR)|g' \ -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \ diff --git a/lgl/m4/gettext.m4 b/lgl/m4/gettext.m4 index 7f3e4e283c..c9ae1f7de8 100644 --- a/lgl/m4/gettext.m4 +++ b/lgl/m4/gettext.m4 @@ -1,5 +1,5 @@ -# gettext.m4 serial 59a (gettext-0.16.1) -dnl Copyright (C) 1995-2006 Free Software Foundation, Inc. +# gettext.m4 serial 60 (gettext-0.17) +dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. diff --git a/lgl/m4/gnulib-comp.m4 b/lgl/m4/gnulib-comp.m4 index 38c8f6c5f8..b6ade09e21 100644 --- a/lgl/m4/gnulib-comp.m4 +++ b/lgl/m4/gnulib-comp.m4 @@ -73,7 +73,7 @@ AC_DEFUN([lgl_INIT], gl_MD2 gl_FLOAT_H dnl you must add AM_GNU_GETTEXT([external]) or similar to configure.ac. - AM_GNU_GETTEXT_VERSION([0.16.1]) + AM_GNU_GETTEXT_VERSION([0.17]) AC_SUBST([LIBINTL]) AC_SUBST([LTLIBINTL]) gl_FUNC_MEMMEM @@ -300,7 +300,6 @@ AC_DEFUN([lgl_FILE_LIST], [ m4/time_h.m4 m4/time_r.m4 m4/uintmax_t.m4 - m4/ulonglong.m4 m4/unistd_h.m4 m4/vasnprintf.m4 m4/vasprintf.m4 diff --git a/lgl/m4/iconv.m4 b/lgl/m4/iconv.m4 index 8e36b52d4d..66bc76f48c 100644 --- a/lgl/m4/iconv.m4 +++ b/lgl/m4/iconv.m4 @@ -1,4 +1,4 @@ -# iconv.m4 serial AM6 (gettext-0.16.2) +# iconv.m4 serial AM6 (gettext-0.17) dnl Copyright (C) 2000-2002, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/lgl/m4/intdiv0.m4 b/lgl/m4/intdiv0.m4 index 534134ac33..8c8a67084f 100644 --- a/lgl/m4/intdiv0.m4 +++ b/lgl/m4/intdiv0.m4 @@ -1,4 +1,4 @@ -# intdiv0.m4 serial 2 (gettext-0.16.2) +# intdiv0.m4 serial 2 (gettext-0.17) dnl Copyright (C) 2002, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/lgl/m4/intl.m4 b/lgl/m4/intl.m4 index e0771d2a04..934408bb90 100644 --- a/lgl/m4/intl.m4 +++ b/lgl/m4/intl.m4 @@ -1,4 +1,4 @@ -# intl.m4 serial 5 (gettext-0.16.2) +# intl.m4 serial 8 (gettext-0.17) dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -97,7 +97,7 @@ AC_DEFUN([AM_INTL_SUBDIR], dnl exported variables _also_ in the static library. if test "$enable_shared" = yes; then case "$host_os" in - cygwin*) is_woe32dll=yes ;; + mingw* | cygwin*) is_woe32dll=yes ;; *) is_woe32dll=no ;; esac else @@ -119,6 +119,18 @@ AC_DEFUN([AM_INTL_SUBDIR], AC_CHECK_TOOL([WINDRES], [windres]) fi + dnl Determine whether when creating a library, "-lc" should be passed to + dnl libtool or not. On many platforms, it is required for the libtool option + dnl -no-undefined to work. On HP-UX, however, the -lc - stored by libtool + dnl in the *.la files - makes it impossible to create multithreaded programs, + dnl because libtool also reorders the -lc to come before the -pthread, and + dnl this disables pthread_create() <http://docs.hp.com/en/1896/pthreads.html>. + case "$host_os" in + hpux*) LTLIBC="" ;; + *) LTLIBC="-lc" ;; + esac + AC_SUBST([LTLIBC]) + dnl Rename some macros and functions used for locking. AH_BOTTOM([ #define __libc_lock_t gl_lock_t @@ -209,7 +221,9 @@ AC_DEFUN([gt_INTL_SUBDIR_CORE], AC_CACHE_CHECK([for NL_LOCALE_NAME macro], gt_cv_nl_locale_name, [AC_TRY_LINK([#include <langinfo.h> #include <locale.h>], - [char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES));], + [char* cs = nl_langinfo(_NL_LOCALE_NAME(LC_MESSAGES)); + return !cs; + ], gt_cv_nl_locale_name=yes, gt_cv_nl_locale_name=no) ]) diff --git a/lgl/m4/intlmacosx.m4 b/lgl/m4/intlmacosx.m4 index 6019bbfa24..d3f0d904d2 100644 --- a/lgl/m4/intlmacosx.m4 +++ b/lgl/m4/intlmacosx.m4 @@ -1,4 +1,4 @@ -# intlmacosx.m4 serial 1 (gettext-0.16.2) +# intlmacosx.m4 serial 1 (gettext-0.17) dnl Copyright (C) 2004-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/lgl/m4/intmax_t.m4 b/lgl/m4/intmax_t.m4 index 17c7b0ae88..50ae35d223 100644 --- a/lgl/m4/intmax_t.m4 +++ b/lgl/m4/intmax_t.m4 @@ -1,5 +1,5 @@ -# intmax_t.m4 serial 5 -dnl Copyright (C) 1997-2004, 2006 Free Software Foundation, Inc. +# intmax_t.m4 serial 6 +dnl Copyright (C) 1997-2004, 2006-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -18,8 +18,8 @@ AC_DEFUN([gl_AC_TYPE_INTMAX_T], AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_AC_HEADER_STDINT_H]) if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then - AC_REQUIRE([gl_AC_TYPE_LONG_LONG]) - test $ac_cv_type_long_long = yes \ + AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) + test $ac_cv_type_long_long_int = yes \ && ac_type='long long' \ || ac_type='long' AC_DEFINE_UNQUOTED(intmax_t, $ac_type, @@ -51,8 +51,8 @@ AC_DEFUN([gt_AC_TYPE_INTMAX_T], AC_DEFINE(HAVE_INTMAX_T, 1, [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.]) else - AC_REQUIRE([gl_AC_TYPE_LONG_LONG]) - test $ac_cv_type_long_long = yes \ + AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) + test $ac_cv_type_long_long_int = yes \ && ac_type='long long' \ || ac_type='long' AC_DEFINE_UNQUOTED(intmax_t, $ac_type, diff --git a/lgl/m4/lib-link.m4 b/lgl/m4/lib-link.m4 index f157d983da..e3d26fc42d 100644 --- a/lgl/m4/lib-link.m4 +++ b/lgl/m4/lib-link.m4 @@ -1,4 +1,4 @@ -# lib-link.m4 serial 13 (gettext-0.16.2) +# lib-link.m4 serial 13 (gettext-0.17) dnl Copyright (C) 2001-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/lgl/m4/lock.m4 b/lgl/m4/lock.m4 index 4cc585ea2e..9111933535 100644 --- a/lgl/m4/lock.m4 +++ b/lgl/m4/lock.m4 @@ -1,4 +1,4 @@ -# lock.m4 serial 7 (gettext-0.16.2) +# lock.m4 serial 7 (gettext-0.17) dnl Copyright (C) 2005-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/lgl/m4/longlong.m4 b/lgl/m4/longlong.m4 index 5799c3965a..15bf9dacad 100644 --- a/lgl/m4/longlong.m4 +++ b/lgl/m4/longlong.m4 @@ -1,4 +1,4 @@ -# longlong.m4 serial 11 +# longlong.m4 serial 13 dnl Copyright (C) 1999-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -18,23 +18,11 @@ AC_DEFUN([AC_TYPE_LONG_LONG_INT], [ AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], [AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [[#if ! (-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) - error in preprocessor; - #endif - long long int ll = 9223372036854775807ll; - long long int nll = -9223372036854775807LL; - typedef int a[((-9223372036854775807LL < 0 - && 0 < 9223372036854775807ll) - ? 1 : -1)]; - int i = 63;]], - [[long long int llmax = 9223372036854775807ll; - return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) - | (llmax / ll) | (llmax % ll));]])], + [_AC_TYPE_LONG_LONG_SNIPPET], [dnl This catches a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004. dnl If cross compiling, assume the bug isn't important, since dnl nobody cross compiles for this platform as far as we know. - AC_RUN_IFELSE( + AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[@%:@include <limits.h> @%:@ifndef LLONG_MAX @@ -63,13 +51,56 @@ AC_DEFUN([AC_TYPE_LONG_LONG_INT], fi ]) -# This macro is obsolescent and should go away soon. -AC_DEFUN([gl_AC_TYPE_LONG_LONG], +# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. +# This fixes a bug in Autoconf 2.61, but can be removed once we +# assume 2.62 everywhere. + +# Note: If the type 'unsigned long long int' exists but is only 32 bits +# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT +# will not be defined. In this case you can treat 'unsigned long long int' +# like 'unsigned long int'. + +AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], [ - AC_REQUIRE([AC_TYPE_LONG_LONG_INT]) - ac_cv_type_long_long=$ac_cv_type_long_long_int - if test $ac_cv_type_long_long = yes; then - AC_DEFINE(HAVE_LONG_LONG, 1, - [Define if you have the 'long long' type.]) + AC_CACHE_CHECK([for unsigned long long int], + [ac_cv_type_unsigned_long_long_int], + [AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [ac_cv_type_unsigned_long_long_int=yes], + [ac_cv_type_unsigned_long_long_int=no])]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], 1, + [Define to 1 if the system has the type `unsigned long long int'.]) fi ]) + +# Expands to a C program that can be used to test for simultaneous support +# of 'long long' and 'unsigned long long'. We don't want to say that +# 'long long' is available if 'unsigned long long' is not, or vice versa, +# because too many programs rely on the symmetry between signed and unsigned +# integer types (excluding 'bool'). +AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET], +[ + AC_LANG_PROGRAM( + [[/* For now, do not test the preprocessor; as of 2007 there are too many + implementations with broken preprocessors. Perhaps this can + be revisited in 2012. In the meantime, code should not expect + #if to work with literals wider than 32 bits. */ + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63;]], + [[/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull));]]) +]) diff --git a/lgl/m4/po.m4 b/lgl/m4/po.m4 index 00133ef36f..0734762ab1 100644 --- a/lgl/m4/po.m4 +++ b/lgl/m4/po.m4 @@ -1,5 +1,5 @@ -# po.m4 serial 13 (gettext-0.15) -dnl Copyright (C) 1995-2006 Free Software Foundation, Inc. +# po.m4 serial 15 (gettext-0.17) +dnl Copyright (C) 1995-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -27,6 +27,10 @@ AC_DEFUN([AM_PO_SUBDIRS], AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake AC_REQUIRE([AM_NLS])dnl + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.17]) + dnl Perform the following tests also if --disable-nls has been given, dnl because they are needed for "make dist" to work. @@ -84,6 +88,10 @@ changequote([,])dnl test -n "$localedir" || localedir='${datadir}/locale' AC_SUBST([localedir]) + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + AC_CONFIG_COMMANDS([po-directories], [[ for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" @@ -426,3 +434,16 @@ EOF fi mv "$ac_file.tmp" "$ac_file" ]) + +dnl Initializes the accumulator used by AM_XGETTEXT_OPTION. +AC_DEFUN([AM_XGETTEXT_OPTION_INIT], +[ + XGETTEXT_EXTRA_OPTIONS= +]) + +dnl Registers an option to be passed to xgettext in the po subdirectory. +AC_DEFUN([AM_XGETTEXT_OPTION], +[ + AC_REQUIRE([AM_XGETTEXT_OPTION_INIT]) + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS $1" +]) diff --git a/lgl/m4/printf-posix.m4 b/lgl/m4/printf-posix.m4 index 33e387c6f9..14ba612839 100644 --- a/lgl/m4/printf-posix.m4 +++ b/lgl/m4/printf-posix.m4 @@ -1,4 +1,4 @@ -# printf-posix.m4 serial 3 (gettext-0.16.2) +# printf-posix.m4 serial 3 (gettext-0.17) dnl Copyright (C) 2003, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/lgl/m4/stdio_h.m4 b/lgl/m4/stdio_h.m4 index 45e54e2a62..a40d418041 100644 --- a/lgl/m4/stdio_h.m4 +++ b/lgl/m4/stdio_h.m4 @@ -1,4 +1,4 @@ -# stdio_h.m4 serial 8 +# stdio_h.m4 serial 9 dnl Copyright (C) 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -73,13 +73,12 @@ AC_DEFUN([gl_STDIN_LARGE_OFFSET], [AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <stdio.h>], [#if defined __SL64 && defined __SCLE /* cygwin */ /* Cygwin 1.5.24 and earlier fail to put stdin in 64-bit mode, making - fseeko/ftello needlessly fail. This bug was fixed at the same time - that cygwin started exporting asnprintf (cygwin 1.7.0), so we use - that as a link-time test for cross-compiles rather than building - a runtime test. */ - size_t s; - if (asnprintf (NULL, &s, "")) - return 0; + fseeko/ftello needlessly fail. This bug was fixed in 1.5.25, and + it is easier to do a version check than building a runtime test. */ +# include <cygwin/version.h> +# if CYGWIN_VERSION_DLL_COMBINED < CYGWIN_VERSION_DLL_MAKE_COMBINED (1005, 25) + choke me +# endif #endif])], [gl_cv_var_stdin_large_offset=yes], [gl_cv_var_stdin_large_offset=no])]) diff --git a/lgl/m4/stdlib_h.m4 b/lgl/m4/stdlib_h.m4 index ea9286ef46..278df744c7 100644 --- a/lgl/m4/stdlib_h.m4 +++ b/lgl/m4/stdlib_h.m4 @@ -1,4 +1,4 @@ -# stdlib_h.m4 serial 3 +# stdlib_h.m4 serial 4 dnl Copyright (C) 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -25,6 +25,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS], GNULIB_GETSUBOPT=0; AC_SUBST([GNULIB_GETSUBOPT]) GNULIB_MKDTEMP=0; AC_SUBST([GNULIB_MKDTEMP]) GNULIB_MKSTEMP=0; AC_SUBST([GNULIB_MKSTEMP]) + GNULIB_PUTENV=0; AC_SUBST([GNULIB_PUTENV]) dnl Assume proper GNU behavior unless another module says otherwise. HAVE_CALLOC_POSIX=1; AC_SUBST([HAVE_CALLOC_POSIX]) HAVE_GETSUBOPT=1; AC_SUBST([HAVE_GETSUBOPT]) @@ -32,4 +33,5 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS], HAVE_MKDTEMP=1; AC_SUBST([HAVE_MKDTEMP]) HAVE_REALLOC_POSIX=1; AC_SUBST([HAVE_REALLOC_POSIX]) REPLACE_MKSTEMP=0; AC_SUBST([REPLACE_MKSTEMP]) + REPLACE_PUTENV=0; AC_SUBST([REPLACE_PUTENV]) ]) diff --git a/lgl/m4/string_h.m4 b/lgl/m4/string_h.m4 index d811e26b88..83711799a1 100644 --- a/lgl/m4/string_h.m4 +++ b/lgl/m4/string_h.m4 @@ -64,8 +64,6 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS], HAVE_DECL_MEMRCHR=1; AC_SUBST([HAVE_DECL_MEMRCHR]) HAVE_STPCPY=1; AC_SUBST([HAVE_STPCPY]) HAVE_STPNCPY=1; AC_SUBST([HAVE_STPNCPY]) - HAVE_STRCASECMP=1; AC_SUBST([HAVE_STRCASECMP]) - HAVE_DECL_STRNCASECMP=1; AC_SUBST([HAVE_DECL_STRNCASECMP]) HAVE_STRCHRNUL=1; AC_SUBST([HAVE_STRCHRNUL]) HAVE_DECL_STRDUP=1; AC_SUBST([HAVE_DECL_STRDUP]) HAVE_STRNDUP=1; AC_SUBST([HAVE_STRNDUP]) diff --git a/lgl/m4/uintmax_t.m4 b/lgl/m4/uintmax_t.m4 index bf83ed7464..641c4898d3 100644 --- a/lgl/m4/uintmax_t.m4 +++ b/lgl/m4/uintmax_t.m4 @@ -1,5 +1,5 @@ -# uintmax_t.m4 serial 9 -dnl Copyright (C) 1997-2004 Free Software Foundation, Inc. +# uintmax_t.m4 serial 10 +dnl Copyright (C) 1997-2004, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. @@ -16,8 +16,8 @@ AC_DEFUN([gl_AC_TYPE_UINTMAX_T], AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) AC_REQUIRE([gl_AC_HEADER_STDINT_H]) if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then - AC_REQUIRE([gl_AC_TYPE_UNSIGNED_LONG_LONG]) - test $ac_cv_type_unsigned_long_long = yes \ + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + test $ac_cv_type_unsigned_long_long_int = yes \ && ac_type='unsigned long long' \ || ac_type='unsigned long' AC_DEFINE_UNQUOTED(uintmax_t, $ac_type, diff --git a/lgl/m4/ulonglong.m4 b/lgl/m4/ulonglong.m4 deleted file mode 100644 index 34f06e4c95..0000000000 --- a/lgl/m4/ulonglong.m4 +++ /dev/null @@ -1,51 +0,0 @@ -# ulonglong.m4 serial 8 -dnl Copyright (C) 1999-2007 Free Software Foundation, Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it, -dnl with or without modifications, as long as this notice is preserved. - -dnl From Paul Eggert. - -# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. -# This fixes a bug in Autoconf 2.61, but can be removed once we -# assume 2.62 everywhere. - -# Note: If the type 'unsigned long long int' exists but is only 32 bits -# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT -# will not be defined. In this case you can treat 'unsigned long long int' -# like 'unsigned long int'. - -AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], -[ - AC_CACHE_CHECK([for unsigned long long int], - [ac_cv_type_unsigned_long_long_int], - [AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [[#if ! (18446744073709551615ULL <= -1ull) - error in preprocessor; - #endif - unsigned long long int ull = 18446744073709551615ULL; - typedef int a[(18446744073709551615ULL <= (unsigned long long int) -1 - ? 1 : -1)]; - int i = 63;]], - [[unsigned long long int ullmax = 18446744073709551615ull; - return (ull << 63 | ull >> 63 | ull << i | ull >> i - | ullmax / ull | ullmax % ull);]])], - [ac_cv_type_unsigned_long_long_int=yes], - [ac_cv_type_unsigned_long_long_int=no])]) - if test $ac_cv_type_unsigned_long_long_int = yes; then - AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], 1, - [Define to 1 if the system has the type `unsigned long long int'.]) - fi -]) - -# This macro is obsolescent and should go away soon. -AC_DEFUN([gl_AC_TYPE_UNSIGNED_LONG_LONG], -[ - AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) - ac_cv_type_unsigned_long_long=$ac_cv_type_unsigned_long_long_int - if test $ac_cv_type_unsigned_long_long = yes; then - AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1, - [Define if you have the 'unsigned long long' type.]) - fi -]) diff --git a/lgl/m4/unistd_h.m4 b/lgl/m4/unistd_h.m4 index b12f84e8ec..91c02e7c83 100644 --- a/lgl/m4/unistd_h.m4 +++ b/lgl/m4/unistd_h.m4 @@ -1,4 +1,4 @@ -# unistd_h.m4 serial 9 +# unistd_h.m4 serial 10 dnl Copyright (C) 2006-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -38,6 +38,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], GNULIB_FTRUNCATE=0; AC_SUBST([GNULIB_FTRUNCATE]) GNULIB_GETCWD=0; AC_SUBST([GNULIB_GETCWD]) GNULIB_GETLOGIN_R=0; AC_SUBST([GNULIB_GETLOGIN_R]) + GNULIB_GETPAGESIZE=0; AC_SUBST([GNULIB_GETPAGESIZE]) GNULIB_LCHOWN=0; AC_SUBST([GNULIB_LCHOWN]) GNULIB_LSEEK=0; AC_SUBST([GNULIB_LSEEK]) GNULIB_READLINK=0; AC_SUBST([GNULIB_READLINK]) @@ -45,9 +46,12 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], dnl Assume proper GNU behavior unless another module says otherwise. HAVE_DUP2=1; AC_SUBST([HAVE_DUP2]) HAVE_FTRUNCATE=1; AC_SUBST([HAVE_FTRUNCATE]) + HAVE_GETPAGESIZE=1; AC_SUBST([HAVE_GETPAGESIZE]) HAVE_READLINK=1; AC_SUBST([HAVE_READLINK]) HAVE_SLEEP=1; AC_SUBST([HAVE_SLEEP]) HAVE_DECL_GETLOGIN_R=1; AC_SUBST([HAVE_DECL_GETLOGIN_R]) + HAVE_OS_H=0; AC_SUBST([HAVE_OS_H]) + HAVE_SYS_PARAM_H=0; AC_SUBST([HAVE_SYS_PARAM_H]) REPLACE_CHOWN=0; AC_SUBST([REPLACE_CHOWN]) REPLACE_FCHDIR=0; AC_SUBST([REPLACE_FCHDIR]) REPLACE_GETCWD=0; AC_SUBST([REPLACE_GETCWD]) diff --git a/lgl/m4/vasnprintf.m4 b/lgl/m4/vasnprintf.m4 index ef2de787f0..6449a9c57f 100644 --- a/lgl/m4/vasnprintf.m4 +++ b/lgl/m4/vasnprintf.m4 @@ -1,4 +1,4 @@ -# vasnprintf.m4 serial 20 +# vasnprintf.m4 serial 23 dnl Copyright (C) 2002-2004, 2006-2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -45,7 +45,10 @@ AC_DEFUN([gl_PREREQ_PRINTF_PARSE], AC_REQUIRE([gt_TYPE_WCHAR_T]) AC_REQUIRE([gt_TYPE_WINT_T]) AC_REQUIRE([AC_TYPE_SIZE_T]) - AC_CHECK_TYPES(ptrdiff_t) + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) AC_REQUIRE([gt_AC_TYPE_INTMAX_T]) ]) @@ -178,6 +181,49 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_ZERO], esac ]) +# Extra prerequisites of lib/vasnprintf.c for supporting large precisions. +AC_DEFUN([gl_PREREQ_VASNPRINTF_PRECISION], +[ + AC_REQUIRE([gl_PRINTF_PRECISION]) + case "$gl_cv_func_printf_precision" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_UNBOUNDED_PRECISION], 1, + [Define if the vasnprintf implementation needs special code for + supporting large precisions without arbitrary bounds.]) + AC_DEFINE([NEED_PRINTF_DOUBLE], 1, + [Define if the vasnprintf implementation needs special code for + 'double' arguments.]) + AC_DEFINE([NEED_PRINTF_LONG_DOUBLE], 1, + [Define if the vasnprintf implementation needs special code for + 'long double' arguments.]) + ;; + esac +]) + +# Extra prerequisites of lib/vasnprintf.c for surviving out-of-memory +# conditions. +AC_DEFUN([gl_PREREQ_VASNPRINTF_ENOMEM], +[ + AC_REQUIRE([gl_PRINTF_ENOMEM]) + case "$gl_cv_func_printf_enomem" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_ENOMEM], 1, + [Define if the vasnprintf implementation needs special code for + surviving out-of-memory conditions.]) + AC_DEFINE([NEED_PRINTF_DOUBLE], 1, + [Define if the vasnprintf implementation needs special code for + 'double' arguments.]) + AC_DEFINE([NEED_PRINTF_LONG_DOUBLE], 1, + [Define if the vasnprintf implementation needs special code for + 'long double' arguments.]) + ;; + esac +]) + # Prerequisites of lib/vasnprintf.c including all extras for POSIX compliance. AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS], [ @@ -189,6 +235,8 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS], gl_PREREQ_VASNPRINTF_DIRECTIVE_F gl_PREREQ_VASNPRINTF_FLAG_GROUPING gl_PREREQ_VASNPRINTF_FLAG_ZERO + gl_PREREQ_VASNPRINTF_PRECISION + gl_PREREQ_VASNPRINTF_ENOMEM ]) # Prerequisites of lib/asnprintf.c. diff --git a/lgl/m4/wint_t.m4 b/lgl/m4/wint_t.m4 index 2cac1a7108..af5ed936cc 100644 --- a/lgl/m4/wint_t.m4 +++ b/lgl/m4/wint_t.m4 @@ -1,4 +1,4 @@ -# wint_t.m4 serial 2 (gettext-0.16.2) +# wint_t.m4 serial 2 (gettext-0.17) dnl Copyright (C) 2003, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, diff --git a/lgl/printf-parse.c b/lgl/printf-parse.c index 0b75c2860d..94c6c61328 100644 --- a/lgl/printf-parse.c +++ b/lgl/printf-parse.c @@ -63,6 +63,9 @@ /* malloc(), realloc(), free(). */ #include <stdlib.h> +/* errno. */ +#include <errno.h> + /* Checked size_t computations. */ #include "xsize.h" @@ -89,7 +92,7 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE)); if (d->dir == NULL) /* Out of memory. */ - return -1; + goto out_of_memory_1; a->count = 0; a_allocated = 0; @@ -109,13 +112,13 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) memory_size = xtimes (a_allocated, sizeof (argument)); \ if (size_overflow_p (memory_size)) \ /* Overflow, would lead to out of memory. */ \ - goto error; \ + goto out_of_memory; \ memory = (argument *) (a->arg \ ? realloc (a->arg, memory_size) \ : malloc (memory_size)); \ if (memory == NULL) \ /* Out of memory. */ \ - goto error; \ + goto out_of_memory; \ a->arg = memory; \ } \ while (a->count <= n) \ @@ -539,11 +542,11 @@ PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); if (size_overflow_p (memory_size)) /* Overflow, would lead to out of memory. */ - goto error; + goto out_of_memory; memory = (DIRECTIVE *) realloc (d->dir, memory_size); if (memory == NULL) /* Out of memory. */ - goto error; + goto out_of_memory; d->dir = memory; } } @@ -566,6 +569,16 @@ error: free (a->arg); if (d->dir) free (d->dir); + errno = EINVAL; + return -1; + +out_of_memory: + if (a->arg) + free (a->arg); + if (d->dir) + free (d->dir); +out_of_memory_1: + errno = ENOMEM; return -1; } diff --git a/lgl/realloc.c b/lgl/realloc.c index 4f6cddf537..64b7d78c57 100644 --- a/lgl/realloc.c +++ b/lgl/realloc.c @@ -18,18 +18,32 @@ /* written by Jim Meyering and Bruno Haible */ #include <config.h> + /* Only the AC_FUNC_REALLOC macro defines 'realloc' already in config.h. */ #ifdef realloc -# define NEED_REALLOC_GNU -# undef realloc +# define NEED_REALLOC_GNU 1 +#endif + +/* Infer the properties of the system's malloc function. + Only the AC_FUNC_MALLOC macro defines 'malloc' already in config.h. */ +#if GNULIB_MALLOC_GNU && !defined malloc +# define SYSTEM_MALLOC_GLIBC_COMPATIBLE 1 #endif +/* Below we want to call the system's malloc and realloc. + Undefine the symbols here so that including <stdlib.h> provides a + declaration of malloc(), not of rpl_malloc(), and likewise for realloc. */ +#undef malloc +#undef realloc + /* Specification. */ #include <stdlib.h> #include <errno.h> -/* Call the system's malloc and realloc below. */ +/* Below we want to call the system's malloc and realloc. + Undefine the symbols, if they were defined by gnulib's <stdlib.h> + replacement. */ #undef malloc #undef realloc @@ -42,7 +56,7 @@ rpl_realloc (void *p, size_t n) { void *result; -#ifdef NEED_REALLOC_GNU +#if NEED_REALLOC_GNU if (n == 0) { n = 1; @@ -53,7 +67,16 @@ rpl_realloc (void *p, size_t n) } #endif - result = (p == NULL ? malloc (n) : realloc (p, n)); + if (p == NULL) + { +#if GNULIB_REALLOC_GNU && !NEED_REALLOC_GNU && !SYSTEM_MALLOC_GLIBC_COMPATIBLE + if (n == 0) + n = 1; +#endif + result = malloc (n); + } + else + result = realloc (p, n); #if !HAVE_REALLOC_POSIX if (result == NULL) diff --git a/lgl/stdlib.in.h b/lgl/stdlib.in.h index 7d46562414..baebcce973 100644 --- a/lgl/stdlib.in.h +++ b/lgl/stdlib.in.h @@ -167,6 +167,15 @@ extern int mkstemp (char * /*template*/); #endif +#if @GNULIB_PUTENV@ +# if @REPLACE_PUTENV@ +# undef putenv +# define putenv rpl_putenv +extern int putenv (char *string); +# endif +#endif + + #ifdef __cplusplus } #endif diff --git a/lgl/string.in.h b/lgl/string.in.h index f458f4400d..a371e5c696 100644 --- a/lgl/string.in.h +++ b/lgl/string.in.h @@ -32,6 +32,7 @@ extern "C" { #endif + /* Return the first occurrence of NEEDLE in HAYSTACK. */ #if @GNULIB_MEMMEM@ # if ! @HAVE_DECL_MEMMEM@ @@ -103,50 +104,6 @@ extern char *stpncpy (char *restrict __dst, char const *restrict __src, stpncpy (a, b, n)) #endif -/* Compare strings S1 and S2, ignoring case, returning less than, equal to or - greater than zero if S1 is lexicographically less than, equal to or greater - than S2. - Note: This function does not work in multibyte locales. */ -#if ! @HAVE_STRCASECMP@ -extern int strcasecmp (char const *s1, char const *s2); -#endif -#if defined GNULIB_POSIXCHECK -/* strcasecmp() does not work with multibyte strings: - POSIX says that it operates on "strings", and "string" in POSIX is defined - as a sequence of bytes, not of characters. */ -# undef strcasecmp -# define strcasecmp(a,b) \ - (GL_LINK_WARNING ("strcasecmp cannot work correctly on character strings " \ - "in multibyte locales - " \ - "use mbscasecmp if you care about " \ - "internationalization, or use c_strcasecmp (from " \ - "gnulib module c-strcase) if you want a locale " \ - "independent function"), \ - strcasecmp (a, b)) -#endif - -/* Compare no more than N bytes of strings S1 and S2, ignoring case, - returning less than, equal to or greater than zero if S1 is - lexicographically less than, equal to or greater than S2. - Note: This function cannot work correctly in multibyte locales. */ -#if ! @HAVE_DECL_STRNCASECMP@ -extern int strncasecmp (char const *s1, char const *s2, size_t n); -#endif -#if defined GNULIB_POSIXCHECK -/* strncasecmp() does not work with multibyte strings: - POSIX says that it operates on "strings", and "string" in POSIX is defined - as a sequence of bytes, not of characters. */ -# undef strncasecmp -# define strncasecmp(a,b,n) \ - (GL_LINK_WARNING ("strncasecmp cannot work correctly on character " \ - "strings in multibyte locales - " \ - "use mbsncasecmp or mbspcasecmp if you care about " \ - "internationalization, or use c_strncasecmp (from " \ - "gnulib module c-strcase) if you want a locale " \ - "independent function"), \ - strncasecmp (a, b, n)) -#endif - #if defined GNULIB_POSIXCHECK /* strchr() does not work with multibyte strings if the locale encoding is GB18030 and the character to be searched is a digit. */ diff --git a/lgl/unistd.in.h b/lgl/unistd.in.h index 5405baf881..4916f75ced 100644 --- a/lgl/unistd.in.h +++ b/lgl/unistd.in.h @@ -180,6 +180,61 @@ extern int getlogin_r (char *name, size_t size); #endif +#if @GNULIB_GETPAGESIZE@ +# if !@HAVE_GETPAGESIZE@ +/* This is for POSIX systems. */ +# if !defined getpagesize && defined _SC_PAGESIZE +# if ! (defined __VMS && __VMS_VER < 70000000) +# define getpagesize() sysconf (_SC_PAGESIZE) +# endif +# endif +/* This is for older VMS. */ +# if !defined getpagesize && defined __VMS +# ifdef __ALPHA +# define getpagesize() 8192 +# else +# define getpagesize() 512 +# endif +# endif +/* This is for BeOS. */ +# if !defined getpagesize && @HAVE_OS_H@ +# include <OS.h> +# if defined B_PAGE_SIZE +# define getpagesize() B_PAGE_SIZE +# endif +# endif +/* This is for AmigaOS4.0. */ +# if !defined getpagesize && defined __amigaos4__ +# define getpagesize() 2048 +# endif +/* This is for older Unix systems. */ +# if !defined getpagesize && @HAVE_SYS_PARAM_H@ +# include <sys/param.h> +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else +# ifdef NBPG +# ifndef CLSIZE +# define CLSIZE 1 +# endif +# define getpagesize() (NBPG * CLSIZE) +# else +# ifdef NBPC +# define getpagesize() NBPC +# endif +# endif +# endif +# endif +# endif +#elif defined GNULIB_POSIXCHECK +# undef getpagesize +# define getpagesize() \ + (GL_LINK_WARNING ("getpagesize is unportable - " \ + "use gnulib module getpagesize for portability"), \ + getpagesize ()) +#endif + + #if @GNULIB_LCHOWN@ # if @REPLACE_LCHOWN@ /* Change the owner of FILE to UID (if UID is not -1) and the group of FILE diff --git a/lgl/vasnprintf.c b/lgl/vasnprintf.c index ee7c319023..6c8d5dcbdc 100644 --- a/lgl/vasnprintf.c +++ b/lgl/vasnprintf.c @@ -88,27 +88,30 @@ /* Checked size_t computations. */ #include "xsize.h" -#if NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL +#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL # include <math.h> # include "float+.h" -# include "fpucw.h" #endif -#if NEED_PRINTF_INFINITE_DOUBLE && !defined IN_LIBINTL +#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL # include <math.h> # include "isnan.h" #endif -#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !defined IN_LIBINTL +#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL # include <math.h> # include "isnanl-nolibm.h" # include "fpucw.h" #endif -#if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL # include <math.h> # include "isnan.h" # include "printf-frexp.h" +#endif + +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL +# include <math.h> # include "isnanl-nolibm.h" # include "printf-frexpl.h" # include "fpucw.h" @@ -200,7 +203,7 @@ local_wcslen (const wchar_t *s) /* Here we need to call the native sprintf, not rpl_sprintf. */ #undef sprintf -#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL +#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_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 # define decimal_point_char_defined 1 @@ -227,7 +230,7 @@ decimal_point_char () # endif #endif -#if NEED_PRINTF_INFINITE_DOUBLE && !defined IN_LIBINTL +#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL /* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ static int @@ -238,7 +241,7 @@ is_infinite_or_zero (double x) #endif -#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !defined IN_LIBINTL +#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL /* Equivalent to !isfinite(x), but does not require libm. */ static int @@ -249,7 +252,7 @@ is_infinitel (long double x) #endif -#if NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL +#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL /* Converting 'long double' to decimal without rare rounding bugs requires real bignums. We use the naming conventions of GNU gmp, but vastly simpler @@ -795,6 +798,8 @@ convert_to_decimal (mpn_t a, size_t extra_zeroes) return c_ptr; } +# if NEED_PRINTF_LONG_DOUBLE + /* Assuming x is finite and >= 0: write x as x = 2^e * m, where m is a bignum. Return the allocated memory in case of success, NULL in case of memory @@ -823,8 +828,8 @@ decode_long_double (long double x, int *ep, mpn_t *mp) 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int', doesn't matter). */ -# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0 -# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2 +# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0 +# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2 { mp_limb_t hi, lo; y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2)); @@ -839,7 +844,7 @@ decode_long_double (long double x, int *ep, mpn_t *mp) abort (); m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo; } -# else +# else { mp_limb_t d; y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS); @@ -849,8 +854,8 @@ decode_long_double (long double x, int *ep, mpn_t *mp) abort (); m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d; } +# endif # endif -# endif for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) { mp_limb_t hi, lo; @@ -866,8 +871,11 @@ decode_long_double (long double x, int *ep, mpn_t *mp) abort (); m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo; } +#if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess + precision. */ if (!(y == 0.0L)) abort (); +#endif /* Normalise. */ while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) m.nlimbs--; @@ -876,17 +884,101 @@ decode_long_double (long double x, int *ep, mpn_t *mp) return m.limbs; } -/* Assuming x is finite and >= 0, and n is an integer: +# endif + +# if NEED_PRINTF_DOUBLE + +/* Assuming x is finite and >= 0: + write x as x = 2^e * m, where m is a bignum. + Return the allocated memory in case of success, NULL in case of memory + allocation failure. */ +static void * +decode_double (double x, int *ep, mpn_t *mp) +{ + mpn_t m; + int exp; + double y; + size_t i; + + /* Allocate memory for result. */ + m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; + m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t)); + if (m.limbs == NULL) + return NULL; + /* Split into exponential part and mantissa. */ + y = frexp (x, &exp); + if (!(y >= 0.0 && y < 1.0)) + abort (); + /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * DBL_MANT_BIT), and the + latter is an integer. */ + /* Convert the mantissa (y * DBL_MANT_BIT) to a sequence of limbs. + I'm not sure whether it's safe to cast a 'double' value between + 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only + 'double' values between 0 and 2^16 (to 'unsigned int' or 'int', + doesn't matter). */ +# if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0 +# if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2 + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2)); + hi = (int) y; + y -= hi; + if (!(y >= 0.0 && y < 1.0)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0 && y < 1.0)) + abort (); + m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } +# else + { + mp_limb_t d; + y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS); + d = (int) y; + y -= d; + if (!(y >= 0.0 && y < 1.0)) + abort (); + m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d; + } +# endif +# endif + for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) + { + mp_limb_t hi, lo; + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + hi = (int) y; + y -= hi; + if (!(y >= 0.0 && y < 1.0)) + abort (); + y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); + lo = (int) y; + y -= lo; + if (!(y >= 0.0 && y < 1.0)) + abort (); + m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo; + } + if (!(y == 0.0)) + abort (); + /* Normalise. */ + while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) + m.nlimbs--; + *mp = m; + *ep = exp - DBL_MANT_BIT; + return m.limbs; +} + +# endif + +/* Assuming x = 2^e * m is finite and >= 0, and n is an integer: Returns the decimal representation of round (x * 10^n). Return the allocated memory - containing the decimal digits in low-to-high order, terminated with a NUL character - in case of success, NULL in case of memory allocation failure. */ static char * -scale10_round_decimal_long_double (long double x, int n) +scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n) { - int e; - mpn_t m; - void *memory = decode_long_double (x, &e, &m); int s; size_t extra_zeroes; unsigned int abs_n; @@ -1066,7 +1158,7 @@ scale10_round_decimal_long_double (long double x, int n) size_t count; for (count = m.nlimbs; count > 0; count--) { - accu += (mp_twolimb_t) *sourceptr++ << s; + accu += (mp_twolimb_t) *sourceptr++ << s_bits; *destptr++ = (mp_limb_t) accu; accu = accu >> GMP_LIMB_BITS; } @@ -1099,6 +1191,44 @@ scale10_round_decimal_long_double (long double x, int n) return digits; } +# if NEED_PRINTF_LONG_DOUBLE + +/* Assuming x is finite and >= 0, and n is an integer: + Returns the decimal representation of round (x * 10^n). + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +scale10_round_decimal_long_double (long double x, int n) +{ + int e; + mpn_t m; + void *memory = decode_long_double (x, &e, &m); + return scale10_round_decimal_decoded (e, m, memory, n); +} + +# endif + +# if NEED_PRINTF_DOUBLE + +/* Assuming x is finite and >= 0, and n is an integer: + Returns the decimal representation of round (x * 10^n). + Return the allocated memory - containing the decimal digits in low-to-high + order, terminated with a NUL character - in case of success, NULL in case + of memory allocation failure. */ +static char * +scale10_round_decimal_double (double x, int n) +{ + int e; + mpn_t m; + void *memory = decode_double (x, &e, &m); + return scale10_round_decimal_decoded (e, m, memory, n); +} + +# endif + +# if NEED_PRINTF_LONG_DOUBLE + /* Assuming x is finite and > 0: Return an approximation for n with 10^n <= x < 10^(n+1). The approximation is usually the right n, but may be off by 1 sometimes. */ @@ -1186,6 +1316,99 @@ floorlog10l (long double x) return (int) l + (l < 0 ? -1 : 0); } +# endif + +# if NEED_PRINTF_DOUBLE + +/* Assuming x is finite and > 0: + Return an approximation for n with 10^n <= x < 10^(n+1). + The approximation is usually the right n, but may be off by 1 sometimes. */ +static int +floorlog10 (double x) +{ + int exp; + double y; + double z; + double l; + + /* Split into exponential part and mantissa. */ + y = frexp (x, &exp); + if (!(y >= 0.0 && y < 1.0)) + abort (); + if (y == 0.0) + return INT_MIN; + if (y < 0.5) + { + while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2)))) + { + y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2)); + exp -= GMP_LIMB_BITS; + } + if (y < (1.0 / (1 << 16))) + { + y *= 1.0 * (1 << 16); + exp -= 16; + } + if (y < (1.0 / (1 << 8))) + { + y *= 1.0 * (1 << 8); + exp -= 8; + } + if (y < (1.0 / (1 << 4))) + { + y *= 1.0 * (1 << 4); + exp -= 4; + } + if (y < (1.0 / (1 << 2))) + { + y *= 1.0 * (1 << 2); + exp -= 2; + } + if (y < (1.0 / (1 << 1))) + { + y *= 1.0 * (1 << 1); + exp -= 1; + } + } + if (!(y >= 0.5 && y < 1.0)) + abort (); + /* Compute an approximation for l = log2(x) = exp + log2(y). */ + l = exp; + z = y; + if (z < 0.70710678118654752444) + { + z *= 1.4142135623730950488; + l -= 0.5; + } + if (z < 0.8408964152537145431) + { + z *= 1.1892071150027210667; + l -= 0.25; + } + if (z < 0.91700404320467123175) + { + z *= 1.0905077326652576592; + l -= 0.125; + } + if (z < 0.9576032806985736469) + { + z *= 1.0442737824274138403; + l -= 0.0625; + } + /* Now 0.95 <= z <= 1.01. */ + z = 1 - z; + /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ... + Four terms are enough to get an approximation with error < 10^-7. */ + l -= z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); + /* Finally multiply with log(2)/log(10), yields an approximation for + log10(x). */ + l *= 0.30102999566398119523; + /* Round down to the next integer. */ + return (int) l + (l < 0 ? -1 : 0); +} + +# endif + #endif DCHAR_T * @@ -1196,10 +1419,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, arguments a; if (PRINTF_PARSE (format, &d, &a) < 0) - { - errno = EINVAL; - return NULL; - } + /* errno is already set. */ + return NULL; #define CLEANUP() \ free (d.dir); \ @@ -1819,8 +2040,19 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } #endif -#if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL - else if (dp->conversion == 'a' || dp->conversion == 'A') +#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)) + && (0 +# if NEED_PRINTF_DOUBLE + || a.arg[dp->arg_index].type == TYPE_DOUBLE +# endif +# if NEED_PRINTF_LONG_DOUBLE + || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE +# endif + ) +# endif + ) { arg_type type = a.arg[dp->arg_index].type; int flags = dp->flags; @@ -1938,6 +2170,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, p = tmp; if (type == TYPE_LONGDOUBLE) { +# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE long double arg = a.arg[dp->arg_index].a.a_longdouble; if (isnanl (arg)) @@ -2057,7 +2290,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } *p++ = dp->conversion - 'A' + 'P'; -# if WIDE_CHAR_VERSION +# if WIDE_CHAR_VERSION { static const wchar_t decimal_format[] = { '%', '+', 'd', '\0' }; @@ -2065,7 +2298,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } while (*p != '\0') p++; -# else +# else if (sizeof (DCHAR_T) == 1) { sprintf ((char *) p, "%+d", exponent); @@ -2080,14 +2313,18 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, for (ep = expbuf; (*p = *ep) != '\0'; ep++) p++; } -# endif +# endif } END_LONG_DOUBLE_ROUNDING (); } +# else + abort (); +# endif } else { +# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE double arg = a.arg[dp->arg_index].a.a_double; if (isnan (arg)) @@ -2204,7 +2441,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } *p++ = dp->conversion - 'A' + 'P'; -# if WIDE_CHAR_VERSION +# if WIDE_CHAR_VERSION { static const wchar_t decimal_format[] = { '%', '+', 'd', '\0' }; @@ -2212,7 +2449,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } while (*p != '\0') p++; -# else +# else if (sizeof (DCHAR_T) == 1) { sprintf ((char *) p, "%+d", exponent); @@ -2227,9 +2464,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, for (ep = expbuf; (*p = *ep) != '\0'; ep++) p++; } -# endif +# endif } } +# else + abort (); +# endif } /* The generated string now extends from tmp to p, with the zero padding insertion point being at pad_ptr. */ @@ -2292,13 +2532,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } #endif -#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL +#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL else if ((dp->conversion == 'f' || dp->conversion == 'F' || dp->conversion == 'e' || dp->conversion == 'E' || dp->conversion == 'g' || dp->conversion == 'G' || dp->conversion == 'a' || dp->conversion == 'A') && (0 -# if NEED_PRINTF_INFINITE_DOUBLE +# if NEED_PRINTF_DOUBLE + || a.arg[dp->arg_index].type == TYPE_DOUBLE +# elif NEED_PRINTF_INFINITE_DOUBLE || (a.arg[dp->arg_index].type == TYPE_DOUBLE /* The systems (mingw) which produce wrong output for Inf, -Inf, and NaN also do so for -0.0. @@ -2315,7 +2557,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, # endif )) { -# if NEED_PRINTF_INFINITE_DOUBLE && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) +# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) arg_type type = a.arg[dp->arg_index].type; # endif int flags = dp->flags; @@ -2398,17 +2640,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, precision = 6; /* Allocate a temporary buffer of sufficient size. */ -# if NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE +# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE + tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1); +# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0); # elif NEED_PRINTF_LONG_DOUBLE tmp_length = LDBL_DIG + 1; +# elif NEED_PRINTF_DOUBLE + tmp_length = DBL_DIG + 1; # else tmp_length = 0; # endif if (tmp_length < precision) tmp_length = precision; # if NEED_PRINTF_LONG_DOUBLE -# if NEED_PRINTF_INFINITE_DOUBLE +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE if (type == TYPE_LONGDOUBLE) # endif if (dp->conversion == 'f' || dp->conversion == 'F') @@ -2423,6 +2669,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } # endif +# if NEED_PRINTF_DOUBLE +# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE + if (type == TYPE_DOUBLE) +# endif + if (dp->conversion == 'f' || dp->conversion == 'F') + { + double arg = a.arg[dp->arg_index].a.a_double; + if (!(isnan (arg) || arg + arg == arg)) + { + /* arg is finite and nonzero. */ + int exponent = floorlog10 (arg < 0 ? -arg : arg); + if (exponent >= 0 && tmp_length < exponent + precision) + tmp_length = exponent + precision; + } + } +# endif /* Account for sign, decimal point etc. */ tmp_length = xsum (tmp_length, 12); @@ -2450,7 +2712,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, p = tmp; # if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE -# if NEED_PRINTF_INFINITE_DOUBLE +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE if (type == TYPE_LONGDOUBLE) # endif { @@ -2810,13 +3072,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, END_LONG_DOUBLE_ROUNDING (); } } -# if NEED_PRINTF_INFINITE_DOUBLE +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE else # endif # endif -# if NEED_PRINTF_INFINITE_DOUBLE +# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE { - /* Simpler than above: handle only NaN, Infinity, zero. */ double arg = a.arg[dp->arg_index].a.a_double; if (isnan (arg)) @@ -2834,7 +3095,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { int sign = 0; - if (signbit (arg)) /* arg < 0.0L or negative zero */ + if (signbit (arg)) /* arg < 0.0 or negative zero */ { sign = -1; arg = -arg; @@ -2860,6 +3121,332 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } else { +# if NEED_PRINTF_DOUBLE + pad_ptr = p; + + if (dp->conversion == 'f' || dp->conversion == 'F') + { + char *digits; + size_t ndigits; + + digits = + scale10_round_decimal_double (arg, precision); + if (digits == NULL) + goto out_of_memory; + ndigits = strlen (digits); + + if (ndigits > precision) + do + { + --ndigits; + *p++ = digits[ndigits]; + } + while (ndigits > precision); + else + *p++ = '0'; + /* Here ndigits <= precision. */ + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > ndigits; precision--) + *p++ = '0'; + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + else if (dp->conversion == 'e' || dp->conversion == 'E') + { + int exponent; + + if (arg == 0.0) + { + exponent = 0; + *p++ = '0'; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + for (; precision > 0; precision--) + *p++ = '0'; + } + } + else + { + /* arg > 0.0. */ + int adjusted; + char *digits; + size_t ndigits; + + exponent = floorlog10 (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_double (arg, + (int)precision - exponent); + if (digits == NULL) + goto out_of_memory; + ndigits = strlen (digits); + + if (ndigits == precision + 1) + break; + if (ndigits < precision + || ndigits > precision + 2) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits == precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + + /* Here ndigits = precision+1. */ + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || precision > 0) + { + *p++ = decimal_point_char (); + while (ndigits > 0) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + + free (digits); + } + + *p++ = dp->conversion; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + { '%', '+', '.', '3', 'd', '\0' }; +# else + { '%', '+', '.', '2', 'd', '\0' }; +# endif + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + { + static const char decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + "%+.3d"; +# else + "%+.2d"; +# endif + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, decimal_format, exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, decimal_format, exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } + } +# endif + } + else if (dp->conversion == 'g' || dp->conversion == 'G') + { + if (precision == 0) + precision = 1; + /* precision >= 1. */ + + if (arg == 0.0) + /* The exponent is 0, >= -4, < precision. + Use fixed-point notation. */ + { + size_t ndigits = precision; + /* Number of trailing zeroes that have to be + dropped. */ + size_t nzeroes = + (flags & FLAG_ALT ? 0 : precision - 1); + + --ndigits; + *p++ = '0'; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = '0'; + } + } + } + else + { + /* arg > 0.0. */ + int exponent; + int adjusted; + char *digits; + size_t ndigits; + size_t nzeroes; + + exponent = floorlog10 (arg); + adjusted = 0; + for (;;) + { + digits = + scale10_round_decimal_double (arg, + (int)(precision - 1) - exponent); + if (digits == NULL) + goto out_of_memory; + ndigits = strlen (digits); + + if (ndigits == precision) + break; + if (ndigits < precision - 1 + || ndigits > precision + 1) + /* The exponent was not guessed + precisely enough. */ + abort (); + if (adjusted) + /* None of two values of exponent is + the right one. Prevent an endless + loop. */ + abort (); + free (digits); + if (ndigits < precision) + exponent -= 1; + else + exponent += 1; + adjusted = 1; + } + /* Here ndigits = precision. */ + + /* Determine the number of trailing zeroes + that have to be dropped. */ + nzeroes = 0; + if ((flags & FLAG_ALT) == 0) + while (nzeroes < ndigits + && digits[nzeroes] == '0') + nzeroes++; + + /* The exponent is now determined. */ + if (exponent >= -4 + && exponent < (long)precision) + { + /* Fixed-point notation: + max(exponent,0)+1 digits, then the + decimal point, then the remaining + digits without trailing zeroes. */ + if (exponent >= 0) + { + size_t count = exponent + 1; + /* Note: count <= precision = ndigits. */ + for (; count > 0; count--) + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + size_t count = -exponent - 1; + *p++ = '0'; + *p++ = decimal_point_char (); + for (; count > 0; count--) + *p++ = '0'; + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + } + else + { + /* Exponential notation. */ + *p++ = digits[--ndigits]; + if ((flags & FLAG_ALT) || ndigits > nzeroes) + { + *p++ = decimal_point_char (); + while (ndigits > nzeroes) + { + --ndigits; + *p++ = digits[ndigits]; + } + } + *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */ +# if WIDE_CHAR_VERSION + { + static const wchar_t decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + { '%', '+', '.', '3', 'd', '\0' }; +# else + { '%', '+', '.', '2', 'd', '\0' }; +# endif + SNPRINTF (p, 6 + 1, decimal_format, exponent); + } + while (*p != '\0') + p++; +# else + { + static const char decimal_format[] = + /* Produce the same number of exponent digits + as the native printf implementation. */ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + "%+.3d"; +# else + "%+.2d"; +# endif + if (sizeof (DCHAR_T) == 1) + { + sprintf ((char *) p, decimal_format, exponent); + while (*p != '\0') + p++; + } + else + { + char expbuf[6 + 1]; + const char *ep; + sprintf (expbuf, decimal_format, exponent); + for (ep = expbuf; (*p = *ep) != '\0'; ep++) + p++; + } + } +# endif + } + + free (digits); + } + } + else + abort (); +# else + /* arg is finite. */ if (!(arg == 0.0)) abort (); @@ -2888,9 +3475,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, *p++ = '+'; /* Produce the same number of exponent digits as the native printf implementation. */ -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ *p++ = '0'; -# endif +# endif *p++ = '0'; *p++ = '0'; } @@ -2908,6 +3495,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } else abort (); +# endif } } } @@ -2978,11 +3566,20 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { arg_type type = a.arg[dp->arg_index].type; int flags = dp->flags; -#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO +#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION int has_width; size_t width; #endif -#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO +#if !USE_SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION + int has_precision; + size_t precision; +#endif +#if NEED_PRINTF_UNBOUNDED_PRECISION + int prec_ourselves; +#else +# define prec_ourselves 0 +#endif +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION int pad_ourselves; #else # define pad_ourselves 0 @@ -2996,7 +3593,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, TCHAR_T *tmp; #endif -#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO +#if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION has_width = 0; width = 0; if (dp->width_start != dp->width_end) @@ -3030,34 +3627,42 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif +#if !USE_SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION + 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; + } + } +#endif + #if !USE_SNPRINTF /* Allocate a temporary buffer of sufficient size for calling sprintf. */ { - size_t precision; - - 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; - precision = (arg < 0 ? 0 : arg); - } - else - { - const FCHAR_T *digitp = dp->precision_start + 1; - - precision = 0; - while (digitp != dp->precision_end) - precision = xsum (xtimes (precision, 10), *digitp++ - '0'); - } - } - switch (dp->conversion) { @@ -3262,8 +3867,23 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif + /* Decide whether to handle the precision ourselves. */ +#if NEED_PRINTF_UNBOUNDED_PRECISION + switch (dp->conversion) + { + case 'd': case 'i': case 'u': + case 'o': + case 'x': case 'X': case 'p': + prec_ourselves = has_precision && (precision > 0); + break; + default: + prec_ourselves = 0; + break; + } +#endif + /* Decide whether to perform the padding ourselves. */ -#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION switch (dp->conversion) { # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO @@ -3280,7 +3900,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, pad_ourselves = 1; break; default: - pad_ourselves = 0; + pad_ourselves = prec_ourselves; break; } #endif @@ -3328,22 +3948,25 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } } } - if (dp->precision_start != dp->precision_end) + if (!prec_ourselves) { - size_t n = dp->precision_end - dp->precision_start; - /* The precision specification is known to consist only - of standard ASCII characters. */ - if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) + if (dp->precision_start != dp->precision_end) { - memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T)); - fbp += n; - } - else - { - const FCHAR_T *mp = dp->precision_start; - do - *fbp++ = (unsigned char) *mp++; - while (--n > 0); + size_t n = dp->precision_end - dp->precision_start; + /* The precision specification is known to consist only + of standard ASCII characters. */ + if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) + { + memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T)); + fbp += n; + } + else + { + const FCHAR_T *mp = dp->precision_start; + do + *fbp++ = (unsigned char) *mp++; + while (--n > 0); + } } } @@ -3426,9 +4049,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, sizeof (TCHAR_T) divides sizeof (DCHAR_T) and alignof (TCHAR_T) <= alignof (DCHAR_T). */ # define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T)) + /* Ensure that maxlen below will be >= 2. Needed on BeOS, + where an snprintf() with maxlen==1 acts like sprintf(). */ + ENSURE_ALLOCATION (xsum (length, + (2 + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR)); /* Prepare checking whether snprintf returns the count via %n. */ - ENSURE_ALLOCATION (xsum (length, 1)); *(TCHAR_T *) (result + length) = '\0'; #endif @@ -3660,8 +4287,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #if USE_SNPRINTF - /* Handle overflow of the allocated buffer. */ - if (count >= maxlen) + /* Handle overflow of the allocated buffer. + If such an overflow occurs, a C99 compliant snprintf() + returns a count >= maxlen. However, a non-compliant + snprintf() function returns only count = maxlen - 1. To + cover both cases, test whether count >= maxlen - 1. */ + if ((unsigned int) count + 1 >= maxlen) { /* If maxlen already has attained its allowed maximum, allocating more memory will not increase maxlen. @@ -3670,13 +4301,19 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, goto overflow; else { - /* Need at least count * sizeof (TCHAR_T) bytes. - But allocate proportionally, to avoid looping + /* Need at least (count + 1) * sizeof (TCHAR_T) + bytes. (The +1 is for the trailing NUL.) + But ask for (count + 2) * sizeof (TCHAR_T) + bytes, so that in the next round, we likely get + maxlen > (unsigned int) count + 1 + and so we don't get here again. + And allocate proportionally, to avoid looping eternally if snprintf() reports a too small count. */ size_t n = xmax (xsum (length, - (count + TCHARS_PER_DCHAR - 1) + ((unsigned int) count + 2 + + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR), xtimes (allocated, 2)); @@ -3686,6 +4323,69 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, } #endif +#if NEED_PRINTF_UNBOUNDED_PRECISION + if (prec_ourselves) + { + /* Handle the precision. */ + TCHAR_T *prec_ptr = +# if USE_SNPRINTF + (TCHAR_T *) (result + length); +# else + tmp; +# endif + size_t prefix_count; + size_t move; + + prefix_count = 0; + /* Put the additional zeroes after the sign. */ + if (count >= 1 + && (*prec_ptr == '-' || *prec_ptr == '+' + || *prec_ptr == ' ')) + prefix_count = 1; + /* Put the additional zeroes after the 0x prefix if + (flags & FLAG_ALT) || (dp->conversion == 'p'). */ + else if (count >= 2 + && prec_ptr[0] == '0' + && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X')) + prefix_count = 2; + + move = count - prefix_count; + if (precision > move) + { + /* Insert zeroes. */ + size_t insert = precision - move; + TCHAR_T *prec_end; + +# if USE_SNPRINTF + size_t n = + xsum (length, + (count + insert + TCHARS_PER_DCHAR - 1) + / TCHARS_PER_DCHAR); + length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; + ENSURE_ALLOCATION (n); + length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; + prec_ptr = (TCHAR_T *) (result + length); +# endif + + prec_end = prec_ptr + count; + prec_ptr += prefix_count; + + while (prec_end > prec_ptr) + { + prec_end--; + prec_end[insert] = prec_end[0]; + } + + prec_end += insert; + do + *--prec_end = '0'; + while (prec_end > prec_ptr); + + count += insert; + } + } +#endif + #if !DCHAR_IS_TCHAR # if !USE_SNPRINTF if (count >= tmp_length) @@ -3794,7 +4494,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* Here count <= allocated - length. */ /* Perform padding. */ -#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO +#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION if (pad_ourselves && has_width) { size_t w; @@ -3978,9 +4678,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #undef TCHARS_PER_DCHAR #undef SNPRINTF #undef USE_SNPRINTF +#undef DCHAR_CPY #undef PRINTF_PARSE #undef DIRECTIVES #undef DIRECTIVE +#undef DCHAR_IS_TCHAR #undef TCHAR_T #undef DCHAR_T #undef FCHAR_T |