Some details of the %b implementation that I added on 2023-03-17 were incorrect. This patch fixes them, while adding new unit tests.
2023-03-22 Bruno Haible <br...@clisp.org> *printf-posix: Fix implementation of %b directive. * lib/vasnprintf.c (VASNPRINTF): In the %b directive implementation, fix the precision handling, and ignore the '0' flag when a width and a precision are both present. * tests/test-snprintf-posix.h (test_function): Add test cases for the %x directive and more test cases for the %b directive. * tests/test-sprintf-posix.h (test_function): Likewise. * tests/test-vasnprintf-posix.c (test_function): Likewise. * tests/test-vasnwprintf-posix.c (test_function): Likewise. * tests/test-vasprintf-posix.c (test_function): Likewise. * modules/vasnwprintf-posix-tests (Files): Add m4/musl.m4. (configure.ac): Invoke gl_MUSL_LIBC. diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 5cd52b5b6e..248444ca23 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -3217,6 +3217,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { arg_type type = a.arg[dp->arg_index].type; int flags = dp->flags; + int has_width; size_t width; int has_precision; size_t precision; @@ -3229,6 +3230,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, DCHAR_T *pad_ptr; DCHAR_T *p; + has_width = 0; width = 0; if (dp->width_start != dp->width_end) { @@ -3256,10 +3258,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, width = xsum (xtimes (width, 10), *digitp++ - '0'); while (digitp != dp->width_end); } + has_width = 1; } has_precision = 0; - precision = 0; + precision = 1; if (dp->precision_start != dp->precision_end) { if (dp->precision_arg_index != ARG_NONE) @@ -3333,12 +3336,24 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, int need_prefix = ((flags & FLAG_ALT) && arg != 0); p = tmp_end; - do + /* "The result of converting a zero value with a precision + of zero is no characters." */ + if (!(has_precision && precision == 0 && arg == 0)) + { + do + { + *--p = '0' + (arg & 1); + arg = arg >> 1; + } + while (arg != 0); + } + + if (has_precision) { - *--p = '0' + (arg & 1); - arg = arg >> 1; + DCHAR_T *digits_start = tmp_end - precision; + while (p > digits_start) + *--p = '0'; } - while (arg != 0); pad_ptr = p; @@ -3365,7 +3380,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, for (p = tmp_end - pad; p < tmp_end; p++) *p = ' '; } - else if (flags & FLAG_ZERO) + else if ((flags & FLAG_ZERO) + /* 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. */ + && !(has_width && has_precision)) { /* Pad with zeroes. */ for (p = tmp_start; p < pad_ptr; p++) diff --git a/modules/vasnwprintf-posix-tests b/modules/vasnwprintf-posix-tests index 667eb61103..6354e79f75 100644 --- a/modules/vasnwprintf-posix-tests +++ b/modules/vasnwprintf-posix-tests @@ -7,6 +7,7 @@ tests/minus-zero.h tests/infinity.h tests/nan.h tests/macros.h +m4/musl.m4 m4/locale-fr.m4 m4/codeset.m4 @@ -21,6 +22,7 @@ wmemcpy configure.ac: AC_REQUIRE([gl_LONG_DOUBLE_VS_DOUBLE]) +gl_MUSL_LIBC gt_LOCALE_FR gt_LOCALE_FR_UTF8 diff --git a/tests/test-snprintf-posix.h b/tests/test-snprintf-posix.h index 05c7be8059..a8993f947a 100644 --- a/tests/test-snprintf-posix.h +++ b/tests/test-snprintf-posix.h @@ -3091,6 +3091,190 @@ test_function (int (*my_snprintf) (char *, size_t, const char *, ...)) } #endif + /* Test the support of the 'x' conversion specifier for hexadecimal output of + integers. */ + + { /* Zero. */ + int retval = + my_snprintf (result, sizeof (result), "%x %d", 0, 33, 44, 55); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A positive number. */ + int retval = + my_snprintf (result, sizeof (result), "%x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A large positive number. */ + int retval = + my_snprintf (result, sizeof (result), "%x %d", 0xFFFFFFFEU, 33, 44, 55); + ASSERT (strcmp (result, "fffffffe 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width. */ + int retval = + my_snprintf (result, sizeof (result), "%10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, " 303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width given as argument. */ + int retval = + my_snprintf (result, sizeof (result), "%*x %d", 10, 12348, 33, 44, 55); + ASSERT (strcmp (result, " 303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative width given as argument (cf. FLAG_LEFT below). */ + int retval = + my_snprintf (result, sizeof (result), "%*x %d", -10, 12348, 33, 44, 55); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + int retval = + my_snprintf (result, sizeof (result), "%.10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "000000303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Zero precision and a positive number. */ + int retval = + my_snprintf (result, sizeof (result), "%.0x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Zero precision and a zero number. */ + int retval = + my_snprintf (result, sizeof (result), "%.0x %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width and precision. */ + int retval = + my_snprintf (result, sizeof (result), "%15.10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, " 000000303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* 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); + #else + ASSERT (strcmp (result, " 000000303c 33") == 0); + #endif + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + int retval = + my_snprintf (result, sizeof (result), "%-10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with zero. */ + int retval = + my_snprintf (result, sizeof (result), "%#x %d", 0, 33, 44, 55); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number. */ + int retval = + my_snprintf (result, sizeof (result), "%#x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "0x303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and width. */ + int retval = + my_snprintf (result, sizeof (result), "%#10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, " 0x303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and padding. */ + int retval = + my_snprintf (result, sizeof (result), "%0#10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "0x0000303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and precision. */ + int retval = + my_snprintf (result, sizeof (result), "%0#.10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "0x000000303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + int retval = + my_snprintf (result, sizeof (result), "%#15.10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, " 0x000000303c 33") == 0); + 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); + #else + ASSERT (strcmp (result, " 0x000000303c 33") == 0); + #endif + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + int retval = + my_snprintf (result, sizeof (result), "%#.0x %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Uppercase 'X'. */ + int retval = + my_snprintf (result, sizeof (result), "%X %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "303C 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Uppercase 'X' with FLAG_ALT. */ + int retval = + my_snprintf (result, sizeof (result), "%#X %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "0X303C 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Uppercase 'X' with FLAG_ALT and zero precision and a zero number. */ + int retval = + my_snprintf (result, sizeof (result), "%#.0X %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } + /* Test the support of the 'b' conversion specifier for binary output of integers. */ @@ -3136,6 +3320,45 @@ test_function (int (*my_snprintf) (char *, size_t, const char *, ...)) ASSERT (retval == strlen (result)); } + { /* Precision. */ + int retval = + my_snprintf (result, sizeof (result), "%.20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, "00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Zero precision and a positive number. */ + int retval = + my_snprintf (result, sizeof (result), "%.0b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, "11000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Zero precision and a zero number. */ + int retval = + my_snprintf (result, sizeof (result), "%.0b %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width and precision. */ + int retval = + my_snprintf (result, sizeof (result), "%25.20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, " 00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Padding and precision. */ + int retval = + my_snprintf (result, sizeof (result), "%025.20b %d", 12345, 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 implementations do so. */ + ASSERT (strcmp (result, " 00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* FLAG_LEFT. */ int retval = my_snprintf (result, sizeof (result), "%-20b %d", 12345, 33, 44, 55); @@ -3156,4 +3379,51 @@ test_function (int (*my_snprintf) (char *, size_t, const char *, ...)) ASSERT (strcmp (result, "0b11000000111001 33") == 0); ASSERT (retval == strlen (result)); } + + { /* FLAG_ALT with a positive number and width. */ + int retval = + my_snprintf (result, sizeof (result), "%#20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, " 0b11000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and padding. */ + int retval = + my_snprintf (result, sizeof (result), "%0#20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, "0b000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and precision. */ + int retval = + my_snprintf (result, sizeof (result), "%0#.20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, "0b00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + int retval = + my_snprintf (result, sizeof (result), "%#25.20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, " 0b00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and padding and precision. */ + int retval = + my_snprintf (result, sizeof (result), "%0#25.20b %d", 12345, 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 implementations do so. */ + ASSERT (strcmp (result, " 0b00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + int retval = + my_snprintf (result, sizeof (result), "%#.0b %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } } diff --git a/tests/test-sprintf-posix.h b/tests/test-sprintf-posix.h index d745a1109b..7f280d3c32 100644 --- a/tests/test-sprintf-posix.h +++ b/tests/test-sprintf-posix.h @@ -3069,6 +3069,190 @@ test_function (int (*my_sprintf) (char *, const char *, ...)) } #endif + /* Test the support of the 'x' conversion specifier for hexadecimal output of + integers. */ + + { /* Zero. */ + int retval = + my_sprintf (result, "%x %d", 0, 33, 44, 55); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A positive number. */ + int retval = + my_sprintf (result, "%x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* A large positive number. */ + int retval = + my_sprintf (result, "%x %d", 0xFFFFFFFEU, 33, 44, 55); + ASSERT (strcmp (result, "fffffffe 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width. */ + int retval = + my_sprintf (result, "%10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, " 303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width given as argument. */ + int retval = + my_sprintf (result, "%*x %d", 10, 12348, 33, 44, 55); + ASSERT (strcmp (result, " 303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Negative width given as argument (cf. FLAG_LEFT below). */ + int retval = + my_sprintf (result, "%*x %d", -10, 12348, 33, 44, 55); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Precision. */ + int retval = + my_sprintf (result, "%.10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "000000303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Zero precision and a positive number. */ + int retval = + my_sprintf (result, "%.0x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Zero precision and a zero number. */ + int retval = + my_sprintf (result, "%.0x %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width and precision. */ + int retval = + my_sprintf (result, "%15.10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, " 000000303c 33") == 0); + 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); + #else + ASSERT (strcmp (result, " 000000303c 33") == 0); + #endif + ASSERT (retval == strlen (result)); + } + + { /* FLAG_LEFT. */ + int retval = + my_sprintf (result, "%-10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with zero. */ + int retval = + my_sprintf (result, "%#x %d", 0, 33, 44, 55); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number. */ + int retval = + my_sprintf (result, "%#x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "0x303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and width. */ + int retval = + my_sprintf (result, "%#10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, " 0x303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and padding. */ + int retval = + my_sprintf (result, "%0#10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "0x0000303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and precision. */ + int retval = + my_sprintf (result, "%0#.10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "0x000000303c 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + int retval = + my_sprintf (result, "%#15.10x %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, " 0x000000303c 33") == 0); + 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); + #else + ASSERT (strcmp (result, " 0x000000303c 33") == 0); + #endif + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + int retval = + my_sprintf (result, "%#.0x %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Uppercase 'X'. */ + int retval = + my_sprintf (result, "%X %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "303C 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Uppercase 'X' with FLAG_ALT. */ + int retval = + my_sprintf (result, "%#X %d", 12348, 33, 44, 55); + ASSERT (strcmp (result, "0X303C 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Uppercase 'X' with FLAG_ALT and zero precision and a zero number. */ + int retval = + my_sprintf (result, "%#.0X %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } + /* Test the support of the 'b' conversion specifier for binary output of integers. */ @@ -3114,6 +3298,45 @@ test_function (int (*my_sprintf) (char *, const char *, ...)) ASSERT (retval == strlen (result)); } + { /* Precision. */ + int retval = + my_sprintf (result, "%.20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, "00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Zero precision and a positive number. */ + int retval = + my_sprintf (result, "%.0b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, "11000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Zero precision and a zero number. */ + int retval = + my_sprintf (result, "%.0b %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Width and precision. */ + int retval = + my_sprintf (result, "%25.20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, " 00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* Padding and precision. */ + int retval = + my_sprintf (result, "%025.20b %d", 12345, 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 implementations do so. */ + ASSERT (strcmp (result, " 00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + { /* FLAG_LEFT. */ int retval = my_sprintf (result, "%-20b %d", 12345, 33, 44, 55); @@ -3134,4 +3357,51 @@ test_function (int (*my_sprintf) (char *, const char *, ...)) ASSERT (strcmp (result, "0b11000000111001 33") == 0); ASSERT (retval == strlen (result)); } + + { /* FLAG_ALT with a positive number and width. */ + int retval = + my_sprintf (result, "%#20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, " 0b11000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and padding. */ + int retval = + my_sprintf (result, "%0#20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, "0b000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and precision. */ + int retval = + my_sprintf (result, "%0#.20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, "0b00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + int retval = + my_sprintf (result, "%#25.20b %d", 12345, 33, 44, 55); + ASSERT (strcmp (result, " 0b00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a positive number and padding and precision. */ + int retval = + my_sprintf (result, "%0#25.20b %d", 12345, 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 implementations do so. */ + ASSERT (strcmp (result, " 0b00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + int retval = + my_sprintf (result, "%#.0b %d", 0, 33, 44, 55); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + } } diff --git a/tests/test-vasnprintf-posix.c b/tests/test-vasnprintf-posix.c index ecbb8bcda0..87f4fc290b 100644 --- a/tests/test-vasnprintf-posix.c +++ b/tests/test-vasnprintf-posix.c @@ -4017,6 +4017,259 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) } #endif + /* Test the support of the 'x' conversion specifier for hexadecimal output of + integers. */ + + { /* Zero. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* A positive number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* A large positive number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%x %d", 0xFFFFFFFEU, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "fffffffe 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Width. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Width given as argument. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%*x %d", 10, 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Negative width given as argument (cf. FLAG_LEFT below). */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%*x %d", -10, 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "000000303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Zero precision and a positive number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.0x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Zero precision and a zero number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.0x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Width and precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%15.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 000000303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Padding and precision. */ + size_t length; + 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); + #else + ASSERT (strcmp (result, " 000000303c 33") == 0); + #endif + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_LEFT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%-10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with zero. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0x303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and width. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 0x303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%0#10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0x0000303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%0#.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0x000000303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#15.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 0x000000303c 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding and precision. */ + size_t length; + 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); + #else + ASSERT (strcmp (result, " 0x000000303c 33") == 0); + #endif + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#.0x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Uppercase 'X'. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%X %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303C 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Uppercase 'X' with FLAG_ALT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#X %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0X303C 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Uppercase 'X' with FLAG_ALT and zero precision and a zero number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#.0X %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + /* Test the support of the 'b' conversion specifier for binary output of integers. */ @@ -4080,6 +4333,60 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } + { /* Precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "00000011000000111001 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Zero precision and a positive number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.0b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "11000000111001 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Zero precision and a zero number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.0b %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Width and precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%25.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 00000011000000111001 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Padding and precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%025.20b %d", 12345, 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 implementations do so. */ + ASSERT (strcmp (result, " 00000011000000111001 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ size_t length; char *result = @@ -4094,6 +4401,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) size_t length; char *result = my_asnprintf (NULL, &length, "%#b %d", 0, 33, 44, 55); + ASSERT (result != NULL); ASSERT (strcmp (result, "0 33") == 0); ASSERT (length == strlen (result)); free (result); @@ -4103,11 +4411,77 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) size_t length; char *result = my_asnprintf (NULL, &length, "%#b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); ASSERT (strcmp (result, "0b11000000111001 33") == 0); ASSERT (length == strlen (result)); free (result); } + { /* FLAG_ALT with a positive number and width. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 0b11000000111001 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%0#20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0b000011000000111001 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%0#.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0b00000011000000111001 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#25.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 0b00000011000000111001 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding and precision. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%0#25.20b %d", 12345, 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 implementations do so. */ + ASSERT (strcmp (result, " 0b00000011000000111001 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#.0b %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + #if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) && !defined __UCLIBC__ /* Test that the 'I' flag is supported. */ { diff --git a/tests/test-vasnwprintf-posix.c b/tests/test-vasnwprintf-posix.c index e53c6a33f3..49f5f91ebe 100644 --- a/tests/test-vasnwprintf-posix.c +++ b/tests/test-vasnwprintf-posix.c @@ -4022,6 +4022,259 @@ test_function (wchar_t * (*my_asnwprintf) (wchar_t *, size_t *, const wchar_t *, } #endif + /* Test the support of the 'x' conversion specifier for hexadecimal output of + integers. */ + + { /* Zero. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"0 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* A positive number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* A large positive number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%x %d", 0xFFFFFFFEU, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"fffffffe 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Width. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L" 303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Width given as argument. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%*x %d", 10, 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L" 303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Negative width given as argument (cf. FLAG_LEFT below). */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%*x %d", -10, 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"000000303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Zero precision and a positive number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%.0x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Zero precision and a zero number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%.0x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (wcscmp (result, L" 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Width and precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%15.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L" 000000303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Padding and precision. */ + size_t length; + 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 || defined __MINGW32__ + ASSERT (wcscmp (result, L"00000000000303c 33") == 0); + #else + ASSERT (wcscmp (result, L" 000000303c 33") == 0); + #endif + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_LEFT. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%-10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with zero. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"0 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"0x303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and width. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L" 0x303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%0#10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"0x0000303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%0#.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"0x000000303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#15.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L" 0x000000303c 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding and precision. */ + size_t length; + 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 || defined __MINGW32__ + ASSERT (wcscmp (result, L"0x000000000303c 33") == 0); + #else + ASSERT (wcscmp (result, L" 0x000000303c 33") == 0); + #endif + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#.0x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (wcscmp (result, L" 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Uppercase 'X'. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%X %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"303C 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Uppercase 'X' with FLAG_ALT. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#X %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"0X303C 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Uppercase 'X' with FLAG_ALT and zero precision and a zero number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#.0X %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (wcscmp (result, L" 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + /* Test the support of the 'b' conversion specifier for binary output of integers. */ @@ -4085,6 +4338,60 @@ test_function (wchar_t * (*my_asnwprintf) (wchar_t *, size_t *, const wchar_t *, free (result); } + { /* Precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"00000011000000111001 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Zero precision and a positive number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%.0b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"11000000111001 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Zero precision and a zero number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%.0b %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (wcscmp (result, L" 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Width and precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%25.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L" 00000011000000111001 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* Padding and precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%025.20b %d", 12345, 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 implementations do so. */ + ASSERT (wcscmp (result, L" 00000011000000111001 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + { /* FLAG_LEFT. */ size_t length; wchar_t *result = @@ -4099,6 +4406,7 @@ test_function (wchar_t * (*my_asnwprintf) (wchar_t *, size_t *, const wchar_t *, size_t length; wchar_t *result = my_asnwprintf (NULL, &length, L"%#b %d", 0, 33, 44, 55); + ASSERT (result != NULL); ASSERT (wcscmp (result, L"0 33") == 0); ASSERT (length == wcslen (result)); free (result); @@ -4108,11 +4416,77 @@ test_function (wchar_t * (*my_asnwprintf) (wchar_t *, size_t *, const wchar_t *, size_t length; wchar_t *result = my_asnwprintf (NULL, &length, L"%#b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); ASSERT (wcscmp (result, L"0b11000000111001 33") == 0); ASSERT (length == wcslen (result)); free (result); } + { /* FLAG_ALT with a positive number and width. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L" 0b11000000111001 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%0#20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"0b000011000000111001 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%0#.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L"0b00000011000000111001 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#25.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (wcscmp (result, L" 0b00000011000000111001 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding and precision. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%0#25.20b %d", 12345, 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 implementations do so. */ + ASSERT (wcscmp (result, L" 0b00000011000000111001 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + size_t length; + wchar_t *result = + my_asnwprintf (NULL, &length, L"%#.0b %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (wcscmp (result, L" 33") == 0); + ASSERT (length == wcslen (result)); + free (result); + } + #if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) && !defined __UCLIBC__ /* Test that the 'I' flag is supported. */ { diff --git a/tests/test-vasprintf-posix.c b/tests/test-vasprintf-posix.c index 46086ef251..0da0c7441b 100644 --- a/tests/test-vasprintf-posix.c +++ b/tests/test-vasprintf-posix.c @@ -3956,6 +3956,259 @@ test_function (int (*my_asprintf) (char **, const char *, ...)) } #endif + /* Test the support of the 'x' conversion specifier for hexadecimal output of + integers. */ + + { /* Zero. */ + char *result; + int retval = + my_asprintf (&result, "%x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* A positive number. */ + char *result; + int retval = + my_asprintf (&result, "%x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* A large positive number. */ + char *result; + int retval = + my_asprintf (&result, "%x %d", 0xFFFFFFFEU, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "fffffffe 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Width. */ + char *result; + int retval = + my_asprintf (&result, "%10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Width given as argument. */ + char *result; + int retval = + my_asprintf (&result, "%*x %d", 10, 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Negative width given as argument (cf. FLAG_LEFT below). */ + char *result; + int retval = + my_asprintf (&result, "%*x %d", -10, 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Precision. */ + char *result; + int retval = + my_asprintf (&result, "%.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "000000303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Zero precision and a positive number. */ + char *result; + int retval = + my_asprintf (&result, "%.0x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Zero precision and a zero number. */ + char *result; + int retval = + my_asprintf (&result, "%.0x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Width and precision. */ + char *result; + int retval = + my_asprintf (&result, "%15.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 000000303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Padding and precision. */ + char *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); + #else + ASSERT (strcmp (result, " 000000303c 33") == 0); + #endif + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_LEFT. */ + char *result; + int retval = + my_asprintf (&result, "%-10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with zero. */ + char *result; + int retval = + my_asprintf (&result, "%#x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number. */ + char *result; + int retval = + my_asprintf (&result, "%#x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0x303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and width. */ + char *result; + int retval = + my_asprintf (&result, "%#10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 0x303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding. */ + char *result; + int retval = + my_asprintf (&result, "%0#10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0x0000303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and precision. */ + char *result; + int retval = + my_asprintf (&result, "%0#.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0x000000303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + char *result; + int retval = + my_asprintf (&result, "%#15.10x %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 0x000000303c 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding and precision. */ + char *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); + #else + ASSERT (strcmp (result, " 0x000000303c 33") == 0); + #endif + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + char *result; + int retval = + my_asprintf (&result, "%#.0x %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Uppercase 'X'. */ + char *result; + int retval = + my_asprintf (&result, "%X %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "303C 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Uppercase 'X' with FLAG_ALT. */ + char *result; + int retval = + my_asprintf (&result, "%#X %d", 12348, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0X303C 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Uppercase 'X' with FLAG_ALT and zero precision and a zero number. */ + char *result; + int retval = + my_asprintf (&result, "%#.0X %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + /* Test the support of the 'b' conversion specifier for binary output of integers. */ @@ -4019,6 +4272,60 @@ test_function (int (*my_asprintf) (char **, const char *, ...)) free (result); } + { /* Precision. */ + char *result; + int retval = + my_asprintf (&result, "%.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Zero precision and a positive number. */ + char *result; + int retval = + my_asprintf (&result, "%.0b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "11000000111001 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Zero precision and a zero number. */ + char *result; + int retval = + my_asprintf (&result, "%.0b %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters." */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Width and precision. */ + char *result; + int retval = + my_asprintf (&result, "%25.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* Padding and precision. */ + char *result; + int retval = + my_asprintf (&result, "%025.20b %d", 12345, 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 implementations do so. */ + ASSERT (strcmp (result, " 00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ char *result; int retval = @@ -4033,6 +4340,7 @@ test_function (int (*my_asprintf) (char **, const char *, ...)) char *result; int retval = my_asprintf (&result, "%#b %d", 0, 33, 44, 55); + ASSERT (result != NULL); ASSERT (strcmp (result, "0 33") == 0); ASSERT (retval == strlen (result)); free (result); @@ -4042,10 +4350,76 @@ test_function (int (*my_asprintf) (char **, const char *, ...)) char *result; int retval = my_asprintf (&result, "%#b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); ASSERT (strcmp (result, "0b11000000111001 33") == 0); ASSERT (retval == strlen (result)); free (result); } + + { /* FLAG_ALT with a positive number and width. */ + char *result; + int retval = + my_asprintf (&result, "%#20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 0b11000000111001 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding. */ + char *result; + int retval = + my_asprintf (&result, "%0#20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0b000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and precision. */ + char *result; + int retval = + my_asprintf (&result, "%0#.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "0b00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and width and precision. */ + char *result; + int retval = + my_asprintf (&result, "%#25.20b %d", 12345, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 0b00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a positive number and padding and precision. */ + char *result; + int retval = + my_asprintf (&result, "%0#25.20b %d", 12345, 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 implementations do so. */ + ASSERT (strcmp (result, " 0b00000011000000111001 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } + + { /* FLAG_ALT with a zero precision and a zero number. */ + char *result; + int retval = + my_asprintf (&result, "%#.0b %d", 0, 33, 44, 55); + ASSERT (result != NULL); + /* ISO C and POSIX specify that "The result of converting a zero value + with a precision of zero is no characters.", and the prefix is added + only for non-zero values. */ + ASSERT (strcmp (result, " 33") == 0); + ASSERT (retval == strlen (result)); + free (result); + } } static int