+2023-05-03 Bruno Haible <bruno@clisp.org>
+
+ vasnprintf, vasnwprintf: Make '0' flag handling more ISO C compliant.
+ * lib/vasnprintf.c (VASNPRINTF): When doing the padding ourselves,
+ ignore the '0' flag if a precision is specified and the conversion is
+ one of d, i, o, u, x, X, b, B.
+ * tests/test-vasnprintf-posix.c (test_function): Update expected results
+ accordingly.
+ * tests/test-vasprintf-posix.c (test_function): Likewise.
+ * tests/test-snprintf-posix.h (test_function): Likewise.
+ * tests/test-sprintf-posix.h (test_function): Likewise.
+ * tests/test-vasnwprintf-posix.c (test_function): Likewise.
+
2023-05-02 Paul Eggert <eggert@cs.ucla.edu>
mktime: include <intprops.h>
#if !USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
size_t width;
#endif
-#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
int has_precision;
size_t precision;
#endif
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
-#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+# if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
has_width = 1;
-#endif
+# endif
}
#endif
-#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
has_precision = 0;
precision = 6;
if (dp->precision_start != dp->precision_end)
for (; pad > 0; pad--)
*p++ = ' ';
}
- else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+ else if ((flags & FLAG_ZERO) && pad_ptr != NULL
+ /* ISO C says: "For d, i, o, u, x, and X
+ conversions, if a precision is
+ specified, the 0 flag is ignored. */
+ && !(has_precision
+ && (dp->conversion == 'd'
+ || dp->conversion == 'i'
+ || dp->conversion == 'o'
+ || dp->conversion == 'u'
+ || dp->conversion == 'x'
+ || dp->conversion == 'X'
+ /* Although ISO C does not
+ require it, treat 'b' and 'B'
+ like 'x' and 'X'. */
+ || dp->conversion == 'b'
+ || dp->conversion == 'B')))
{
/* Pad with zeroes. */
DCHAR_T *q = end;
{ /* Padding and precision. */
int retval =
my_snprintf (result, sizeof (result), "%015.10x %d", 12348, 33, 44, 55);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #ifdef __MINGW32__
- ASSERT (strcmp (result, "00000000000303c 33") == 0 /* mingw 5 */
- || strcmp (result, " 000000303c 33") == 0 /* mingw 10 */);
- #else
+ /* ISO C 99 § 7.19.6.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (strcmp (result, " 000000303c 33") == 0);
- #endif
ASSERT (retval == strlen (result));
}
{ /* FLAG_ALT with a positive number and padding and precision. */
int retval =
my_snprintf (result, sizeof (result), "%0#15.10x %d", 12348, 33, 44, 55);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #ifdef __MINGW32__
- ASSERT (strcmp (result, "0x000000000303c 33") == 0 /* mingw 5 */
- || strcmp (result, " 0x000000303c 33") == 0 /* mingw 10 */);
- #else
+ /* ISO C 99 § 7.19.6.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (strcmp (result, " 0x000000303c 33") == 0);
- #endif
ASSERT (retval == strlen (result));
}
{ /* Padding and precision. */
int retval =
my_sprintf (result, "%015.10x %d", 12348, 33, 44, 55);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #ifdef __MINGW32__
- ASSERT (strcmp (result, "00000000000303c 33") == 0 /* mingw 5 */
- || strcmp (result, " 000000303c 33") == 0 /* mingw 10 */);
- #else
+ /* ISO C 99 § 7.19.6.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (strcmp (result, " 000000303c 33") == 0);
- #endif
ASSERT (retval == strlen (result));
}
{ /* FLAG_ALT with a positive number and padding and precision. */
int retval =
my_sprintf (result, "%0#15.10x %d", 12348, 33, 44, 55);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #ifdef __MINGW32__
- ASSERT (strcmp (result, "0x000000000303c 33") == 0 /* mingw 5 */
- || strcmp (result, " 0x000000303c 33") == 0 /* mingw 10 */);
- #else
+ /* ISO C 99 § 7.19.6.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (strcmp (result, " 0x000000303c 33") == 0);
- #endif
ASSERT (retval == strlen (result));
}
char *result =
my_asnprintf (NULL, &length, "%015.10x %d", 12348, 33, 44, 55);
ASSERT (result != NULL);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #ifdef __MINGW32__
- ASSERT (strcmp (result, "00000000000303c 33") == 0 /* mingw 5 */
- || strcmp (result, " 000000303c 33") == 0 /* mingw 10 */);
- #else
+ /* ISO C 99 § 7.19.6.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (strcmp (result, " 000000303c 33") == 0);
- #endif
ASSERT (length == strlen (result));
free (result);
}
char *result =
my_asnprintf (NULL, &length, "%0#15.10x %d", 12348, 33, 44, 55);
ASSERT (result != NULL);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #ifdef __MINGW32__
- ASSERT (strcmp (result, "0x000000000303c 33") == 0 /* mingw 5 */
- || strcmp (result, " 0x000000303c 33") == 0 /* mingw 10 */);
- #else
+ /* ISO C 99 § 7.19.6.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (strcmp (result, " 0x000000303c 33") == 0);
- #endif
ASSERT (length == strlen (result));
free (result);
}
wchar_t *result =
my_asnwprintf (NULL, &length, L"%015.10x %d", 12348, 33, 44, 55);
ASSERT (result != NULL);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #if MUSL_LIBC
- ASSERT (wcscmp (result, L"00000000000303c 33") == 0);
- #else
+ /* ISO C 99 § 7.24.2.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (wcscmp (result, L" 000000303c 33") == 0);
- #endif
ASSERT (length == wcslen (result));
free (result);
}
wchar_t *result =
my_asnwprintf (NULL, &length, L"%0#15.10x %d", 12348, 33, 44, 55);
ASSERT (result != NULL);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #if MUSL_LIBC
- ASSERT (wcscmp (result, L"0x000000000303c 33") == 0);
- #else
+ /* ISO C 99 § 7.24.2.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (wcscmp (result, L" 0x000000303c 33") == 0);
- #endif
ASSERT (length == wcslen (result));
free (result);
}
int retval =
my_asprintf (&result, "%015.10x %d", 12348, 33, 44, 55);
ASSERT (result != NULL);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #ifdef __MINGW32__
- ASSERT (strcmp (result, "00000000000303c 33") == 0 /* mingw 5 */
- || strcmp (result, " 000000303c 33") == 0 /* mingw 10 */);
- #else
+ /* ISO C 99 § 7.19.6.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (strcmp (result, " 000000303c 33") == 0);
- #endif
ASSERT (retval == strlen (result));
free (result);
}
int retval =
my_asprintf (&result, "%0#15.10x %d", 12348, 33, 44, 55);
ASSERT (result != NULL);
- /* Neither ISO C nor POSIX specify that the '0' flag is ignored when a width
- and a precision are both present. But most implementations do so. */
- #ifdef __MINGW32__
- ASSERT (strcmp (result, "0x000000000303c 33") == 0 /* mingw 5 */
- || strcmp (result, " 0x000000303c 33") == 0 /* mingw 10 */);
- #else
+ /* ISO C 99 § 7.19.6.1.(6) says: "For d, i, o, u, x, and X conversions, if a
+ precision is specified, the 0 flag is ignored." */
ASSERT (strcmp (result, " 0x000000303c 33") == 0);
- #endif
ASSERT (retval == strlen (result));
free (result);
}