From e9bb23084ab2af1b2792808165335e6daebebfa9 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 6 May 2007 23:02:10 +0000 Subject: [PATCH] Work around an incorrect implementation of the 0 flag on most platforms. --- ChangeLog | 30 ++++++ doc/functions/fprintf.texi | 8 +- doc/functions/printf.texi | 8 +- doc/functions/snprintf.texi | 8 +- doc/functions/sprintf.texi | 8 +- doc/functions/vfprintf.texi | 8 +- doc/functions/vprintf.texi | 8 +- doc/functions/vsnprintf.texi | 8 +- doc/functions/vsprintf.texi | 8 +- lib/vasnprintf.c | 223 +++++++++++++++++++++++++++++++----------- m4/fprintf-posix.m4 | 12 ++- m4/printf.m4 | 107 +++++++++++++------- m4/snprintf-posix.m4 | 22 +++-- m4/sprintf-posix.m4 | 12 ++- m4/vasnprintf-posix.m4 | 17 +++- m4/vasnprintf.m4 | 17 +++- m4/vasprintf-posix.m4 | 17 +++- m4/vfprintf-posix.m4 | 12 ++- m4/vsnprintf-posix.m4 | 22 +++-- m4/vsprintf-posix.m4 | 12 ++- tests/test-snprintf-posix.h | 129 +++++++++++++++++++++++- tests/test-sprintf-posix.h | 117 +++++++++++++++++++++- tests/test-vasnprintf-posix.c | 145 ++++++++++++++++++++++++++- tests/test-vasprintf-posix.c | 145 ++++++++++++++++++++++++++- 24 files changed, 935 insertions(+), 168 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3bae344b7..9ffbae819 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,35 @@ 2007-05-06 Bruno Haible + * lib/vasnprintf.c (VASNPRINTF) [NEED_PRINTF_FLAG_ZERO]: Perform the + padding ourselves for the floating-point directives. + * m4/printf.m4 (gl_PRINTF_FLAG_ZERO): New macro. + * m4/vasnprintf.m4 (gl_PREREQ_VASNPRINTF_FLAG_ZERO): New macro. + * m4/snprintf-posix.m4 (gl_FUNC_SNPRINTF_POSIX): Invoke + gl_PRINTF_FLAG_ZERO and test its result. Invoke + gl_PREREQ_VASNPRINTF_FLAG_ZERO. + * m4/sprintf-posix.m4 (gl_FUNC_SPRINTF_POSIX): Likewise. + * m4/fprintf-posix.m4 (gl_FUNC_FPRINTF_POSIX): Likewise. + * m4/vasnprintf-posix.m4 (gl_FUNC_VASNPRINTF_POSIX): Likewise. + * m4/vasprintf-posix.m4 (gl_FUNC_VASPRINTF_POSIX): Likewise. + * m4/vfprintf-posix.m4 (gl_FUNC_VFPRINTF_POSIX): Likewise. + * m4/vsnprintf-posix.m4 (gl_FUNC_VSNPRINTF_POSIX): Likewise. + * m4/vsprintf-posix.m4 (gl_FUNC_VSPRINTF_POSIX): Likewise. + * tests/test-snprintf-posix.h (test_function): Also check the width + and some flags in the %f directive. + * tests/test-sprintf-posix.h (test_function): Likewise. + * tests/test-vasnprintf-posix.c (test_function): Likewise. + * tests/test-vasprintf-posix.c (test_function): Likewise. + * doc/functions/fprintf.texi: Update. + * doc/functions/printf.texi: Update. + * doc/functions/snprintf.texi: Update. + * doc/functions/sprintf.texi: Update. + * doc/functions/vfprintf.texi: Update. + * doc/functions/vprintf.texi: Update. + * doc/functions/vsnprintf.texi: Update. + * doc/functions/vsprintf.texi: Update. + +2007-05-06 Bruno Haible + * lib/vasnprintf.c (VASNPRINTF) [NEED_PRINTF_FLAG_GROUPING]: Don't pass the ' flag character to sprintf or snprintf. * m4/printf.m4 (gl_PRINTF_FLAG_GROUPING): New macro. diff --git a/doc/functions/fprintf.texi b/doc/functions/fprintf.texi index 476c31cab..661964034 100644 --- a/doc/functions/fprintf.texi +++ b/doc/functions/fprintf.texi @@ -26,15 +26,15 @@ NetBSD 3.0, mingw, BeOS. @item This function doesn't support the @code{'} flag on some platforms: NetBSD 3.0, mingw. +@item +printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded +with zeroes) on some platforms: +MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw. @end itemize Portability problems not fixed by Gnulib: @itemize @item -printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded -with zeroes) on some platforms: -FreeBSD 6.0. -@item printf of @samp{long double} numbers is unsupported on some platforms: mingw. @end itemize diff --git a/doc/functions/printf.texi b/doc/functions/printf.texi index f794c8011..cd76aa9ec 100644 --- a/doc/functions/printf.texi +++ b/doc/functions/printf.texi @@ -26,15 +26,15 @@ NetBSD 3.0, mingw, BeOS. @item This function doesn't support the @code{'} flag on some platforms: NetBSD 3.0, mingw. +@item +printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded +with zeroes) on some platforms: +MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw. @end itemize Portability problems not fixed by Gnulib: @itemize @item -printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded -with zeroes) on some platforms: -FreeBSD 6.0. -@item printf of @samp{long double} numbers is unsupported on some platforms: mingw. @end itemize diff --git a/doc/functions/snprintf.texi b/doc/functions/snprintf.texi index 5a41a67d9..f7427bbe1 100644 --- a/doc/functions/snprintf.texi +++ b/doc/functions/snprintf.texi @@ -34,6 +34,10 @@ NetBSD 3.0, mingw, BeOS. This function doesn't support the @code{'} flag on some platforms: NetBSD 3.0, mingw. @item +printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded +with zeroes) on some platforms: +MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw. +@item This function does not truncate the result as specified in C99 on some platforms: mingw. @item @@ -51,10 +55,6 @@ OSF/1 5.1. Portability problems not fixed by Gnulib: @itemize @item -printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded -with zeroes) on some platforms: -FreeBSD 6.0. -@item printf of @samp{long double} numbers is unsupported on some platforms: mingw. @end itemize diff --git a/doc/functions/sprintf.texi b/doc/functions/sprintf.texi index 0760dd5dc..30a12733b 100644 --- a/doc/functions/sprintf.texi +++ b/doc/functions/sprintf.texi @@ -26,15 +26,15 @@ NetBSD 3.0, mingw, BeOS. @item This function doesn't support the @code{'} flag on some platforms: NetBSD 3.0, mingw. +@item +printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded +with zeroes) on some platforms: +MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw. @end itemize Portability problems not fixed by Gnulib: @itemize @item -printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded -with zeroes) on some platforms: -FreeBSD 6.0. -@item printf of @samp{long double} numbers is unsupported on some platforms: mingw. @end itemize diff --git a/doc/functions/vfprintf.texi b/doc/functions/vfprintf.texi index d5eeef276..5010ba254 100644 --- a/doc/functions/vfprintf.texi +++ b/doc/functions/vfprintf.texi @@ -26,15 +26,15 @@ NetBSD 3.0, mingw, BeOS. @item This function doesn't support the @code{'} flag on some platforms: NetBSD 3.0, mingw. +@item +printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded +with zeroes) on some platforms: +MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw. @end itemize Portability problems not fixed by Gnulib: @itemize @item -printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded -with zeroes) on some platforms: -FreeBSD 6.0. -@item printf of @samp{long double} numbers is unsupported on some platforms: mingw. @end itemize diff --git a/doc/functions/vprintf.texi b/doc/functions/vprintf.texi index 430dab203..f7b860932 100644 --- a/doc/functions/vprintf.texi +++ b/doc/functions/vprintf.texi @@ -26,15 +26,15 @@ NetBSD 3.0, mingw, BeOS. @item This function doesn't support the @code{'} flag on some platforms: NetBSD 3.0, mingw. +@item +printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded +with zeroes) on some platforms: +MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw. @end itemize Portability problems not fixed by Gnulib: @itemize @item -printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded -with zeroes) on some platforms: -FreeBSD 6.0. -@item printf of @samp{long double} numbers is unsupported on some platforms: mingw. @end itemize diff --git a/doc/functions/vsnprintf.texi b/doc/functions/vsnprintf.texi index 3e6171672..4be1bbf5b 100644 --- a/doc/functions/vsnprintf.texi +++ b/doc/functions/vsnprintf.texi @@ -34,6 +34,10 @@ NetBSD 3.0, mingw, BeOS. This function doesn't support the @code{'} flag on some platforms: NetBSD 3.0, mingw. @item +printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded +with zeroes) on some platforms: +MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw. +@item This function does not truncate the result as specified in C99 on some platforms: mingw. @item @@ -51,10 +55,6 @@ HP-UX 11, OSF/1 5.1. Portability problems not fixed by Gnulib: @itemize @item -printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded -with zeroes) on some platforms: -FreeBSD 6.0. -@item printf of @samp{long double} numbers is unsupported on some platforms: mingw. @end itemize diff --git a/doc/functions/vsprintf.texi b/doc/functions/vsprintf.texi index 6ec8e1bbc..8f0d8ec1c 100644 --- a/doc/functions/vsprintf.texi +++ b/doc/functions/vsprintf.texi @@ -26,15 +26,15 @@ NetBSD 3.0, mingw, BeOS. @item This function doesn't support the @code{'} flag on some platforms: NetBSD 3.0, mingw. +@item +printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded +with zeroes) on some platforms: +MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, mingw. @end itemize Portability problems not fixed by Gnulib: @itemize @item -printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded -with zeroes) on some platforms: -FreeBSD 6.0. -@item printf of @samp{long double} numbers is unsupported on some platforms: mingw. @end itemize diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 205200b65..45a219944 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -756,42 +756,65 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar else { arg_type type = a.arg[dp->arg_index].type; - CHAR_T *p; + int flags = dp->flags; +#if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO + int has_width; + size_t width; +#endif +#if NEED_PRINTF_FLAG_ZERO + int pad_ourselves; +#else +# define pad_ourselves 0 +#endif + CHAR_T *fbp; unsigned int prefix_count; int prefixes[2]; #if !USE_SNPRINTF size_t tmp_length; CHAR_T tmpbuf[700]; CHAR_T *tmp; +#endif + +#if !USE_SNPRINTF || NEED_PRINTF_FLAG_ZERO + 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 CHAR_T *digitp = dp->width_start; + + do + width = xsum (xtimes (width, 10), *digitp++ - '0'); + while (digitp != dp->width_end); + } + has_width = 1; + } +#endif +#if !USE_SNPRINTF /* Allocate a temporary buffer of sufficient size for calling sprintf. */ { - size_t width; size_t precision; - 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; - width = (arg < 0 ? (unsigned int) (-arg) : arg); - } - else - { - const CHAR_T *digitp = dp->width_start; - - do - width = xsum (xtimes (width, 10), *digitp++ - '0'); - while (digitp != dp->width_end); - } - } - precision = 6; if (dp->precision_start != dp->precision_end) { @@ -1008,39 +1031,56 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar } #endif + /* Decide whether to perform the padding ourselves. */ +#if NEED_PRINTF_FLAG_ZERO + switch (dp->conversion) + { + case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': + case 'a': case 'A': + pad_ourselves = 1; + break; + default: + pad_ourselves = 0; + break; + } +#endif + /* Construct the format string for calling snprintf or sprintf. */ - p = buf; - *p++ = '%'; + fbp = buf; + *fbp++ = '%'; #if NEED_PRINTF_FLAG_GROUPING /* The underlying implementation doesn't support the ' flag. Produce no grouping characters in this case; this is acceptable because the grouping is locale dependent. */ #else - if (dp->flags & FLAG_GROUP) - *p++ = '\''; + if (flags & FLAG_GROUP) + *fbp++ = '\''; #endif - if (dp->flags & FLAG_LEFT) - *p++ = '-'; - if (dp->flags & FLAG_SHOWSIGN) - *p++ = '+'; - if (dp->flags & FLAG_SPACE) - *p++ = ' '; - if (dp->flags & FLAG_ALT) - *p++ = '#'; - if (dp->flags & FLAG_ZERO) - *p++ = '0'; - if (dp->width_start != dp->width_end) + if (flags & FLAG_LEFT) + *fbp++ = '-'; + if (flags & FLAG_SHOWSIGN) + *fbp++ = '+'; + if (flags & FLAG_SPACE) + *fbp++ = ' '; + if (flags & FLAG_ALT) + *fbp++ = '#'; + if (!pad_ourselves) { - size_t n = dp->width_end - dp->width_start; - memcpy (p, dp->width_start, n * sizeof (CHAR_T)); - p += n; + if (flags & FLAG_ZERO) + *fbp++ = '0'; + if (dp->width_start != dp->width_end) + { + size_t n = dp->width_end - dp->width_start; + memcpy (fbp, dp->width_start, n * sizeof (CHAR_T)); + fbp += n; + } } if (dp->precision_start != dp->precision_end) { size_t n = dp->precision_end - dp->precision_start; - memcpy (p, dp->precision_start, n * sizeof (CHAR_T)); - p += n; + memcpy (fbp, dp->precision_start, n * sizeof (CHAR_T)); + fbp += n; } switch (type) @@ -1048,7 +1088,7 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar #if HAVE_LONG_LONG_INT case TYPE_LONGLONGINT: case TYPE_ULONGLONGINT: - *p++ = 'l'; + *fbp++ = 'l'; /*FALLTHROUGH*/ #endif case TYPE_LONGINT: @@ -1059,31 +1099,31 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar #if HAVE_WCHAR_T case TYPE_WIDE_STRING: #endif - *p++ = 'l'; + *fbp++ = 'l'; break; case TYPE_LONGDOUBLE: - *p++ = 'L'; + *fbp++ = 'L'; break; default: break; } #if NEED_PRINTF_DIRECTIVE_F if (dp->conversion == 'F') - *p = 'f'; + *fbp = 'f'; else #endif - *p = dp->conversion; + *fbp = dp->conversion; #if USE_SNPRINTF - p[1] = '%'; - p[2] = 'n'; - p[3] = '\0'; + fbp[1] = '%'; + fbp[2] = 'n'; + fbp[3] = '\0'; #else - p[1] = '\0'; + fbp[1] = '\0'; #endif /* Construct the arguments for calling snprintf or sprintf. */ prefix_count = 0; - if (dp->width_arg_index != ARG_NONE) + if (!pad_ourselves && dp->width_arg_index != ARG_NONE) { if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) abort (); @@ -1288,11 +1328,11 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { /* snprintf() doesn't understand the '%n' directive. */ - if (p[1] != '\0') + if (fbp[1] != '\0') { /* Don't use the '%n' directive; instead, look at the snprintf() return value. */ - p[1] = '\0'; + fbp[1] = '\0'; continue; } else @@ -1328,6 +1368,77 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar return NULL; } + /* Perform padding. */ +#if NEED_PRINTF_FLAG_ZERO + if (pad_ourselves && has_width && count < width) + { +# if USE_SNPRINTF + /* Make room for the result. */ + if (width >= maxlen) + { + /* Need at least width bytes. But allocate + proportionally, to avoid looping eternally if + snprintf() reports a too small count. */ + size_t n = + xmax (xsum (length, width), + xtimes (allocated, 2)); + + length += count; + ENSURE_ALLOCATION (n); + length -= count; + maxlen = allocated - length; /* >= width */ + } +# endif + { +# if USE_SNPRINTF + CHAR_T * const rp = result + length; +# else + CHAR_T * const rp = tmp; +# endif + CHAR_T *p = rp + count; + size_t pad = width - count; + CHAR_T *end = p + pad; + CHAR_T *pad_ptr = (*rp == '-' ? rp + 1 : rp); + /* No zero-padding of "inf" and "nan". */ + if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z') + || (*pad_ptr >= 'a' && *pad_ptr <= 'z')) + pad_ptr = NULL; + /* The generated string now extends from rp to p, + with the zero padding insertion point being at + pad_ptr. */ + + if (flags & FLAG_LEFT) + { + /* Pad with spaces on the right. */ + for (; pad > 0; pad--) + *p++ = ' '; + } + else if ((flags & FLAG_ZERO) && pad_ptr != NULL) + { + /* Pad with zeroes. */ + CHAR_T *q = end; + + while (p > pad_ptr) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = '0'; + } + else + { + /* Pad with spaces on the left. */ + CHAR_T *q = end; + + while (p > rp) + *--q = *--p; + for (; pad > 0; pad--) + *p++ = ' '; + } + + count = width; /* = count + pad = end - rp */ + } + } +#endif + #if !USE_SNPRINTF if (count >= tmp_length) /* tmp_length was incorrectly calculated - fix the diff --git a/m4/fprintf-posix.m4 b/m4/fprintf-posix.m4 index c63815805..064527bea 100644 --- a/m4/fprintf-posix.m4 +++ b/m4/fprintf-posix.m4 @@ -1,4 +1,4 @@ -# fprintf-posix.m4 serial 4 +# fprintf-posix.m4 serial 5 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, @@ -13,6 +13,7 @@ AC_DEFUN([gl_FUNC_FPRINTF_POSIX], AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) AC_REQUIRE([gl_PRINTF_POSITIONS]) AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) gl_cv_func_fprintf_posix=no case "$gl_cv_func_printf_sizes_c99" in *yes) @@ -26,8 +27,12 @@ AC_DEFUN([gl_FUNC_FPRINTF_POSIX], *yes) case "$gl_cv_func_printf_flag_grouping" in *yes) - # fprintf exists and is already POSIX compliant. - gl_cv_func_fprintf_posix=yes + case "$gl_cv_func_printf_flag_zero" in + *yes) + # fprintf exists and is already POSIX compliant. + gl_cv_func_fprintf_posix=yes + ;; + esac ;; esac ;; @@ -44,6 +49,7 @@ AC_DEFUN([gl_FUNC_FPRINTF_POSIX], gl_PREREQ_VASNPRINTF_DIRECTIVE_A gl_PREREQ_VASNPRINTF_DIRECTIVE_F gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_ZERO gl_REPLACE_VASNPRINTF gl_REPLACE_FPRINTF fi diff --git a/m4/printf.m4 b/m4/printf.m4 index e09c9d880..d1d6fe68a 100644 --- a/m4/printf.m4 +++ b/m4/printf.m4 @@ -1,4 +1,4 @@ -# printf.m4 serial 8 +# printf.m4 serial 9 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, @@ -318,6 +318,45 @@ changequote([,])dnl ]) ]) +dnl Test whether the *printf family of functions supports padding of non-finite +dnl values with the 0 flag correctly. (ISO C99 + TC1 + TC2.) See +dnl +dnl Result is gl_cv_func_printf_flag_zero. + +AC_DEFUN([gl_PRINTF_FLAG_ZERO], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether printf supports the zero flag correctly], + [gl_cv_func_printf_flag_zero], + [ + AC_TRY_RUN([ +#include +#include +static char buf[100]; +int main () +{ + if (sprintf (buf, "%010f", 1.0 / 0.0, 33, 44, 55) < 0 + || (strcmp (buf, " inf") != 0 + && strcmp (buf, " infinity") != 0)) + return 1; + return 0; +}], [gl_cv_func_printf_flag_zero=yes], [gl_cv_func_printf_flag_zero=no], + [ +changequote(,)dnl + case "$host_os" in + # Guess yes on glibc systems. + *-gnu*) gl_cv_func_printf_flag_zero="guessing yes";; + # Guess yes on BeOS. + beos*) gl_cv_func_printf_flag_zero="guessing yes";; + # If we don't know, assume the worst. + *) gl_cv_func_printf_flag_zero="guessing no";; + esac +changequote([,])dnl + ]) + ]) +]) + dnl Test whether the snprintf function exists. (ISO C99, POSIX:2001) dnl Result is ac_cv_func_snprintf. @@ -625,11 +664,12 @@ dnl 3 = gl_PRINTF_DIRECTIVE_F dnl 4 = gl_PRINTF_DIRECTIVE_N dnl 5 = gl_PRINTF_POSITIONS dnl 6 = gl_PRINTF_FLAG_GROUPING -dnl 7 = gl_SNPRINTF_PRESENCE -dnl 8 = gl_SNPRINTF_TRUNCATION_C99 -dnl 9 = gl_SNPRINTF_RETVAL_C99 -dnl 10 = gl_SNPRINTF_DIRECTIVE_N -dnl 11 = gl_VSNPRINTF_ZEROSIZE_C99 +dnl 7 = gl_PRINTF_FLAG_ZERO +dnl 8 = gl_SNPRINTF_PRESENCE +dnl 9 = gl_SNPRINTF_TRUNCATION_C99 +dnl 10 = gl_SNPRINTF_RETVAL_C99 +dnl 11 = gl_SNPRINTF_DIRECTIVE_N +dnl 12 = gl_VSNPRINTF_ZEROSIZE_C99 dnl dnl 1 = checking whether printf supports size specifiers as in C99... dnl 2 = checking whether printf supports the 'a' and 'A' directives... @@ -637,33 +677,34 @@ dnl 3 = checking whether printf supports the 'F' directive... dnl 4 = checking whether printf supports the 'n' directive... dnl 5 = checking whether printf supports POSIX/XSI format strings with positions... dnl 6 = checking whether printf supports the grouping flag... -dnl 7 = checking for snprintf... -dnl 8 = checking whether snprintf truncates the result as in C99... -dnl 9 = checking whether snprintf returns a byte count as in C99... -dnl 10 = checking whether snprintf fully supports the 'n' directive... -dnl 11 = checking whether vsnprintf respects a zero size as in C99... +dnl 7 = checking whether printf supports the zero flag correctly... +dnl 8 = checking for snprintf... +dnl 9 = checking whether snprintf truncates the result as in C99... +dnl 10 = checking whether snprintf returns a byte count as in C99... +dnl 11 = checking whether snprintf fully supports the 'n' directive... +dnl 12 = 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 -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 . # # . . ? . . . . ? -dnl Cygwin 2006 # # # . . ? . . . . ? -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 10.20, 11.00, 11.11, 11.23 # # # . . . . . # # # -dnl IRIX 6.5 # # # . . . . . # . . -dnl OSF/1 5.1 # # # . . . . . # . # -dnl OSF/1 4.0d # # # . . . # # # # # -dnl NetBSD 4.0 . ? ? . . ? . . . ? ? -dnl NetBSD 3.0 . # # . # # . . . . . -dnl BeOS # # # . # . . . . . . -dnl mingw # # # . # # . # # # . +dnl 1 2 3 4 5 6 7 8 9 10 11 12 +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 . # # . . ? ? . . . . ? +dnl Cygwin 2006 # # # . . ? ? . . . . ? +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 10.20, 11.00, 11.11, 11.23 # # # . . . # . . # # # +dnl IRIX 6.5 # # # . . . # . . # . . +dnl OSF/1 5.1 # # # . . . # . . # . # +dnl OSF/1 4.0d # # # . . . # # # # # # +dnl NetBSD 4.0 . ? ? . . ? ? . . . ? ? +dnl NetBSD 3.0 . # # . # # # . . . . . +dnl BeOS # # # . # . . . . . . . +dnl mingw # # # . # # # . # # # . diff --git a/m4/snprintf-posix.m4 b/m4/snprintf-posix.m4 index 6208adcd4..e32e4089a 100644 --- a/m4/snprintf-posix.m4 +++ b/m4/snprintf-posix.m4 @@ -1,4 +1,4 @@ -# snprintf-posix.m4 serial 5 +# snprintf-posix.m4 serial 6 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, @@ -13,6 +13,7 @@ AC_DEFUN([gl_FUNC_SNPRINTF_POSIX], AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) AC_REQUIRE([gl_PRINTF_POSITIONS]) AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) gl_cv_func_snprintf_posix=no AC_CHECK_FUNCS([snprintf]) if test $ac_cv_func_snprintf = yes; then @@ -32,17 +33,21 @@ AC_DEFUN([gl_FUNC_SNPRINTF_POSIX], *yes) case "$gl_cv_func_printf_flag_grouping" in *yes) - case "$gl_cv_func_snprintf_truncation_c99" in + case "$gl_cv_func_printf_flag_zero" in *yes) - case "$gl_cv_func_snprintf_retval_c99" in + case "$gl_cv_func_snprintf_truncation_c99" in *yes) - case "$gl_cv_func_snprintf_directive_n" in + case "$gl_cv_func_snprintf_retval_c99" in *yes) - case "$gl_cv_func_vsnprintf_zerosize_c99" in + case "$gl_cv_func_snprintf_directive_n" in *yes) - # snprintf exists and is already - # POSIX compliant. - gl_cv_func_snprintf_posix=yes + case "$gl_cv_func_vsnprintf_zerosize_c99" in + *yes) + # snprintf exists and is already + # POSIX compliant. + gl_cv_func_snprintf_posix=yes + ;; + esac ;; esac ;; @@ -68,6 +73,7 @@ AC_DEFUN([gl_FUNC_SNPRINTF_POSIX], gl_PREREQ_VASNPRINTF_DIRECTIVE_A gl_PREREQ_VASNPRINTF_DIRECTIVE_F gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_ZERO gl_REPLACE_VASNPRINTF gl_REPLACE_SNPRINTF fi diff --git a/m4/sprintf-posix.m4 b/m4/sprintf-posix.m4 index bb354d1ef..7aadf0767 100644 --- a/m4/sprintf-posix.m4 +++ b/m4/sprintf-posix.m4 @@ -1,4 +1,4 @@ -# sprintf-posix.m4 serial 4 +# sprintf-posix.m4 serial 5 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, @@ -13,6 +13,7 @@ AC_DEFUN([gl_FUNC_SPRINTF_POSIX], AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) AC_REQUIRE([gl_PRINTF_POSITIONS]) AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) gl_cv_func_sprintf_posix=no case "$gl_cv_func_printf_sizes_c99" in *yes) @@ -26,8 +27,12 @@ AC_DEFUN([gl_FUNC_SPRINTF_POSIX], *yes) case "$gl_cv_func_printf_flag_grouping" in *yes) - # sprintf exists and is already POSIX compliant. - gl_cv_func_sprintf_posix=yes + case "$gl_cv_func_printf_flag_zero" in + *yes) + # sprintf exists and is already POSIX compliant. + gl_cv_func_sprintf_posix=yes + ;; + esac ;; esac ;; @@ -44,6 +49,7 @@ AC_DEFUN([gl_FUNC_SPRINTF_POSIX], gl_PREREQ_VASNPRINTF_DIRECTIVE_A gl_PREREQ_VASNPRINTF_DIRECTIVE_F gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_ZERO gl_REPLACE_VASNPRINTF gl_REPLACE_SPRINTF fi diff --git a/m4/vasnprintf-posix.m4 b/m4/vasnprintf-posix.m4 index 34eee29c8..68634bf2f 100644 --- a/m4/vasnprintf-posix.m4 +++ b/m4/vasnprintf-posix.m4 @@ -1,4 +1,4 @@ -# vasnprintf-posix.m4 serial 5 +# vasnprintf-posix.m4 serial 6 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, @@ -13,6 +13,7 @@ AC_DEFUN([gl_FUNC_VASNPRINTF_POSIX], AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) AC_REQUIRE([gl_PRINTF_POSITIONS]) AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) gl_cv_func_vasnprintf_posix=no AC_CHECK_FUNCS_ONCE([vasnprintf]) case "$gl_cv_func_printf_sizes_c99" in @@ -27,10 +28,15 @@ AC_DEFUN([gl_FUNC_VASNPRINTF_POSIX], *yes) case "$gl_cv_func_printf_flag_grouping" in *yes) - if test $ac_cv_func_vasnprintf = yes; then - # vasnprintf exists and is already POSIX compliant. - gl_cv_func_vasnprintf_posix=yes - fi + case "$gl_cv_func_printf_flag_zero" in + *yes) + if test $ac_cv_func_vasnprintf = yes; then + # vasnprintf exists and is already POSIX + # compliant. + gl_cv_func_vasnprintf_posix=yes + fi + ;; + esac ;; esac ;; @@ -47,6 +53,7 @@ AC_DEFUN([gl_FUNC_VASNPRINTF_POSIX], gl_PREREQ_VASNPRINTF_DIRECTIVE_A gl_PREREQ_VASNPRINTF_DIRECTIVE_F gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_ZERO gl_REPLACE_VASNPRINTF fi ]) diff --git a/m4/vasnprintf.m4 b/m4/vasnprintf.m4 index 773c92f96..41a5ce180 100644 --- a/m4/vasnprintf.m4 +++ b/m4/vasnprintf.m4 @@ -1,4 +1,4 @@ -# vasnprintf.m4 serial 14 +# vasnprintf.m4 serial 15 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, @@ -105,6 +105,21 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_GROUPING], esac ]) +# Extra prerequisites of lib/vasnprintf.c for supporting the 0 flag. +AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_ZERO], +[ + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) + case "$gl_cv_func_printf_flag_zero" in + *yes) + ;; + *) + AC_DEFINE([NEED_PRINTF_FLAG_ZERO], 1, + [Define if the vasnprintf implementation needs special code for the + 0 flag.]) + ;; + esac +]) + # Prerequisites of lib/asnprintf.c. AC_DEFUN([gl_PREREQ_ASNPRINTF], [ diff --git a/m4/vasprintf-posix.m4 b/m4/vasprintf-posix.m4 index 43151632e..6cec101a1 100644 --- a/m4/vasprintf-posix.m4 +++ b/m4/vasprintf-posix.m4 @@ -1,4 +1,4 @@ -# vasprintf-posix.m4 serial 5 +# vasprintf-posix.m4 serial 6 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, @@ -13,6 +13,7 @@ AC_DEFUN([gl_FUNC_VASPRINTF_POSIX], AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) AC_REQUIRE([gl_PRINTF_POSITIONS]) AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) gl_cv_func_vasprintf_posix=no AC_CHECK_FUNCS([vasprintf]) case "$gl_cv_func_printf_sizes_c99" in @@ -27,10 +28,15 @@ AC_DEFUN([gl_FUNC_VASPRINTF_POSIX], *yes) case "$gl_cv_func_printf_flag_grouping" in *yes) - if test $ac_cv_func_vasprintf = yes; then - # vasprintf exists and is already POSIX compliant. - gl_cv_func_vasprintf_posix=yes - fi + case "$gl_cv_func_printf_flag_zero" in + *yes) + if test $ac_cv_func_vasprintf = yes; then + # vasprintf exists and is already POSIX + # compliant. + gl_cv_func_vasprintf_posix=yes + fi + ;; + esac ;; esac ;; @@ -47,6 +53,7 @@ AC_DEFUN([gl_FUNC_VASPRINTF_POSIX], gl_PREREQ_VASNPRINTF_DIRECTIVE_A gl_PREREQ_VASNPRINTF_DIRECTIVE_F gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_ZERO gl_REPLACE_VASNPRINTF gl_REPLACE_VASPRINTF fi diff --git a/m4/vfprintf-posix.m4 b/m4/vfprintf-posix.m4 index 669ae2008..60098a241 100644 --- a/m4/vfprintf-posix.m4 +++ b/m4/vfprintf-posix.m4 @@ -1,4 +1,4 @@ -# vfprintf-posix.m4 serial 4 +# vfprintf-posix.m4 serial 5 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, @@ -13,6 +13,7 @@ AC_DEFUN([gl_FUNC_VFPRINTF_POSIX], AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) AC_REQUIRE([gl_PRINTF_POSITIONS]) AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) gl_cv_func_vfprintf_posix=no case "$gl_cv_func_printf_sizes_c99" in *yes) @@ -26,8 +27,12 @@ AC_DEFUN([gl_FUNC_VFPRINTF_POSIX], *yes) case "$gl_cv_func_printf_flag_grouping" in *yes) - # vfprintf exists and is already POSIX compliant. - gl_cv_func_vfprintf_posix=yes + case "$gl_cv_func_printf_flag_zero" in + *yes) + # vfprintf exists and is already POSIX compliant. + gl_cv_func_vfprintf_posix=yes + ;; + esac ;; esac ;; @@ -44,6 +49,7 @@ AC_DEFUN([gl_FUNC_VFPRINTF_POSIX], gl_PREREQ_VASNPRINTF_DIRECTIVE_A gl_PREREQ_VASNPRINTF_DIRECTIVE_F gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_ZERO gl_REPLACE_VASNPRINTF gl_REPLACE_VFPRINTF fi diff --git a/m4/vsnprintf-posix.m4 b/m4/vsnprintf-posix.m4 index 941cf515b..29af67f13 100644 --- a/m4/vsnprintf-posix.m4 +++ b/m4/vsnprintf-posix.m4 @@ -1,4 +1,4 @@ -# vsnprintf-posix.m4 serial 5 +# vsnprintf-posix.m4 serial 6 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, @@ -13,6 +13,7 @@ AC_DEFUN([gl_FUNC_VSNPRINTF_POSIX], AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) AC_REQUIRE([gl_PRINTF_POSITIONS]) AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) gl_cv_func_vsnprintf_posix=no AC_CHECK_FUNCS([vsnprintf]) if test $ac_cv_func_vsnprintf = yes; then @@ -33,17 +34,21 @@ AC_DEFUN([gl_FUNC_VSNPRINTF_POSIX], *yes) case "$gl_cv_func_printf_flag_grouping" in *yes) - case "$gl_cv_func_snprintf_truncation_c99" in + case "$gl_cv_func_printf_flag_zero" in *yes) - case "$gl_cv_func_snprintf_retval_c99" in + case "$gl_cv_func_snprintf_truncation_c99" in *yes) - case "$gl_cv_func_snprintf_directive_n" in + case "$gl_cv_func_snprintf_retval_c99" in *yes) - case "$gl_cv_func_vsnprintf_zerosize_c99" in + case "$gl_cv_func_snprintf_directive_n" in *yes) - # vsnprintf exists and is already - # POSIX compliant. - gl_cv_func_vsnprintf_posix=yes + case "$gl_cv_func_vsnprintf_zerosize_c99" in + *yes) + # vsnprintf exists and is + # already POSIX compliant. + gl_cv_func_vsnprintf_posix=yes + ;; + esac ;; esac ;; @@ -69,6 +74,7 @@ AC_DEFUN([gl_FUNC_VSNPRINTF_POSIX], gl_PREREQ_VASNPRINTF_DIRECTIVE_A gl_PREREQ_VASNPRINTF_DIRECTIVE_F gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_ZERO gl_REPLACE_VASNPRINTF gl_REPLACE_VSNPRINTF fi diff --git a/m4/vsprintf-posix.m4 b/m4/vsprintf-posix.m4 index 626da1eef..9507d8180 100644 --- a/m4/vsprintf-posix.m4 +++ b/m4/vsprintf-posix.m4 @@ -1,4 +1,4 @@ -# vsprintf-posix.m4 serial 4 +# vsprintf-posix.m4 serial 5 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, @@ -13,6 +13,7 @@ AC_DEFUN([gl_FUNC_VSPRINTF_POSIX], AC_REQUIRE([gl_PRINTF_DIRECTIVE_N]) AC_REQUIRE([gl_PRINTF_POSITIONS]) AC_REQUIRE([gl_PRINTF_FLAG_GROUPING]) + AC_REQUIRE([gl_PRINTF_FLAG_ZERO]) gl_cv_func_vsprintf_posix=no case "$gl_cv_func_printf_sizes_c99" in *yes) @@ -26,8 +27,12 @@ AC_DEFUN([gl_FUNC_VSPRINTF_POSIX], *yes) case "$gl_cv_func_printf_flag_grouping" in *yes) - # vsprintf exists and is already POSIX compliant. - gl_cv_func_vsprintf_posix=yes + case "$gl_cv_func_printf_flag_zero" in + *yes) + # vsprintf exists and is already POSIX compliant. + gl_cv_func_vsprintf_posix=yes + ;; + esac ;; esac ;; @@ -44,6 +49,7 @@ AC_DEFUN([gl_FUNC_VSPRINTF_POSIX], gl_PREREQ_VASNPRINTF_DIRECTIVE_A gl_PREREQ_VASNPRINTF_DIRECTIVE_F gl_PREREQ_VASNPRINTF_FLAG_GROUPING + gl_PREREQ_VASNPRINTF_FLAG_ZERO gl_REPLACE_VASNPRINTF gl_REPLACE_VSPRINTF fi diff --git a/tests/test-snprintf-posix.h b/tests/test-snprintf-posix.h index 7b1370b88..8803edf9d 100644 --- a/tests/test-snprintf-posix.h +++ b/tests/test-snprintf-posix.h @@ -683,7 +683,61 @@ test_function (int (*my_snprintf) (char *, size_t, const char *, ...)) ASSERT (retval == strlen (result)); } - { /* FLAG_ZERO. */ + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%10f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-10f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ char result[100]; int retval = my_snprintf (result, sizeof (result), "%015f %d", 1234.0, 33, 44, 55); @@ -700,6 +754,14 @@ test_function (int (*my_snprintf) (char *, size_t, const char *, ...)) ASSERT (retval == strlen (result)); } + { /* FLAG_ZERO with NaN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015f %d", NaN (), 33, 44, 55); + ASSERT (strcmp (result, " nan 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Precision. */ char result[100]; int retval = @@ -775,7 +837,61 @@ test_function (int (*my_snprintf) (char *, size_t, const char *, ...)) ASSERT (retval == strlen (result)); } - { /* FLAG_ZERO. */ + { /* Width. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%10Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%-10Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%+Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "% Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%#.Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ char result[100]; int retval = my_snprintf (result, sizeof (result), "%015Lf %d", 1234.0L, 33, 44, 55); @@ -792,6 +908,15 @@ test_function (int (*my_snprintf) (char *, size_t, const char *, ...)) ASSERT (retval == strlen (result)); } + { /* FLAG_ZERO with NaN. */ + static long double zero = 0.0L; + char result[100]; + int retval = + my_snprintf (result, sizeof (result), "%015Lf %d", zero / zero, 33, 44, 55); + ASSERT (strcmp (result, " nan 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Precision. */ char result[100]; int retval = diff --git a/tests/test-sprintf-posix.h b/tests/test-sprintf-posix.h index f6d70e617..2de6d0f2f 100644 --- a/tests/test-sprintf-posix.h +++ b/tests/test-sprintf-posix.h @@ -669,7 +669,55 @@ test_function (int (*my_sprintf) (char *, const char *, ...)) ASSERT (retval == strlen (result)); } - { /* FLAG_ZERO. */ + { /* Width. */ + char result[1000]; + int retval = + my_sprintf (result, "%10f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[1000]; + int retval = + my_sprintf (result, "%-10f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[1000]; + int retval = + my_sprintf (result, "%+f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[1000]; + int retval = + my_sprintf (result, "% f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[1000]; + int retval = + my_sprintf (result, "%#f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[1000]; + int retval = + my_sprintf (result, "%#.f %d", 1.75, 33, 44, 55); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ char result[1000]; int retval = my_sprintf (result, "%015f %d", 1234.0, 33, 44, 55); @@ -686,6 +734,14 @@ test_function (int (*my_sprintf) (char *, const char *, ...)) ASSERT (retval == strlen (result)); } + { /* FLAG_ZERO with NaN. */ + char result[1000]; + int retval = + my_sprintf (result, "%015f %d", NaN (), 33, 44, 55); + ASSERT (strcmp (result, " nan 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Precision. */ char result[1000]; int retval = @@ -761,7 +817,55 @@ test_function (int (*my_sprintf) (char *, const char *, ...)) ASSERT (retval == strlen (result)); } - { /* FLAG_ZERO. */ + { /* Width. */ + char result[1000]; + int retval = + my_sprintf (result, "%10Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + char result[1000]; + int retval = + my_sprintf (result, "%-10Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SHOWSIGN. */ + char result[1000]; + int retval = + my_sprintf (result, "%+Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_SPACE. */ + char result[1000]; + int retval = + my_sprintf (result, "% Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[1000]; + int retval = + my_sprintf (result, "%#Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT. */ + char result[1000]; + int retval = + my_sprintf (result, "%#.Lf %d", 1.75L, 33, 44, 55); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ZERO with finite number. */ char result[1000]; int retval = my_sprintf (result, "%015Lf %d", 1234.0L, 33, 44, 55); @@ -778,6 +882,15 @@ test_function (int (*my_sprintf) (char *, const char *, ...)) ASSERT (retval == strlen (result)); } + { /* FLAG_ZERO with NaN. */ + static long double zero = 0.0L; + char result[1000]; + int retval = + my_sprintf (result, "%015Lf %d", zero / zero, 33, 44, 55); + ASSERT (strcmp (result, " nan 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* Precision. */ char result[1000]; int retval = diff --git a/tests/test-vasnprintf-posix.c b/tests/test-vasnprintf-posix.c index 4162d3b53..a058fc97d 100644 --- a/tests/test-vasnprintf-posix.c +++ b/tests/test-vasnprintf-posix.c @@ -837,7 +837,67 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } - { /* FLAG_ZERO. */ + { /* Width. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%10f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_LEFT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%-10f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_SHOWSIGN. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%+f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_SPACE. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "% f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#.f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ZERO with finite number. */ size_t length; char *result = my_asnprintf (NULL, &length, "%015f %d", 1234.0, 33, 44, 55); @@ -858,6 +918,16 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } + { /* FLAG_ZERO with NaN. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%015f %d", NaN (), 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " nan 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* Precision. */ size_t length; char *result = @@ -951,7 +1021,67 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } - { /* FLAG_ZERO. */ + { /* Width. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%10Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_LEFT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%-10Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_SHOWSIGN. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%+Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_SPACE. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "% Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#.Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ZERO with finite number. */ size_t length; char *result = my_asnprintf (NULL, &length, "%015Lf %d", 1234.0L, 33, 44, 55); @@ -972,6 +1102,17 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } + { /* FLAG_ZERO with NaN. */ + static long double zero = 0.0L; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%015Lf %d", zero / zero, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " nan 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* Precision. */ size_t length; char *result = diff --git a/tests/test-vasprintf-posix.c b/tests/test-vasprintf-posix.c index e26b8a5d0..ca9dbabca 100644 --- a/tests/test-vasprintf-posix.c +++ b/tests/test-vasprintf-posix.c @@ -818,7 +818,67 @@ test_function (int (*my_asprintf) (char **, const char *, ...)) free (result); } - { /* FLAG_ZERO. */ + { /* Width. */ + char *result; + int retval = + my_asprintf (&result, "%10f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_LEFT. */ + char *result; + int retval = + my_asprintf (&result, "%-10f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_SHOWSIGN. */ + char *result; + int retval = + my_asprintf (&result, "%+f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_SPACE. */ + char *result; + int retval = + my_asprintf (&result, "% f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT. */ + char *result; + int retval = + my_asprintf (&result, "%#f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT. */ + char *result; + int retval = + my_asprintf (&result, "%#.f %d", 1.75, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ZERO with finite number. */ char *result; int retval = my_asprintf (&result, "%015f %d", 1234.0, 33, 44, 55); @@ -839,6 +899,16 @@ test_function (int (*my_asprintf) (char **, const char *, ...)) free (result); } + { /* FLAG_ZERO with NaN. */ + char *result; + int retval = + my_asprintf (&result, "%015f %d", NaN (), 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " nan 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + { /* Precision. */ char *result; int retval = @@ -932,7 +1002,67 @@ test_function (int (*my_asprintf) (char **, const char *, ...)) free (result); } - { /* FLAG_ZERO. */ + { /* Width. */ + char *result; + int retval = + my_asprintf (&result, "%10Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_LEFT. */ + char *result; + int retval = + my_asprintf (&result, "%-10Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_SHOWSIGN. */ + char *result; + int retval = + my_asprintf (&result, "%+Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "+1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_SPACE. */ + char *result; + int retval = + my_asprintf (&result, "% Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT. */ + char *result; + int retval = + my_asprintf (&result, "%#Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT. */ + char *result; + int retval = + my_asprintf (&result, "%#.Lf %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "2. 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ZERO with finite number. */ char *result; int retval = my_asprintf (&result, "%015Lf %d", 1234.0L, 33, 44, 55); @@ -953,6 +1083,17 @@ test_function (int (*my_asprintf) (char **, const char *, ...)) free (result); } + { /* FLAG_ZERO with NaN. */ + static long double zero = 0.0L; + char *result; + int retval = + my_asprintf (&result, "%015Lf %d", zero / zero, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " nan 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + { /* Precision. */ char *result; int retval = -- 2.11.0