summaryrefslogtreecommitdiffstats
path: root/gl/vasnprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/vasnprintf.c')
-rw-r--r--gl/vasnprintf.c1668
1 files changed, 1455 insertions, 213 deletions
diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c
index 277c39e..de20445 100644
--- a/gl/vasnprintf.c
+++ b/gl/vasnprintf.c
@@ -1,5 +1,5 @@
1/* vsprintf with automatic memory allocation. 1/* vsprintf with automatic memory allocation.
2 Copyright (C) 1999, 2002-2023 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2002-2024 Free Software Foundation, Inc.
3 3
4 This file is free software: you can redistribute it and/or modify 4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as 5 it under the terms of the GNU Lesser General Public License as
@@ -83,9 +83,9 @@
83#include <stdio.h> /* snprintf(), sprintf() */ 83#include <stdio.h> /* snprintf(), sprintf() */
84#include <stdlib.h> /* abort(), malloc(), realloc(), free() */ 84#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
85#include <string.h> /* memcpy(), strlen() */ 85#include <string.h> /* memcpy(), strlen() */
86#include <wchar.h> /* mbstate_t, mbrtowc(), mbrlen(), wcrtomb() */ 86#include <wchar.h> /* mbstate_t, mbrtowc(), mbrlen(), wcrtomb(), mbszero() */
87#include <errno.h> /* errno */ 87#include <errno.h> /* errno */
88#include <limits.h> /* CHAR_BIT */ 88#include <limits.h> /* CHAR_BIT, INT_WIDTH, LONG_WIDTH */
89#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ 89#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
90#if HAVE_NL_LANGINFO 90#if HAVE_NL_LANGINFO
91# include <langinfo.h> 91# include <langinfo.h>
@@ -103,29 +103,29 @@
103 103
104#include "attribute.h" 104#include "attribute.h"
105 105
106#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL 106#if NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
107# include <math.h> 107# include <math.h>
108# include "float+.h" 108# include "float+.h"
109#endif 109#endif
110 110
111#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL 111#if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
112# include <math.h> 112# include <math.h>
113# include "isnand-nolibm.h" 113# include "isnand-nolibm.h"
114#endif 114#endif
115 115
116#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL 116#if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
117# include <math.h> 117# include <math.h>
118# include "isnanl-nolibm.h" 118# include "isnanl-nolibm.h"
119# include "fpucw.h" 119# include "fpucw.h"
120#endif 120#endif
121 121
122#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL 122#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
123# include <math.h> 123# include <math.h>
124# include "isnand-nolibm.h" 124# include "isnand-nolibm.h"
125# include "printf-frexp.h" 125# include "printf-frexp.h"
126#endif 126#endif
127 127
128#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL 128#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
129# include <math.h> 129# include <math.h>
130# include "isnanl-nolibm.h" 130# include "isnanl-nolibm.h"
131# include "printf-frexpl.h" 131# include "printf-frexpl.h"
@@ -138,8 +138,6 @@
138# define VASNPRINTF vasnwprintf 138# define VASNPRINTF vasnwprintf
139# define FCHAR_T wchar_t 139# define FCHAR_T wchar_t
140# define DCHAR_T wchar_t 140# define DCHAR_T wchar_t
141# define TCHAR_T wchar_t
142# define DCHAR_IS_TCHAR 1
143# define DIRECTIVE wchar_t_directive 141# define DIRECTIVE wchar_t_directive
144# define DIRECTIVES wchar_t_directives 142# define DIRECTIVES wchar_t_directives
145# define PRINTF_PARSE wprintf_parse 143# define PRINTF_PARSE wprintf_parse
@@ -159,24 +157,32 @@
159# endif 157# endif
160#endif 158#endif
161#if WIDE_CHAR_VERSION 159#if WIDE_CHAR_VERSION
162 /* TCHAR_T is wchar_t. */ 160 /* DCHAR_T is wchar_t. */
163# define USE_SNPRINTF 1 161# if HAVE_DECL__SNWPRINTF || (HAVE_SWPRINTF && HAVE_WORKING_SWPRINTF)
164# if HAVE_DECL__SNWPRINTF 162# define TCHAR_T wchar_t
165 /* On Windows, the function swprintf() has a different signature than 163# define DCHAR_IS_TCHAR 1
166 on Unix; we use the function _snwprintf() or - on mingw - snwprintf() 164# define USE_SNPRINTF 1
167 instead. The mingw function snwprintf() has fewer bugs than the 165# if HAVE_DECL__SNWPRINTF
168 MSVCRT function _snwprintf(), so prefer that. */ 166 /* On Windows, the function swprintf() has a different signature than
169# if defined __MINGW32__ 167 on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
170# define SNPRINTF snwprintf 168 instead. The mingw function snwprintf() has fewer bugs than the
169 MSVCRT function _snwprintf(), so prefer that. */
170# if defined __MINGW32__
171# define SNPRINTF snwprintf
172# else
173# define SNPRINTF _snwprintf
174# define USE_MSVC__SNPRINTF 1
175# endif
171# else 176# else
172# define SNPRINTF _snwprintf 177 /* Unix. */
173# define USE_MSVC__SNPRINTF 1 178# define SNPRINTF swprintf
174# endif 179# endif
175# else 180# else
176 /* Unix. */ 181 /* Old platforms such as NetBSD 3.0, OpenBSD 3.8, HP-UX 11.00, IRIX 6.5. */
177# define SNPRINTF swprintf 182# define TCHAR_T char
178# endif 183# endif
179#else 184#endif
185#if !WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR
180 /* TCHAR_T is char. */ 186 /* TCHAR_T is char. */
181 /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'. 187 /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
182 But don't use it on BeOS, since BeOS snprintf produces no output if the 188 But don't use it on BeOS, since BeOS snprintf produces no output if the
@@ -241,7 +247,7 @@ local_strnlen (const char *string, size_t maxlen)
241# endif 247# endif
242#endif 248#endif
243 249
244#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T 250#if (((!USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_WPRINTF_DIRECTIVE_LC) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
245# if HAVE_WCSLEN 251# if HAVE_WCSLEN
246# define local_wcslen wcslen 252# define local_wcslen wcslen
247# else 253# else
@@ -264,8 +270,8 @@ local_wcslen (const wchar_t *s)
264# endif 270# endif
265#endif 271#endif
266 272
267#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && HAVE_WCHAR_T && WIDE_CHAR_VERSION 273#if (!USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
268# if HAVE_WCSNLEN 274# if HAVE_WCSNLEN && HAVE_DECL_WCSNLEN
269# define local_wcsnlen wcsnlen 275# define local_wcsnlen wcsnlen
270# else 276# else
271# ifndef local_wcsnlen_defined 277# ifndef local_wcsnlen_defined
@@ -283,12 +289,12 @@ local_wcsnlen (const wchar_t *s, size_t maxlen)
283# endif 289# endif
284#endif 290#endif
285 291
286#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T) || (ENABLE_WCHAR_FALLBACK && HAVE_WINT_T)) && !WIDE_CHAR_VERSION 292#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T) || ((NEED_PRINTF_DIRECTIVE_LC || ENABLE_WCHAR_FALLBACK) && HAVE_WINT_T)) && !WIDE_CHAR_VERSION
287# if ENABLE_WCHAR_FALLBACK 293# if ENABLE_WCHAR_FALLBACK
288static size_t 294static size_t
289wctomb_fallback (char *s, wchar_t wc) 295wctomb_fallback (char *s, wchar_t wc)
290{ 296{
291 static char hex[16] = "0123456789ABCDEF"; 297 static char const hex[16] = "0123456789ABCDEF";
292 298
293 s[0] = '\\'; 299 s[0] = '\\';
294 if (sizeof (wchar_t) > 2 && wc > 0xffff) 300 if (sizeof (wchar_t) > 2 && wc > 0xffff)
@@ -351,7 +357,7 @@ local_wctomb (char *s, wchar_t wc)
351# endif 357# endif
352#endif 358#endif
353 359
354#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL 360#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
355/* Determine the decimal-point character according to the current locale. */ 361/* Determine the decimal-point character according to the current locale. */
356# ifndef decimal_point_char_defined 362# ifndef decimal_point_char_defined
357# define decimal_point_char_defined 1 363# define decimal_point_char_defined 1
@@ -378,7 +384,7 @@ decimal_point_char (void)
378# endif 384# endif
379#endif 385#endif
380 386
381#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL 387#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE
382 388
383/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ 389/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
384static int 390static int
@@ -389,7 +395,7 @@ is_infinite_or_zero (double x)
389 395
390#endif 396#endif
391 397
392#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL 398#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE
393 399
394/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ 400/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
395static int 401static int
@@ -400,7 +406,7 @@ is_infinite_or_zerol (long double x)
400 406
401#endif 407#endif
402 408
403#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL 409#if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE
404 410
405/* Converting 'long double' to decimal without rare rounding bugs requires 411/* Converting 'long double' to decimal without rare rounding bugs requires
406 real bignums. We use the naming conventions of GNU gmp, but vastly simpler 412 real bignums. We use the naming conventions of GNU gmp, but vastly simpler
@@ -921,6 +927,14 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
921 return roomptr; 927 return roomptr;
922} 928}
923 929
930/* Avoid pointless GCC warning "argument 1 value '18446744073709551615' exceeds
931 maximum object size 9223372036854775807", triggered by the use of xsum as
932 argument of malloc. */
933# if __GNUC__ >= 7
934# pragma GCC diagnostic push
935# pragma GCC diagnostic ignored "-Walloc-size-larger-than="
936# endif
937
924/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal 938/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
925 representation. 939 representation.
926 Destroys the contents of a. 940 Destroys the contents of a.
@@ -977,6 +991,10 @@ convert_to_decimal (mpn_t a, size_t extra_zeroes)
977 return c_ptr; 991 return c_ptr;
978} 992}
979 993
994# if __GNUC__ >= 7
995# pragma GCC diagnostic pop
996# endif
997
980# if NEED_PRINTF_LONG_DOUBLE 998# if NEED_PRINTF_LONG_DOUBLE
981 999
982/* Assuming x is finite and >= 0: 1000/* Assuming x is finite and >= 0:
@@ -1171,8 +1189,6 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1171 void *z_memory; 1189 void *z_memory;
1172 char *digits; 1190 char *digits;
1173 1191
1174 if (memory == NULL)
1175 return NULL;
1176 /* x = 2^e * m, hence 1192 /* x = 2^e * m, hence
1177 y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m) 1193 y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
1178 = round (2^s * 5^n * m). */ 1194 = round (2^s * 5^n * m). */
@@ -1380,10 +1396,13 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1380static char * 1396static char *
1381scale10_round_decimal_long_double (long double x, int n) 1397scale10_round_decimal_long_double (long double x, int n)
1382{ 1398{
1383 int e IF_LINT(= 0); 1399 int e;
1384 mpn_t m; 1400 mpn_t m;
1385 void *memory = decode_long_double (x, &e, &m); 1401 void *memory = decode_long_double (x, &e, &m);
1386 return scale10_round_decimal_decoded (e, m, memory, n); 1402 if (memory != NULL)
1403 return scale10_round_decimal_decoded (e, m, memory, n);
1404 else
1405 return NULL;
1387} 1406}
1388 1407
1389# endif 1408# endif
@@ -1398,10 +1417,13 @@ scale10_round_decimal_long_double (long double x, int n)
1398static char * 1417static char *
1399scale10_round_decimal_double (double x, int n) 1418scale10_round_decimal_double (double x, int n)
1400{ 1419{
1401 int e IF_LINT(= 0); 1420 int e;
1402 mpn_t m; 1421 mpn_t m;
1403 void *memory = decode_double (x, &e, &m); 1422 void *memory = decode_double (x, &e, &m);
1404 return scale10_round_decimal_decoded (e, m, memory, n); 1423 if (memory != NULL)
1424 return scale10_round_decimal_decoded (e, m, memory, n);
1425 else
1426 return NULL;
1405} 1427}
1406 1428
1407# endif 1429# endif
@@ -1604,7 +1626,7 @@ is_borderline (const char *digits, size_t precision)
1604 1626
1605#endif 1627#endif
1606 1628
1607#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF 1629#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
1608 1630
1609/* Use a different function name, to make it possible that the 'wchar_t' 1631/* Use a different function name, to make it possible that the 'wchar_t'
1610 parametrization and the 'char' parametrization get compiled in the same 1632 parametrization and the 'char' parametrization get compiled in the same
@@ -1627,24 +1649,156 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
1627 switch (conversion) 1649 switch (conversion)
1628 { 1650 {
1629 case 'd': case 'i': case 'u': 1651 case 'd': case 'i': case 'u':
1630 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 1652 switch (type)
1631 tmp_length = 1653 {
1632 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 1654 default:
1633 * 0.30103 /* binary -> decimal */ 1655 tmp_length =
1634 ) 1656 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
1635 + 1; /* turn floor into ceil */ 1657 * 0.30103 /* binary -> decimal */
1636 else if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 1658 )
1637 tmp_length = 1659 + 1; /* turn floor into ceil */
1638 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 1660 break;
1639 * 0.30103 /* binary -> decimal */ 1661 case TYPE_LONGINT:
1640 ) 1662 tmp_length =
1641 + 1; /* turn floor into ceil */ 1663 (unsigned int) (sizeof (long int) * CHAR_BIT
1642 else 1664 * 0.30103 /* binary -> decimal */
1643 tmp_length = 1665 )
1644 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 1666 + 1; /* turn floor into ceil */
1645 * 0.30103 /* binary -> decimal */ 1667 break;
1646 ) 1668 case TYPE_ULONGINT:
1647 + 1; /* turn floor into ceil */ 1669 tmp_length =
1670 (unsigned int) (sizeof (unsigned long int) * CHAR_BIT
1671 * 0.30103 /* binary -> decimal */
1672 )
1673 + 1; /* turn floor into ceil */
1674 break;
1675 case TYPE_LONGLONGINT:
1676 tmp_length =
1677 (unsigned int) (sizeof (long long int) * CHAR_BIT
1678 * 0.30103 /* binary -> decimal */
1679 )
1680 + 1; /* turn floor into ceil */
1681 break;
1682 case TYPE_ULONGLONGINT:
1683 tmp_length =
1684 (unsigned int) (sizeof (unsigned long long int) * CHAR_BIT
1685 * 0.30103 /* binary -> decimal */
1686 )
1687 + 1; /* turn floor into ceil */
1688 break;
1689 case TYPE_INT8_T:
1690 tmp_length =
1691 (unsigned int) (sizeof (int8_t) * CHAR_BIT
1692 * 0.30103 /* binary -> decimal */
1693 )
1694 + 1; /* turn floor into ceil */
1695 break;
1696 case TYPE_UINT8_T:
1697 tmp_length =
1698 (unsigned int) (sizeof (uint8_t) * CHAR_BIT
1699 * 0.30103 /* binary -> decimal */
1700 )
1701 + 1; /* turn floor into ceil */
1702 break;
1703 case TYPE_INT16_T:
1704 tmp_length =
1705 (unsigned int) (sizeof (int16_t) * CHAR_BIT
1706 * 0.30103 /* binary -> decimal */
1707 )
1708 + 1; /* turn floor into ceil */
1709 break;
1710 case TYPE_UINT16_T:
1711 tmp_length =
1712 (unsigned int) (sizeof (uint16_t) * CHAR_BIT
1713 * 0.30103 /* binary -> decimal */
1714 )
1715 + 1; /* turn floor into ceil */
1716 break;
1717 case TYPE_INT32_T:
1718 tmp_length =
1719 (unsigned int) (sizeof (int32_t) * CHAR_BIT
1720 * 0.30103 /* binary -> decimal */
1721 )
1722 + 1; /* turn floor into ceil */
1723 break;
1724 case TYPE_UINT32_T:
1725 tmp_length =
1726 (unsigned int) (sizeof (uint32_t) * CHAR_BIT
1727 * 0.30103 /* binary -> decimal */
1728 )
1729 + 1; /* turn floor into ceil */
1730 break;
1731 case TYPE_INT64_T:
1732 tmp_length =
1733 (unsigned int) (sizeof (int64_t) * CHAR_BIT
1734 * 0.30103 /* binary -> decimal */
1735 )
1736 + 1; /* turn floor into ceil */
1737 break;
1738 case TYPE_UINT64_T:
1739 tmp_length =
1740 (unsigned int) (sizeof (uint64_t) * CHAR_BIT
1741 * 0.30103 /* binary -> decimal */
1742 )
1743 + 1; /* turn floor into ceil */
1744 break;
1745 case TYPE_INT_FAST8_T:
1746 tmp_length =
1747 (unsigned int) (sizeof (int_fast8_t) * CHAR_BIT
1748 * 0.30103 /* binary -> decimal */
1749 )
1750 + 1; /* turn floor into ceil */
1751 break;
1752 case TYPE_UINT_FAST8_T:
1753 tmp_length =
1754 (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT
1755 * 0.30103 /* binary -> decimal */
1756 )
1757 + 1; /* turn floor into ceil */
1758 break;
1759 case TYPE_INT_FAST16_T:
1760 tmp_length =
1761 (unsigned int) (sizeof (int_fast16_t) * CHAR_BIT
1762 * 0.30103 /* binary -> decimal */
1763 )
1764 + 1; /* turn floor into ceil */
1765 break;
1766 case TYPE_UINT_FAST16_T:
1767 tmp_length =
1768 (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT
1769 * 0.30103 /* binary -> decimal */
1770 )
1771 + 1; /* turn floor into ceil */
1772 break;
1773 case TYPE_INT_FAST32_T:
1774 tmp_length =
1775 (unsigned int) (sizeof (int_fast32_t) * CHAR_BIT
1776 * 0.30103 /* binary -> decimal */
1777 )
1778 + 1; /* turn floor into ceil */
1779 break;
1780 case TYPE_UINT_FAST32_T:
1781 tmp_length =
1782 (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT
1783 * 0.30103 /* binary -> decimal */
1784 )
1785 + 1; /* turn floor into ceil */
1786 break;
1787 case TYPE_INT_FAST64_T:
1788 tmp_length =
1789 (unsigned int) (sizeof (int_fast64_t) * CHAR_BIT
1790 * 0.30103 /* binary -> decimal */
1791 )
1792 + 1; /* turn floor into ceil */
1793 break;
1794 case TYPE_UINT_FAST64_T:
1795 tmp_length =
1796 (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT
1797 * 0.30103 /* binary -> decimal */
1798 )
1799 + 1; /* turn floor into ceil */
1800 break;
1801 }
1648 if (tmp_length < precision) 1802 if (tmp_length < precision)
1649 tmp_length = precision; 1803 tmp_length = precision;
1650 /* Multiply by 2, as an estimate for FLAG_GROUP. */ 1804 /* Multiply by 2, as an estimate for FLAG_GROUP. */
@@ -1653,25 +1807,156 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
1653 tmp_length = xsum (tmp_length, 1); 1807 tmp_length = xsum (tmp_length, 1);
1654 break; 1808 break;
1655 1809
1810 case 'b':
1811 #if SUPPORT_GNU_PRINTF_DIRECTIVES \
1812 || (__GLIBC__ + (__GLIBC_MINOR__ >= 35) > 2)
1813 case 'B':
1814 #endif
1815 switch (type)
1816 {
1817 default:
1818 tmp_length =
1819 (unsigned int) (sizeof (unsigned int) * CHAR_BIT)
1820 + 1; /* turn floor into ceil */
1821 break;
1822 case TYPE_ULONGINT:
1823 tmp_length =
1824 (unsigned int) (sizeof (unsigned long int) * CHAR_BIT)
1825 + 1; /* turn floor into ceil */
1826 break;
1827 case TYPE_ULONGLONGINT:
1828 tmp_length =
1829 (unsigned int) (sizeof (unsigned long long int) * CHAR_BIT)
1830 + 1; /* turn floor into ceil */
1831 break;
1832 case TYPE_UINT8_T:
1833 tmp_length =
1834 (unsigned int) (sizeof (uint8_t) * CHAR_BIT)
1835 + 1; /* turn floor into ceil */
1836 break;
1837 case TYPE_UINT16_T:
1838 tmp_length =
1839 (unsigned int) (sizeof (uint16_t) * CHAR_BIT)
1840 + 1; /* turn floor into ceil */
1841 break;
1842 case TYPE_UINT32_T:
1843 tmp_length =
1844 (unsigned int) (sizeof (uint32_t) * CHAR_BIT)
1845 + 1; /* turn floor into ceil */
1846 break;
1847 case TYPE_UINT64_T:
1848 tmp_length =
1849 (unsigned int) (sizeof (uint64_t) * CHAR_BIT)
1850 + 1; /* turn floor into ceil */
1851 break;
1852 case TYPE_UINT_FAST8_T:
1853 tmp_length =
1854 (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT)
1855 + 1; /* turn floor into ceil */
1856 break;
1857 case TYPE_UINT_FAST16_T:
1858 tmp_length =
1859 (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT)
1860 + 1; /* turn floor into ceil */
1861 break;
1862 case TYPE_UINT_FAST32_T:
1863 tmp_length =
1864 (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT)
1865 + 1; /* turn floor into ceil */
1866 break;
1867 case TYPE_UINT_FAST64_T:
1868 tmp_length =
1869 (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT)
1870 + 1; /* turn floor into ceil */
1871 break;
1872 }
1873 if (tmp_length < precision)
1874 tmp_length = precision;
1875 /* Add 2, to account for a prefix from the alternate form. */
1876 tmp_length = xsum (tmp_length, 2);
1877 break;
1878
1656 case 'o': 1879 case 'o':
1657 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 1880 switch (type)
1658 tmp_length = 1881 {
1659 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 1882 default:
1660 * 0.333334 /* binary -> octal */ 1883 tmp_length =
1661 ) 1884 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
1662 + 1; /* turn floor into ceil */ 1885 * 0.333334 /* binary -> octal */
1663 else if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 1886 )
1664 tmp_length = 1887 + 1; /* turn floor into ceil */
1665 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 1888 break;
1666 * 0.333334 /* binary -> octal */ 1889 case TYPE_ULONGINT:
1667 ) 1890 tmp_length =
1668 + 1; /* turn floor into ceil */ 1891 (unsigned int) (sizeof (unsigned long int) * CHAR_BIT
1669 else 1892 * 0.333334 /* binary -> octal */
1670 tmp_length = 1893 )
1671 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 1894 + 1; /* turn floor into ceil */
1672 * 0.333334 /* binary -> octal */ 1895 break;
1673 ) 1896 case TYPE_ULONGLONGINT:
1674 + 1; /* turn floor into ceil */ 1897 tmp_length =
1898 (unsigned int) (sizeof (unsigned long long int) * CHAR_BIT
1899 * 0.333334 /* binary -> octal */
1900 )
1901 + 1; /* turn floor into ceil */
1902 break;
1903 case TYPE_UINT8_T:
1904 tmp_length =
1905 (unsigned int) (sizeof (uint8_t) * CHAR_BIT
1906 * 0.333334 /* binary -> octal */
1907 )
1908 + 1; /* turn floor into ceil */
1909 break;
1910 case TYPE_UINT16_T:
1911 tmp_length =
1912 (unsigned int) (sizeof (uint16_t) * CHAR_BIT
1913 * 0.333334 /* binary -> octal */
1914 )
1915 + 1; /* turn floor into ceil */
1916 break;
1917 case TYPE_UINT32_T:
1918 tmp_length =
1919 (unsigned int) (sizeof (uint32_t) * CHAR_BIT
1920 * 0.333334 /* binary -> octal */
1921 )
1922 + 1; /* turn floor into ceil */
1923 break;
1924 case TYPE_UINT64_T:
1925 tmp_length =
1926 (unsigned int) (sizeof (uint64_t) * CHAR_BIT
1927 * 0.333334 /* binary -> octal */
1928 )
1929 + 1; /* turn floor into ceil */
1930 break;
1931 case TYPE_UINT_FAST8_T:
1932 tmp_length =
1933 (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT
1934 * 0.333334 /* binary -> octal */
1935 )
1936 + 1; /* turn floor into ceil */
1937 break;
1938 case TYPE_UINT_FAST16_T:
1939 tmp_length =
1940 (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT
1941 * 0.333334 /* binary -> octal */
1942 )
1943 + 1; /* turn floor into ceil */
1944 break;
1945 case TYPE_UINT_FAST32_T:
1946 tmp_length =
1947 (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT
1948 * 0.333334 /* binary -> octal */
1949 )
1950 + 1; /* turn floor into ceil */
1951 break;
1952 case TYPE_UINT_FAST64_T:
1953 tmp_length =
1954 (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT
1955 * 0.333334 /* binary -> octal */
1956 )
1957 + 1; /* turn floor into ceil */
1958 break;
1959 }
1675 if (tmp_length < precision) 1960 if (tmp_length < precision)
1676 tmp_length = precision; 1961 tmp_length = precision;
1677 /* Add 1, to account for a leading sign. */ 1962 /* Add 1, to account for a leading sign. */
@@ -1679,27 +1964,89 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
1679 break; 1964 break;
1680 1965
1681 case 'x': case 'X': 1966 case 'x': case 'X':
1682 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) 1967 switch (type)
1683 tmp_length = 1968 {
1684 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT 1969 default:
1685 * 0.25 /* binary -> hexadecimal */ 1970 tmp_length =
1686 ) 1971 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
1687 + 1; /* turn floor into ceil */ 1972 * 0.25 /* binary -> hexadecimal */
1688 else if (type == TYPE_LONGINT || type == TYPE_ULONGINT) 1973 )
1689 tmp_length = 1974 + 1; /* turn floor into ceil */
1690 (unsigned int) (sizeof (unsigned long) * CHAR_BIT 1975 break;
1691 * 0.25 /* binary -> hexadecimal */ 1976 case TYPE_ULONGINT:
1692 ) 1977 tmp_length =
1693 + 1; /* turn floor into ceil */ 1978 (unsigned int) (sizeof (unsigned long int) * CHAR_BIT
1694 else 1979 * 0.25 /* binary -> hexadecimal */
1695 tmp_length = 1980 )
1696 (unsigned int) (sizeof (unsigned int) * CHAR_BIT 1981 + 1; /* turn floor into ceil */
1697 * 0.25 /* binary -> hexadecimal */ 1982 break;
1698 ) 1983 case TYPE_ULONGLONGINT:
1699 + 1; /* turn floor into ceil */ 1984 tmp_length =
1985 (unsigned int) (sizeof (unsigned long long int) * CHAR_BIT
1986 * 0.25 /* binary -> hexadecimal */
1987 )
1988 + 1; /* turn floor into ceil */
1989 break;
1990 case TYPE_UINT8_T:
1991 tmp_length =
1992 (unsigned int) (sizeof (uint8_t) * CHAR_BIT
1993 * 0.25 /* binary -> hexadecimal */
1994 )
1995 + 1; /* turn floor into ceil */
1996 break;
1997 case TYPE_UINT16_T:
1998 tmp_length =
1999 (unsigned int) (sizeof (uint16_t) * CHAR_BIT
2000 * 0.25 /* binary -> hexadecimal */
2001 )
2002 + 1; /* turn floor into ceil */
2003 break;
2004 case TYPE_UINT32_T:
2005 tmp_length =
2006 (unsigned int) (sizeof (uint32_t) * CHAR_BIT
2007 * 0.25 /* binary -> hexadecimal */
2008 )
2009 + 1; /* turn floor into ceil */
2010 break;
2011 case TYPE_UINT64_T:
2012 tmp_length =
2013 (unsigned int) (sizeof (uint64_t) * CHAR_BIT
2014 * 0.25 /* binary -> hexadecimal */
2015 )
2016 + 1; /* turn floor into ceil */
2017 break;
2018 case TYPE_UINT_FAST8_T:
2019 tmp_length =
2020 (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT
2021 * 0.25 /* binary -> hexadecimal */
2022 )
2023 + 1; /* turn floor into ceil */
2024 break;
2025 case TYPE_UINT_FAST16_T:
2026 tmp_length =
2027 (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT
2028 * 0.25 /* binary -> hexadecimal */
2029 )
2030 + 1; /* turn floor into ceil */
2031 break;
2032 case TYPE_UINT_FAST32_T:
2033 tmp_length =
2034 (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT
2035 * 0.25 /* binary -> hexadecimal */
2036 )
2037 + 1; /* turn floor into ceil */
2038 break;
2039 case TYPE_UINT_FAST64_T:
2040 tmp_length =
2041 (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT
2042 * 0.25 /* binary -> hexadecimal */
2043 )
2044 + 1; /* turn floor into ceil */
2045 break;
2046 }
1700 if (tmp_length < precision) 2047 if (tmp_length < precision)
1701 tmp_length = precision; 2048 tmp_length = precision;
1702 /* Add 2, to account for a leading sign or alternate form. */ 2049 /* Add 2, to account for a prefix from the alternate form. */
1703 tmp_length = xsum (tmp_length, 2); 2050 tmp_length = xsum (tmp_length, 2);
1704 break; 2051 break;
1705 2052
@@ -1988,6 +2335,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
1988 2335
1989 if (dp->conversion == 'n') 2336 if (dp->conversion == 'n')
1990 { 2337 {
2338#if NEED_PRINTF_WITH_N_DIRECTIVE
1991 switch (a.arg[dp->arg_index].type) 2339 switch (a.arg[dp->arg_index].type)
1992 { 2340 {
1993 case TYPE_COUNT_SCHAR_POINTER: 2341 case TYPE_COUNT_SCHAR_POINTER:
@@ -2005,9 +2353,36 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2005 case TYPE_COUNT_LONGLONGINT_POINTER: 2353 case TYPE_COUNT_LONGLONGINT_POINTER:
2006 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; 2354 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
2007 break; 2355 break;
2356 case TYPE_COUNT_INT8_T_POINTER:
2357 *a.arg[dp->arg_index].a.a_count_int8_t_pointer = length;
2358 break;
2359 case TYPE_COUNT_INT16_T_POINTER:
2360 *a.arg[dp->arg_index].a.a_count_int16_t_pointer = length;
2361 break;
2362 case TYPE_COUNT_INT32_T_POINTER:
2363 *a.arg[dp->arg_index].a.a_count_int32_t_pointer = length;
2364 break;
2365 case TYPE_COUNT_INT64_T_POINTER:
2366 *a.arg[dp->arg_index].a.a_count_int64_t_pointer = length;
2367 break;
2368 case TYPE_COUNT_INT_FAST8_T_POINTER:
2369 *a.arg[dp->arg_index].a.a_count_int_fast8_t_pointer = length;
2370 break;
2371 case TYPE_COUNT_INT_FAST16_T_POINTER:
2372 *a.arg[dp->arg_index].a.a_count_int_fast16_t_pointer = length;
2373 break;
2374 case TYPE_COUNT_INT_FAST32_T_POINTER:
2375 *a.arg[dp->arg_index].a.a_count_int_fast32_t_pointer = length;
2376 break;
2377 case TYPE_COUNT_INT_FAST64_T_POINTER:
2378 *a.arg[dp->arg_index].a.a_count_int_fast64_t_pointer = length;
2379 break;
2008 default: 2380 default:
2009 abort (); 2381 abort ();
2010 } 2382 }
2383#else
2384 abort ();
2385#endif
2011 } 2386 }
2012#if ENABLE_UNISTDIO 2387#if ENABLE_UNISTDIO
2013 /* The unistdio extensions. */ 2388 /* The unistdio extensions. */
@@ -2130,7 +2505,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2130 characters = 0; 2505 characters = 0;
2131 } 2506 }
2132 2507
2133 if (characters < width && !(dp->flags & FLAG_LEFT)) 2508 if (characters < width && !(flags & FLAG_LEFT))
2134 { 2509 {
2135 size_t n = width - characters; 2510 size_t n = width - characters;
2136 ENSURE_ALLOCATION (xsum (length, n)); 2511 ENSURE_ALLOCATION (xsum (length, n));
@@ -2175,7 +2550,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2175 } 2550 }
2176# endif 2551# endif
2177 2552
2178 if (characters < width && (dp->flags & FLAG_LEFT)) 2553 if (characters < width && (flags & FLAG_LEFT))
2179 { 2554 {
2180 size_t n = width - characters; 2555 size_t n = width - characters;
2181 ENSURE_ALLOCATION (xsum (length, n)); 2556 ENSURE_ALLOCATION (xsum (length, n));
@@ -2232,7 +2607,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2232 characters = 0; 2607 characters = 0;
2233 } 2608 }
2234 2609
2235 if (characters < width && !(dp->flags & FLAG_LEFT)) 2610 if (characters < width && !(flags & FLAG_LEFT))
2236 { 2611 {
2237 size_t n = width - characters; 2612 size_t n = width - characters;
2238 ENSURE_ALLOCATION (xsum (length, n)); 2613 ENSURE_ALLOCATION (xsum (length, n));
@@ -2277,7 +2652,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2277 } 2652 }
2278# endif 2653# endif
2279 2654
2280 if (characters < width && (dp->flags & FLAG_LEFT)) 2655 if (characters < width && (flags & FLAG_LEFT))
2281 { 2656 {
2282 size_t n = width - characters; 2657 size_t n = width - characters;
2283 ENSURE_ALLOCATION (xsum (length, n)); 2658 ENSURE_ALLOCATION (xsum (length, n));
@@ -2334,7 +2709,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2334 characters = 0; 2709 characters = 0;
2335 } 2710 }
2336 2711
2337 if (characters < width && !(dp->flags & FLAG_LEFT)) 2712 if (characters < width && !(flags & FLAG_LEFT))
2338 { 2713 {
2339 size_t n = width - characters; 2714 size_t n = width - characters;
2340 ENSURE_ALLOCATION (xsum (length, n)); 2715 ENSURE_ALLOCATION (xsum (length, n));
@@ -2379,7 +2754,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2379 } 2754 }
2380# endif 2755# endif
2381 2756
2382 if (characters < width && (dp->flags & FLAG_LEFT)) 2757 if (characters < width && (flags & FLAG_LEFT))
2383 { 2758 {
2384 size_t n = width - characters; 2759 size_t n = width - characters;
2385 ENSURE_ALLOCATION (xsum (length, n)); 2760 ENSURE_ALLOCATION (xsum (length, n));
@@ -2394,7 +2769,150 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2394 } 2769 }
2395 } 2770 }
2396#endif 2771#endif
2397#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T 2772#if WIDE_CHAR_VERSION && (!DCHAR_IS_TCHAR || NEED_WPRINTF_DIRECTIVE_LC)
2773 else if ((dp->conversion == 's'
2774 && a.arg[dp->arg_index].type == TYPE_WIDE_STRING)
2775 || (dp->conversion == 'c'
2776 && a.arg[dp->arg_index].type == TYPE_WIDE_CHAR))
2777 {
2778 /* %ls or %lc in vasnwprintf. See the specification of
2779 fwprintf. */
2780 /* It would be silly to use snprintf ("%ls", ...) and then
2781 convert back the result from a char[] to a wchar_t[].
2782 Instead, just copy the argument wchar_t[] to the result. */
2783 int flags = dp->flags;
2784 size_t width;
2785
2786 width = 0;
2787 if (dp->width_start != dp->width_end)
2788 {
2789 if (dp->width_arg_index != ARG_NONE)
2790 {
2791 int arg;
2792
2793 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2794 abort ();
2795 arg = a.arg[dp->width_arg_index].a.a_int;
2796 width = arg;
2797 if (arg < 0)
2798 {
2799 /* "A negative field width is taken as a '-' flag
2800 followed by a positive field width." */
2801 flags |= FLAG_LEFT;
2802 width = -width;
2803 }
2804 }
2805 else
2806 {
2807 const FCHAR_T *digitp = dp->width_start;
2808
2809 do
2810 width = xsum (xtimes (width, 10), *digitp++ - '0');
2811 while (digitp != dp->width_end);
2812 }
2813 }
2814
2815 {
2816 const wchar_t *ls_arg;
2817 wchar_t lc_arg[1];
2818 size_t characters;
2819
2820 if (dp->conversion == 's')
2821 {
2822 int has_precision;
2823 size_t precision;
2824
2825 has_precision = 0;
2826 precision = 6;
2827 if (dp->precision_start != dp->precision_end)
2828 {
2829 if (dp->precision_arg_index != ARG_NONE)
2830 {
2831 int arg;
2832
2833 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2834 abort ();
2835 arg = a.arg[dp->precision_arg_index].a.a_int;
2836 /* "A negative precision is taken as if the precision
2837 were omitted." */
2838 if (arg >= 0)
2839 {
2840 precision = arg;
2841 has_precision = 1;
2842 }
2843 }
2844 else
2845 {
2846 const FCHAR_T *digitp = dp->precision_start + 1;
2847
2848 precision = 0;
2849 while (digitp != dp->precision_end)
2850 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2851 has_precision = 1;
2852 }
2853 }
2854
2855 ls_arg = a.arg[dp->arg_index].a.a_wide_string;
2856
2857 if (has_precision)
2858 {
2859 /* Use only at most PRECISION wide characters, from
2860 the left. */
2861 const wchar_t *ls_arg_end;
2862
2863 ls_arg_end = ls_arg;
2864 characters = 0;
2865 for (; precision > 0; precision--)
2866 {
2867 if (*ls_arg_end == 0)
2868 /* Found the terminating null wide character. */
2869 break;
2870 ls_arg_end++;
2871 characters++;
2872 }
2873 }
2874 else
2875 {
2876 /* Use the entire string, and count the number of wide
2877 characters. */
2878 characters = local_wcslen (ls_arg);
2879 }
2880 }
2881 else /* dp->conversion == 'c' */
2882 {
2883 lc_arg[0] = (wchar_t) a.arg[dp->arg_index].a.a_wide_char;
2884 ls_arg = lc_arg;
2885 characters = 1;
2886 }
2887
2888 {
2889 size_t total = (characters < width ? width : characters);
2890 ENSURE_ALLOCATION (xsum (length, total));
2891
2892 if (characters < width && !(flags & FLAG_LEFT))
2893 {
2894 size_t n = width - characters;
2895 DCHAR_SET (result + length, ' ', n);
2896 length += n;
2897 }
2898
2899 if (characters > 0)
2900 {
2901 DCHAR_CPY (result + length, ls_arg, characters);
2902 length += characters;
2903 }
2904
2905 if (characters < width && (flags & FLAG_LEFT))
2906 {
2907 size_t n = width - characters;
2908 DCHAR_SET (result + length, ' ', n);
2909 length += n;
2910 }
2911 }
2912 }
2913 }
2914#endif
2915#if (!USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T
2398 else if (dp->conversion == 's' 2916 else if (dp->conversion == 's'
2399# if WIDE_CHAR_VERSION 2917# if WIDE_CHAR_VERSION
2400 && a.arg[dp->arg_index].type != TYPE_WIDE_STRING 2918 && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
@@ -2493,7 +3011,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2493 wide characters, from the left. */ 3011 wide characters, from the left. */
2494# if HAVE_MBRTOWC 3012# if HAVE_MBRTOWC
2495 mbstate_t state; 3013 mbstate_t state;
2496 memset (&state, '\0', sizeof (mbstate_t)); 3014 mbszero (&state);
2497# endif 3015# endif
2498 arg_end = arg; 3016 arg_end = arg;
2499 characters = 0; 3017 characters = 0;
@@ -2521,7 +3039,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2521 characters. */ 3039 characters. */
2522# if HAVE_MBRTOWC 3040# if HAVE_MBRTOWC
2523 mbstate_t state; 3041 mbstate_t state;
2524 memset (&state, '\0', sizeof (mbstate_t)); 3042 mbszero (&state);
2525# endif 3043# endif
2526 arg_end = arg; 3044 arg_end = arg;
2527 characters = 0; 3045 characters = 0;
@@ -2551,7 +3069,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2551 characters = 0; 3069 characters = 0;
2552 } 3070 }
2553 3071
2554 if (characters < width && !(dp->flags & FLAG_LEFT)) 3072 if (characters < width && !(flags & FLAG_LEFT))
2555 { 3073 {
2556 size_t n = width - characters; 3074 size_t n = width - characters;
2557 ENSURE_ALLOCATION (xsum (length, n)); 3075 ENSURE_ALLOCATION (xsum (length, n));
@@ -2565,7 +3083,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2565 size_t remaining; 3083 size_t remaining;
2566# if HAVE_MBRTOWC 3084# if HAVE_MBRTOWC
2567 mbstate_t state; 3085 mbstate_t state;
2568 memset (&state, '\0', sizeof (mbstate_t)); 3086 mbszero (&state);
2569# endif 3087# endif
2570 ENSURE_ALLOCATION (xsum (length, characters)); 3088 ENSURE_ALLOCATION (xsum (length, characters));
2571 for (remaining = characters; remaining > 0; remaining--) 3089 for (remaining = characters; remaining > 0; remaining--)
@@ -2591,7 +3109,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2591 { 3109 {
2592# if HAVE_MBRTOWC 3110# if HAVE_MBRTOWC
2593 mbstate_t state; 3111 mbstate_t state;
2594 memset (&state, '\0', sizeof (mbstate_t)); 3112 mbszero (&state);
2595# endif 3113# endif
2596 while (arg < arg_end) 3114 while (arg < arg_end)
2597 { 3115 {
@@ -2602,17 +3120,19 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2602# else 3120# else
2603 count = mbtowc (&wc, arg, arg_end - arg); 3121 count = mbtowc (&wc, arg, arg_end - arg);
2604# endif 3122# endif
2605 if (count <= 0) 3123 if (count == 0)
2606 /* mbrtowc not consistent with mbrlen, or mbtowc 3124 /* mbrtowc not consistent with strlen. */
2607 not consistent with mblen. */
2608 abort (); 3125 abort ();
3126 if (count < 0)
3127 /* Invalid or incomplete multibyte character. */
3128 goto fail_with_EILSEQ;
2609 ENSURE_ALLOCATION (xsum (length, 1)); 3129 ENSURE_ALLOCATION (xsum (length, 1));
2610 result[length++] = wc; 3130 result[length++] = wc;
2611 arg += count; 3131 arg += count;
2612 } 3132 }
2613 } 3133 }
2614 3134
2615 if (characters < width && (dp->flags & FLAG_LEFT)) 3135 if (characters < width && (flags & FLAG_LEFT))
2616 { 3136 {
2617 size_t n = width - characters; 3137 size_t n = width - characters;
2618 ENSURE_ALLOCATION (xsum (length, n)); 3138 ENSURE_ALLOCATION (xsum (length, n));
@@ -2641,7 +3161,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2641 at most PRECISION bytes, from the left. */ 3161 at most PRECISION bytes, from the left. */
2642# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3162# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2643 mbstate_t state; 3163 mbstate_t state;
2644 memset (&state, '\0', sizeof (mbstate_t)); 3164 mbszero (&state);
2645# endif 3165# endif
2646 arg_end = arg; 3166 arg_end = arg;
2647 characters = 0; 3167 characters = 0;
@@ -2674,7 +3194,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2674 bytes. */ 3194 bytes. */
2675# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3195# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2676 mbstate_t state; 3196 mbstate_t state;
2677 memset (&state, '\0', sizeof (mbstate_t)); 3197 mbszero (&state);
2678# endif 3198# endif
2679 arg_end = arg; 3199 arg_end = arg;
2680 characters = 0; 3200 characters = 0;
@@ -2714,7 +3234,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2714 size_t remaining; 3234 size_t remaining;
2715# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3235# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2716 mbstate_t state; 3236 mbstate_t state;
2717 memset (&state, '\0', sizeof (mbstate_t)); 3237 mbszero (&state);
2718# endif 3238# endif
2719 for (remaining = characters; remaining > 0; ) 3239 for (remaining = characters; remaining > 0; )
2720 { 3240 {
@@ -2768,7 +3288,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2768 /* w doesn't matter. */ 3288 /* w doesn't matter. */
2769 w = 0; 3289 w = 0;
2770 3290
2771 if (w < width && !(dp->flags & FLAG_LEFT)) 3291 if (w < width && !(flags & FLAG_LEFT))
2772 { 3292 {
2773 size_t n = width - w; 3293 size_t n = width - w;
2774 ENSURE_ALLOCATION (xsum (length, n)); 3294 ENSURE_ALLOCATION (xsum (length, n));
@@ -2783,7 +3303,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2783 size_t remaining; 3303 size_t remaining;
2784# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3304# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2785 mbstate_t state; 3305 mbstate_t state;
2786 memset (&state, '\0', sizeof (mbstate_t)); 3306 mbszero (&state);
2787# endif 3307# endif
2788 ENSURE_ALLOCATION (xsum (length, characters)); 3308 ENSURE_ALLOCATION (xsum (length, characters));
2789 for (remaining = characters; remaining > 0; ) 3309 for (remaining = characters; remaining > 0; )
@@ -2809,7 +3329,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2809 { 3329 {
2810# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3330# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2811 mbstate_t state; 3331 mbstate_t state;
2812 memset (&state, '\0', sizeof (mbstate_t)); 3332 mbszero (&state);
2813# endif 3333# endif
2814 while (arg < arg_end) 3334 while (arg < arg_end)
2815 { 3335 {
@@ -2836,7 +3356,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2836 length += tmpdst_len; 3356 length += tmpdst_len;
2837# endif 3357# endif
2838 3358
2839 if (w < width && (dp->flags & FLAG_LEFT)) 3359 if (w < width && (flags & FLAG_LEFT))
2840 { 3360 {
2841 size_t n = width - w; 3361 size_t n = width - w;
2842 ENSURE_ALLOCATION (xsum (length, n)); 3362 ENSURE_ALLOCATION (xsum (length, n));
@@ -2847,12 +3367,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2847# endif 3367# endif
2848 } 3368 }
2849#endif 3369#endif
2850#if ENABLE_WCHAR_FALLBACK && HAVE_WINT_T && !WIDE_CHAR_VERSION 3370#if (NEED_PRINTF_DIRECTIVE_LC || ENABLE_WCHAR_FALLBACK) && HAVE_WINT_T && !WIDE_CHAR_VERSION
2851 else if (dp->conversion == 'c' 3371 else if (dp->conversion == 'c'
2852 && a.arg[dp->arg_index].type == TYPE_WIDE_CHAR) 3372 && a.arg[dp->arg_index].type == TYPE_WIDE_CHAR)
2853 { 3373 {
2854 /* Implement the 'lc' directive ourselves, in order to provide 3374 /* Implement the 'lc' directive ourselves, in order to provide
2855 the fallback that avoids EILSEQ. */ 3375 a correct behaviour for the null wint_t argument and/or the
3376 fallback that avoids EILSEQ. */
2856 int flags = dp->flags; 3377 int flags = dp->flags;
2857 int has_width; 3378 int has_width;
2858 size_t width; 3379 size_t width;
@@ -2907,21 +3428,18 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2907 { 3428 {
2908 /* Count the number of bytes. */ 3429 /* Count the number of bytes. */
2909 characters = 0; 3430 characters = 0;
2910 if (arg != 0) 3431 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2911 { 3432 int count;
2912 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2913 int count;
2914# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3433# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2915 mbstate_t state; 3434 mbstate_t state;
2916 memset (&state, '\0', sizeof (mbstate_t)); 3435 mbszero (&state);
2917# endif 3436# endif
2918 3437
2919 count = local_wcrtomb (cbuf, arg, &state); 3438 count = local_wcrtomb (cbuf, arg, &state);
2920 if (count < 0) 3439 if (count < 0)
2921 /* Inconsistency. */ 3440 /* Cannot convert. */
2922 abort (); 3441 goto fail_with_EILSEQ;
2923 characters = count; 3442 characters = count;
2924 }
2925 } 3443 }
2926# if DCHAR_IS_TCHAR 3444# if DCHAR_IS_TCHAR
2927 else 3445 else
@@ -2933,13 +3451,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2933 3451
2934# if !DCHAR_IS_TCHAR 3452# if !DCHAR_IS_TCHAR
2935 /* Convert the string into a piece of temporary memory. */ 3453 /* Convert the string into a piece of temporary memory. */
2936 if (characters > 0) /* implies arg != 0 */ 3454 if (characters > 0)
2937 { 3455 {
2938 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ 3456 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2939 int count; 3457 int count;
2940# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3458# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2941 mbstate_t state; 3459 mbstate_t state;
2942 memset (&state, '\0', sizeof (mbstate_t)); 3460 mbszero (&state);
2943# endif 3461# endif
2944 3462
2945 count = local_wcrtomb (cbuf, arg, &state); 3463 count = local_wcrtomb (cbuf, arg, &state);
@@ -2977,7 +3495,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2977 /* w doesn't matter. */ 3495 /* w doesn't matter. */
2978 w = 0; 3496 w = 0;
2979 3497
2980 if (w < width && !(dp->flags & FLAG_LEFT)) 3498 if (w < width && !(flags & FLAG_LEFT))
2981 { 3499 {
2982 size_t n = width - w; 3500 size_t n = width - w;
2983 ENSURE_ALLOCATION (xsum (length, n)); 3501 ENSURE_ALLOCATION (xsum (length, n));
@@ -2990,12 +3508,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2990 { 3508 {
2991 /* We know the number of bytes in advance. */ 3509 /* We know the number of bytes in advance. */
2992 ENSURE_ALLOCATION (xsum (length, characters)); 3510 ENSURE_ALLOCATION (xsum (length, characters));
2993 if (characters > 0) /* implies arg != 0 */ 3511 if (characters > 0)
2994 { 3512 {
2995 int count; 3513 int count;
2996# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3514# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2997 mbstate_t state; 3515 mbstate_t state;
2998 memset (&state, '\0', sizeof (mbstate_t)); 3516 mbszero (&state);
2999# endif 3517# endif
3000 3518
3001 count = local_wcrtomb (result + length, arg, &state); 3519 count = local_wcrtomb (result + length, arg, &state);
@@ -3007,23 +3525,20 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3007 } 3525 }
3008 else 3526 else
3009 { 3527 {
3010 if (arg != 0) 3528 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3011 { 3529 int count;
3012 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3013 int count;
3014# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3530# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
3015 mbstate_t state; 3531 mbstate_t state;
3016 memset (&state, '\0', sizeof (mbstate_t)); 3532 mbszero (&state);
3017# endif 3533# endif
3018 3534
3019 count = local_wcrtomb (cbuf, arg, &state); 3535 count = local_wcrtomb (cbuf, arg, &state);
3020 if (count <= 0) 3536 if (count < 0)
3021 /* Inconsistency. */ 3537 /* Cannot convert. */
3022 abort (); 3538 goto fail_with_EILSEQ;
3023 ENSURE_ALLOCATION (xsum (length, count)); 3539 ENSURE_ALLOCATION (xsum (length, count));
3024 memcpy (result + length, cbuf, count); 3540 memcpy (result + length, cbuf, count);
3025 length += count; 3541 length += count;
3026 }
3027 } 3542 }
3028# else 3543# else
3029 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len), 3544 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
@@ -3033,7 +3548,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3033 length += tmpdst_len; 3548 length += tmpdst_len;
3034# endif 3549# endif
3035 3550
3036 if (w < width && (dp->flags & FLAG_LEFT)) 3551 if (w < width && (flags & FLAG_LEFT))
3037 { 3552 {
3038 size_t n = width - w; 3553 size_t n = width - w;
3039 ENSURE_ALLOCATION (xsum (length, n)); 3554 ENSURE_ALLOCATION (xsum (length, n));
@@ -3043,14 +3558,399 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3043 } 3558 }
3044 } 3559 }
3045#endif 3560#endif
3046#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL 3561#if NEED_WPRINTF_DIRECTIVE_C && WIDE_CHAR_VERSION
3562 else if (dp->conversion == 'c'
3563 && a.arg[dp->arg_index].type != TYPE_WIDE_CHAR)
3564 {
3565 /* Implement the 'c' directive ourselves, in order to avoid
3566 EILSEQ in the "C" locale. */
3567 int flags = dp->flags;
3568 size_t width;
3569
3570 width = 0;
3571 if (dp->width_start != dp->width_end)
3572 {
3573 if (dp->width_arg_index != ARG_NONE)
3574 {
3575 int arg;
3576
3577 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3578 abort ();
3579 arg = a.arg[dp->width_arg_index].a.a_int;
3580 width = arg;
3581 if (arg < 0)
3582 {
3583 /* "A negative field width is taken as a '-' flag
3584 followed by a positive field width." */
3585 flags |= FLAG_LEFT;
3586 width = -width;
3587 }
3588 }
3589 else
3590 {
3591 const FCHAR_T *digitp = dp->width_start;
3592
3593 do
3594 width = xsum (xtimes (width, 10), *digitp++ - '0');
3595 while (digitp != dp->width_end);
3596 }
3597 }
3598
3599 /* %c in vasnwprintf. See the specification of fwprintf. */
3600 {
3601 char arg = (char) a.arg[dp->arg_index].a.a_char;
3602 mbstate_t state;
3603 wchar_t wc;
3604
3605 mbszero (&state);
3606 int count = mbrtowc (&wc, &arg, 1, &state);
3607 if (count < 0)
3608 /* Invalid or incomplete multibyte character. */
3609 goto fail_with_EILSEQ;
3610
3611 if (1 < width && !(flags & FLAG_LEFT))
3612 {
3613 size_t n = width - 1;
3614 ENSURE_ALLOCATION (xsum (length, n));
3615 DCHAR_SET (result + length, ' ', n);
3616 length += n;
3617 }
3618
3619 ENSURE_ALLOCATION (xsum (length, 1));
3620 result[length++] = wc;
3621
3622 if (1 < width && (flags & FLAG_LEFT))
3623 {
3624 size_t n = width - 1;
3625 ENSURE_ALLOCATION (xsum (length, n));
3626 DCHAR_SET (result + length, ' ', n);
3627 length += n;
3628 }
3629 }
3630 }
3631#endif
3632#if NEED_PRINTF_DIRECTIVE_B || NEED_PRINTF_DIRECTIVE_UPPERCASE_B
3633 else if (0
3634# if NEED_PRINTF_DIRECTIVE_B
3635 || (dp->conversion == 'b')
3636# endif
3637# if NEED_PRINTF_DIRECTIVE_UPPERCASE_B
3638 || (dp->conversion == 'B')
3639# endif
3640 )
3641 {
3642 arg_type type = a.arg[dp->arg_index].type;
3643 int flags = dp->flags;
3644 int has_width;
3645 size_t width;
3646 int has_precision;
3647 size_t precision;
3648 size_t tmp_length;
3649 size_t count;
3650 DCHAR_T tmpbuf[700];
3651 DCHAR_T *tmp;
3652 DCHAR_T *tmp_end;
3653 DCHAR_T *tmp_start;
3654 DCHAR_T *pad_ptr;
3655 DCHAR_T *p;
3656
3657 has_width = 0;
3658 width = 0;
3659 if (dp->width_start != dp->width_end)
3660 {
3661 if (dp->width_arg_index != ARG_NONE)
3662 {
3663 int arg;
3664
3665 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3666 abort ();
3667 arg = a.arg[dp->width_arg_index].a.a_int;
3668 width = arg;
3669 if (arg < 0)
3670 {
3671 /* "A negative field width is taken as a '-' flag
3672 followed by a positive field width." */
3673 flags |= FLAG_LEFT;
3674 width = -width;
3675 }
3676 }
3677 else
3678 {
3679 const FCHAR_T *digitp = dp->width_start;
3680
3681 do
3682 width = xsum (xtimes (width, 10), *digitp++ - '0');
3683 while (digitp != dp->width_end);
3684 }
3685 has_width = 1;
3686 }
3687
3688 has_precision = 0;
3689 precision = 1;
3690 if (dp->precision_start != dp->precision_end)
3691 {
3692 if (dp->precision_arg_index != ARG_NONE)
3693 {
3694 int arg;
3695
3696 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
3697 abort ();
3698 arg = a.arg[dp->precision_arg_index].a.a_int;
3699 /* "A negative precision is taken as if the precision
3700 were omitted." */
3701 if (arg >= 0)
3702 {
3703 precision = arg;
3704 has_precision = 1;
3705 }
3706 }
3707 else
3708 {
3709 const FCHAR_T *digitp = dp->precision_start + 1;
3710
3711 precision = 0;
3712 while (digitp != dp->precision_end)
3713 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
3714 has_precision = 1;
3715 }
3716 }
3717
3718 /* Allocate a temporary buffer of sufficient size. */
3719 switch (type)
3720 {
3721 default:
3722 tmp_length =
3723 (unsigned int) (sizeof (unsigned int) * CHAR_BIT)
3724 + 1; /* turn floor into ceil */
3725 break;
3726 case TYPE_ULONGINT:
3727 tmp_length =
3728 (unsigned int) (sizeof (unsigned long int) * CHAR_BIT)
3729 + 1; /* turn floor into ceil */
3730 break;
3731 case TYPE_ULONGLONGINT:
3732 tmp_length =
3733 (unsigned int) (sizeof (unsigned long long int) * CHAR_BIT)
3734 + 1; /* turn floor into ceil */
3735 break;
3736 case TYPE_UINT8_T:
3737 tmp_length =
3738 (unsigned int) (sizeof (uint8_t) * CHAR_BIT)
3739 + 1; /* turn floor into ceil */
3740 break;
3741 case TYPE_UINT16_T:
3742 tmp_length =
3743 (unsigned int) (sizeof (uint16_t) * CHAR_BIT)
3744 + 1; /* turn floor into ceil */
3745 break;
3746 case TYPE_UINT32_T:
3747 tmp_length =
3748 (unsigned int) (sizeof (uint32_t) * CHAR_BIT)
3749 + 1; /* turn floor into ceil */
3750 break;
3751 case TYPE_UINT64_T:
3752 tmp_length =
3753 (unsigned int) (sizeof (uint64_t) * CHAR_BIT)
3754 + 1; /* turn floor into ceil */
3755 break;
3756 case TYPE_UINT_FAST8_T:
3757 tmp_length =
3758 (unsigned int) (sizeof (uint_fast8_t) * CHAR_BIT)
3759 + 1; /* turn floor into ceil */
3760 break;
3761 case TYPE_UINT_FAST16_T:
3762 tmp_length =
3763 (unsigned int) (sizeof (uint_fast16_t) * CHAR_BIT)
3764 + 1; /* turn floor into ceil */
3765 break;
3766 case TYPE_UINT_FAST32_T:
3767 tmp_length =
3768 (unsigned int) (sizeof (uint_fast32_t) * CHAR_BIT)
3769 + 1; /* turn floor into ceil */
3770 break;
3771 case TYPE_UINT_FAST64_T:
3772 tmp_length =
3773 (unsigned int) (sizeof (uint_fast64_t) * CHAR_BIT)
3774 + 1; /* turn floor into ceil */
3775 break;
3776 }
3777 if (tmp_length < precision)
3778 tmp_length = precision;
3779 /* Add 2, to account for a prefix from the alternate form. */
3780 tmp_length = xsum (tmp_length, 2);
3781
3782 if (tmp_length < width)
3783 tmp_length = width;
3784
3785 if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
3786 tmp = tmpbuf;
3787 else
3788 {
3789 size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
3790
3791 if (size_overflow_p (tmp_memsize))
3792 /* Overflow, would lead to out of memory. */
3793 goto out_of_memory;
3794 tmp = (DCHAR_T *) malloc (tmp_memsize);
3795 if (tmp == NULL)
3796 /* Out of memory. */
3797 goto out_of_memory;
3798 }
3799
3800 tmp_end = tmp + tmp_length;
3801
3802 unsigned long long arg;
3803 switch (type)
3804 {
3805 case TYPE_UCHAR:
3806 arg = a.arg[dp->arg_index].a.a_uchar;
3807 break;
3808 case TYPE_USHORT:
3809 arg = a.arg[dp->arg_index].a.a_ushort;
3810 break;
3811 case TYPE_UINT:
3812 arg = a.arg[dp->arg_index].a.a_uint;
3813 break;
3814 case TYPE_ULONGINT:
3815 arg = a.arg[dp->arg_index].a.a_ulongint;
3816 break;
3817 case TYPE_ULONGLONGINT:
3818 arg = a.arg[dp->arg_index].a.a_ulonglongint;
3819 break;
3820 case TYPE_UINT8_T:
3821 arg = a.arg[dp->arg_index].a.a_uint8_t;
3822 break;
3823 case TYPE_UINT16_T:
3824 arg = a.arg[dp->arg_index].a.a_uint16_t;
3825 break;
3826 case TYPE_UINT32_T:
3827 arg = a.arg[dp->arg_index].a.a_uint32_t;
3828 break;
3829 case TYPE_UINT64_T:
3830 arg = a.arg[dp->arg_index].a.a_uint64_t;
3831 break;
3832 case TYPE_UINT_FAST8_T:
3833 arg = a.arg[dp->arg_index].a.a_uint_fast8_t;
3834 break;
3835 case TYPE_UINT_FAST16_T:
3836 arg = a.arg[dp->arg_index].a.a_uint_fast16_t;
3837 break;
3838 case TYPE_UINT_FAST32_T:
3839 arg = a.arg[dp->arg_index].a.a_uint_fast32_t;
3840 break;
3841 case TYPE_UINT_FAST64_T:
3842 arg = a.arg[dp->arg_index].a.a_uint_fast64_t;
3843 break;
3844 default:
3845 abort ();
3846 }
3847 int need_prefix = ((flags & FLAG_ALT) && arg != 0);
3848
3849 p = tmp_end;
3850 /* "The result of converting a zero value with a precision
3851 of zero is no characters." */
3852 if (!(has_precision && precision == 0 && arg == 0))
3853 {
3854 do
3855 {
3856 *--p = '0' + (arg & 1);
3857 arg = arg >> 1;
3858 }
3859 while (arg != 0);
3860 }
3861
3862 if (has_precision)
3863 {
3864 DCHAR_T *digits_start = tmp_end - precision;
3865 while (p > digits_start)
3866 *--p = '0';
3867 }
3868
3869 pad_ptr = p;
3870
3871 if (need_prefix)
3872 {
3873# if NEED_PRINTF_DIRECTIVE_B && !NEED_PRINTF_DIRECTIVE_UPPERCASE_B
3874 *--p = 'b';
3875# elif NEED_PRINTF_DIRECTIVE_UPPERCASE_B && !NEED_PRINTF_DIRECTIVE_B
3876 *--p = 'B';
3877# else
3878 *--p = dp->conversion;
3879# endif
3880 *--p = '0';
3881 }
3882 tmp_start = p;
3883
3884 /* The generated string now extends from tmp_start to tmp_end,
3885 with the zero padding insertion point being at pad_ptr,
3886 tmp_start <= pad_ptr <= tmp_end. */
3887 count = tmp_end - tmp_start;
3888
3889 if (count < width)
3890 {
3891 size_t pad = width - count;
3892
3893 if (flags & FLAG_LEFT)
3894 {
3895 /* Pad with spaces on the right. */
3896 for (p = tmp_start; p < tmp_end; p++)
3897 *(p - pad) = *p;
3898 for (p = tmp_end - pad; p < tmp_end; p++)
3899 *p = ' ';
3900 }
3901 else if ((flags & FLAG_ZERO)
3902 /* Neither ISO C nor POSIX specify that the '0'
3903 flag is ignored when a width and a precision
3904 are both present. But most implementations
3905 do so. */
3906 && !(has_width && has_precision))
3907 {
3908 /* Pad with zeroes. */
3909 for (p = tmp_start; p < pad_ptr; p++)
3910 *(p - pad) = *p;
3911 for (p = pad_ptr - pad; p < pad_ptr; p++)
3912 *p = '0';
3913 }
3914 else
3915 {
3916 /* Pad with spaces on the left. */
3917 for (p = tmp_start - pad; p < tmp_start; p++)
3918 *p = ' ';
3919 }
3920
3921 tmp_start = tmp_start - pad;
3922 }
3923
3924 count = tmp_end - tmp_start;
3925
3926 if (count > tmp_length)
3927 /* tmp_length was incorrectly calculated - fix the
3928 code above! */
3929 abort ();
3930
3931 /* Make room for the result. */
3932 if (count >= allocated - length)
3933 {
3934 size_t n = xsum (length, count);
3935
3936 ENSURE_ALLOCATION (n);
3937 }
3938
3939 /* Append the result. */
3940 memcpy (result + length, tmp_start, count * sizeof (DCHAR_T));
3941 if (tmp != tmpbuf)
3942 free (tmp);
3943 length += count;
3944 }
3945#endif
3946#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
3047 else if ((dp->conversion == 'a' || dp->conversion == 'A') 3947 else if ((dp->conversion == 'a' || dp->conversion == 'A')
3048# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE)) 3948# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
3049 && (0 3949 && (0
3050# if NEED_PRINTF_DOUBLE 3950# if NEED_PRINTF_DOUBLE
3051 || a.arg[dp->arg_index].type == TYPE_DOUBLE 3951 || a.arg[dp->arg_index].type == TYPE_DOUBLE
3052# endif 3952# endif
3053# if NEED_PRINTF_LONG_DOUBLE 3953# if NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
3054 || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE 3954 || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
3055# endif 3955# endif
3056 ) 3956 )
@@ -3170,7 +4070,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3170 p = tmp; 4070 p = tmp;
3171 if (type == TYPE_LONGDOUBLE) 4071 if (type == TYPE_LONGDOUBLE)
3172 { 4072 {
3173# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE 4073# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
3174 long double arg = a.arg[dp->arg_index].a.a_longdouble; 4074 long double arg = a.arg[dp->arg_index].a.a_longdouble;
3175 4075
3176 if (isnanl (arg)) 4076 if (isnanl (arg))
@@ -3290,7 +4190,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3290 } 4190 }
3291 } 4191 }
3292 *p++ = dp->conversion - 'A' + 'P'; 4192 *p++ = dp->conversion - 'A' + 'P';
3293# if WIDE_CHAR_VERSION 4193# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
3294 { 4194 {
3295 static const wchar_t decimal_format[] = 4195 static const wchar_t decimal_format[] =
3296 { '%', '+', 'd', '\0' }; 4196 { '%', '+', 'd', '\0' };
@@ -3441,7 +4341,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3441 } 4341 }
3442 } 4342 }
3443 *p++ = dp->conversion - 'A' + 'P'; 4343 *p++ = dp->conversion - 'A' + 'P';
3444# if WIDE_CHAR_VERSION 4344# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
3445 { 4345 {
3446 static const wchar_t decimal_format[] = 4346 static const wchar_t decimal_format[] =
3447 { '%', '+', 'd', '\0' }; 4347 { '%', '+', 'd', '\0' };
@@ -3533,7 +4433,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3533 length += count; 4433 length += count;
3534 } 4434 }
3535#endif 4435#endif
3536#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL 4436#if NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE
3537 else if ((dp->conversion == 'f' || dp->conversion == 'F' 4437 else if ((dp->conversion == 'f' || dp->conversion == 'F'
3538 || dp->conversion == 'e' || dp->conversion == 'E' 4438 || dp->conversion == 'e' || dp->conversion == 'E'
3539 || dp->conversion == 'g' || dp->conversion == 'G' 4439 || dp->conversion == 'g' || dp->conversion == 'G'
@@ -3901,7 +4801,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3901 } 4801 }
3902 4802
3903 *p++ = dp->conversion; /* 'e' or 'E' */ 4803 *p++ = dp->conversion; /* 'e' or 'E' */
3904# if WIDE_CHAR_VERSION 4804# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
3905 { 4805 {
3906 static const wchar_t decimal_format[] = 4806 static const wchar_t decimal_format[] =
3907 { '%', '+', '.', '2', 'd', '\0' }; 4807 { '%', '+', '.', '2', 'd', '\0' };
@@ -4082,7 +4982,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4082 } 4982 }
4083 } 4983 }
4084 *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */ 4984 *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
4085# if WIDE_CHAR_VERSION 4985# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
4086 { 4986 {
4087 static const wchar_t decimal_format[] = 4987 static const wchar_t decimal_format[] =
4088 { '%', '+', '.', '2', 'd', '\0' }; 4988 { '%', '+', '.', '2', 'd', '\0' };
@@ -4359,7 +5259,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4359 } 5259 }
4360 5260
4361 *p++ = dp->conversion; /* 'e' or 'E' */ 5261 *p++ = dp->conversion; /* 'e' or 'E' */
4362# if WIDE_CHAR_VERSION 5262# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
4363 { 5263 {
4364 static const wchar_t decimal_format[] = 5264 static const wchar_t decimal_format[] =
4365 /* Produce the same number of exponent digits 5265 /* Produce the same number of exponent digits
@@ -4552,7 +5452,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4552 } 5452 }
4553 } 5453 }
4554 *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */ 5454 *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
4555# if WIDE_CHAR_VERSION 5455# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
4556 { 5456 {
4557 static const wchar_t decimal_format[] = 5457 static const wchar_t decimal_format[] =
4558 /* Produce the same number of exponent digits 5458 /* Produce the same number of exponent digits
@@ -4720,24 +5620,24 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4720 { 5620 {
4721 arg_type type = a.arg[dp->arg_index].type; 5621 arg_type type = a.arg[dp->arg_index].type;
4722 int flags = dp->flags; 5622 int flags = dp->flags;
4723#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION 5623#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4724 int has_width; 5624 int has_width;
4725#endif 5625#endif
4726#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION 5626#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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4727 size_t width; 5627 size_t width;
4728#endif 5628#endif
4729#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION 5629#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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4730 int has_precision; 5630 int has_precision;
4731 size_t precision; 5631 size_t precision;
4732#endif 5632#endif
4733#if NEED_PRINTF_UNBOUNDED_PRECISION 5633#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4734 int prec_ourselves; 5634 int prec_ourselves;
4735#else 5635#else
4736# define prec_ourselves 0 5636# define prec_ourselves 0
4737#endif 5637#endif
4738#if NEED_PRINTF_FLAG_LEFTADJUST 5638#if (WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST
4739# define pad_ourselves 1 5639# define pad_ourselves 1
4740#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION 5640#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4741 int pad_ourselves; 5641 int pad_ourselves;
4742#else 5642#else
4743# define pad_ourselves 0 5643# define pad_ourselves 0
@@ -4752,10 +5652,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4752 TCHAR_T *tmp; 5652 TCHAR_T *tmp;
4753#endif 5653#endif
4754 5654
4755#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION 5655#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4756 has_width = 0; 5656 has_width = 0;
4757#endif 5657#endif
4758#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION 5658#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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4759 width = 0; 5659 width = 0;
4760 if (dp->width_start != dp->width_end) 5660 if (dp->width_start != dp->width_end)
4761 { 5661 {
@@ -4783,13 +5683,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4783 width = xsum (xtimes (width, 10), *digitp++ - '0'); 5683 width = xsum (xtimes (width, 10), *digitp++ - '0');
4784 while (digitp != dp->width_end); 5684 while (digitp != dp->width_end);
4785 } 5685 }
4786#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION 5686# if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4787 has_width = 1; 5687 has_width = 1;
4788#endif 5688# endif
4789 } 5689 }
4790#endif 5690#endif
4791 5691
4792#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION 5692#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_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4793 has_precision = 0; 5693 has_precision = 0;
4794 precision = 6; 5694 precision = 6;
4795 if (dp->precision_start != dp->precision_end) 5695 if (dp->precision_start != dp->precision_end)
@@ -4822,14 +5722,32 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4822#endif 5722#endif
4823 5723
4824 /* Decide whether to handle the precision ourselves. */ 5724 /* Decide whether to handle the precision ourselves. */
4825#if NEED_PRINTF_UNBOUNDED_PRECISION 5725#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4826 switch (dp->conversion) 5726 switch (dp->conversion)
4827 { 5727 {
5728# if NEED_PRINTF_UNBOUNDED_PRECISION
4828 case 'd': case 'i': case 'u': 5729 case 'd': case 'i': case 'u':
5730 case 'b':
5731 #if SUPPORT_GNU_PRINTF_DIRECTIVES \
5732 || (__GLIBC__ + (__GLIBC_MINOR__ >= 35) > 2)
5733 case 'B':
5734 #endif
4829 case 'o': 5735 case 'o':
4830 case 'x': case 'X': case 'p':
4831 prec_ourselves = has_precision && (precision > 0); 5736 prec_ourselves = has_precision && (precision > 0);
4832 break; 5737 break;
5738# endif
5739 case 'x': case 'X': case 'p':
5740 prec_ourselves =
5741 has_precision
5742 && (0
5743# if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO
5744 || (precision == 0)
5745# endif
5746# if NEED_PRINTF_UNBOUNDED_PRECISION
5747 || (precision > 0)
5748# endif
5749 );
5750 break;
4833 default: 5751 default:
4834 prec_ourselves = 0; 5752 prec_ourselves = 0;
4835 break; 5753 break;
@@ -4837,7 +5755,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4837#endif 5755#endif
4838 5756
4839 /* Decide whether to perform the padding ourselves. */ 5757 /* Decide whether to perform the padding ourselves. */
4840#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION) 5758#if !((WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST) && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
4841 switch (dp->conversion) 5759 switch (dp->conversion)
4842 { 5760 {
4843# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO 5761# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
@@ -4956,6 +5874,54 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4956 { 5874 {
4957 case TYPE_LONGLONGINT: 5875 case TYPE_LONGLONGINT:
4958 case TYPE_ULONGLONGINT: 5876 case TYPE_ULONGLONGINT:
5877 #if INT8_WIDTH > LONG_WIDTH
5878 case TYPE_INT8_T:
5879 #endif
5880 #if UINT8_WIDTH > LONG_WIDTH
5881 case TYPE_UINT8_T:
5882 #endif
5883 #if INT16_WIDTH > LONG_WIDTH
5884 case TYPE_INT16_T:
5885 #endif
5886 #if UINT16_WIDTH > LONG_WIDTH
5887 case TYPE_UINT16_T:
5888 #endif
5889 #if INT32_WIDTH > LONG_WIDTH
5890 case TYPE_INT32_T:
5891 #endif
5892 #if UINT32_WIDTH > LONG_WIDTH
5893 case TYPE_UINT32_T:
5894 #endif
5895 #if INT64_WIDTH > LONG_WIDTH
5896 case TYPE_INT64_T:
5897 #endif
5898 #if UINT64_WIDTH > LONG_WIDTH
5899 case TYPE_UINT64_T:
5900 #endif
5901 #if INT_FAST8_WIDTH > LONG_WIDTH
5902 case TYPE_INT_FAST8_T:
5903 #endif
5904 #if UINT_FAST8_WIDTH > LONG_WIDTH
5905 case TYPE_UINT_FAST8_T:
5906 #endif
5907 #if INT_FAST16_WIDTH > LONG_WIDTH
5908 case TYPE_INT_FAST16_T:
5909 #endif
5910 #if UINT_FAST16_WIDTH > LONG_WIDTH
5911 case TYPE_UINT_FAST16_T:
5912 #endif
5913 #if INT_FAST32_WIDTH > LONG_WIDTH
5914 case TYPE_INT3_FAST2_T:
5915 #endif
5916 #if UINT_FAST32_WIDTH > LONG_WIDTH
5917 case TYPE_UINT_FAST32_T:
5918 #endif
5919 #if INT_FAST64_WIDTH > LONG_WIDTH
5920 case TYPE_INT_FAST64_T:
5921 #endif
5922 #if UINT_FAST64_WIDTH > LONG_WIDTH
5923 case TYPE_UINT_FAST64_T:
5924 #endif
4959#if defined _WIN32 && ! defined __CYGWIN__ 5925#if defined _WIN32 && ! defined __CYGWIN__
4960 *fbp++ = 'I'; 5926 *fbp++ = 'I';
4961 *fbp++ = '6'; 5927 *fbp++ = '6';
@@ -4967,12 +5933,60 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4967 FALLTHROUGH; 5933 FALLTHROUGH;
4968 case TYPE_LONGINT: 5934 case TYPE_LONGINT:
4969 case TYPE_ULONGINT: 5935 case TYPE_ULONGINT:
4970#if HAVE_WINT_T 5936 #if INT8_WIDTH > INT_WIDTH && INT8_WIDTH <= LONG_WIDTH
5937 case TYPE_INT8_T:
5938 #endif
5939 #if UINT8_WIDTH > INT_WIDTH && UINT8_WIDTH <= LONG_WIDTH
5940 case TYPE_UINT8_T:
5941 #endif
5942 #if INT16_WIDTH > INT_WIDTH && INT16_WIDTH <= LONG_WIDTH
5943 case TYPE_INT16_T:
5944 #endif
5945 #if UINT16_WIDTH > INT_WIDTH && UINT16_WIDTH <= LONG_WIDTH
5946 case TYPE_UINT16_T:
5947 #endif
5948 #if INT32_WIDTH > INT_WIDTH && INT32_WIDTH <= LONG_WIDTH
5949 case TYPE_INT32_T:
5950 #endif
5951 #if UINT32_WIDTH > INT_WIDTH && UINT32_WIDTH <= LONG_WIDTH
5952 case TYPE_UINT32_T:
5953 #endif
5954 #if INT64_WIDTH > INT_WIDTH && INT64_WIDTH <= LONG_WIDTH
5955 case TYPE_INT64_T:
5956 #endif
5957 #if UINT64_WIDTH > INT_WIDTH && UINT64_WIDTH <= LONG_WIDTH
5958 case TYPE_UINT64_T:
5959 #endif
5960 #if INT_FAST8_WIDTH > INT_WIDTH && INT_FAST8_WIDTH <= LONG_WIDTH
5961 case TYPE_INT_FAST8_T:
5962 #endif
5963 #if UINT_FAST8_WIDTH > INT_WIDTH && UINT_FAST8_WIDTH <= LONG_WIDTH
5964 case TYPE_UINT_FAST8_T:
5965 #endif
5966 #if INT_FAST16_WIDTH > INT_WIDTH && INT_FAST16_WIDTH <= LONG_WIDTH
5967 case TYPE_INT_FAST16_T:
5968 #endif
5969 #if UINT_FAST16_WIDTH > INT_WIDTH && UINT_FAST16_WIDTH <= LONG_WIDTH
5970 case TYPE_UINT_FAST16_T:
5971 #endif
5972 #if INT_FAST32_WIDTH > INT_WIDTH && INT_FAST32_WIDTH <= LONG_WIDTH
5973 case TYPE_INT_FAST32_T:
5974 #endif
5975 #if UINT_FAST32_WIDTH > INT_WIDTH && UINT_FAST32_WIDTH <= LONG_WIDTH
5976 case TYPE_UINT_FAST32_T:
5977 #endif
5978 #if INT_FAST64_WIDTH > INT_WIDTH && INT_FAST64_WIDTH <= LONG_WIDTH
5979 case TYPE_INT_FAST64_T:
5980 #endif
5981 #if UINT_FAST64_WIDTH > INT_WIDTH && UINT_FAST64_WIDTH <= LONG_WIDTH
5982 case TYPE_UINT_FAST64_T:
5983 #endif
5984 #if HAVE_WINT_T
4971 case TYPE_WIDE_CHAR: 5985 case TYPE_WIDE_CHAR:
4972#endif 5986 #endif
4973#if HAVE_WCHAR_T 5987 #if HAVE_WCHAR_T
4974 case TYPE_WIDE_STRING: 5988 case TYPE_WIDE_STRING:
4975#endif 5989 #endif
4976 *fbp++ = 'l'; 5990 *fbp++ = 'l';
4977 break; 5991 break;
4978 case TYPE_LONGDOUBLE: 5992 case TYPE_LONGDOUBLE:
@@ -4988,47 +6002,74 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4988#endif 6002#endif
4989 *fbp = dp->conversion; 6003 *fbp = dp->conversion;
4990#if USE_SNPRINTF 6004#if USE_SNPRINTF
4991# if ((HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99) \ 6005 /* Decide whether to pass %n in the format string
6006 to SNPRINTF. */
6007# if (((!WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR) \
6008 && (HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99)) \
4992 || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) \ 6009 || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) \
4993 && !defined __UCLIBC__) \ 6010 && !defined __UCLIBC__) \
4994 || (defined __APPLE__ && defined __MACH__) \ 6011 || (defined __APPLE__ && defined __MACH__) \
6012 || defined __OpenBSD__ \
4995 || defined __ANDROID__ \ 6013 || defined __ANDROID__ \
4996 || (defined _WIN32 && ! defined __CYGWIN__)) 6014 || (defined _WIN32 && ! defined __CYGWIN__)) \
4997 /* On systems where we know that snprintf's return value 6015 || (WIDE_CHAR_VERSION && MUSL_LIBC)
4998 conforms to ISO C 99 (HAVE_SNPRINTF_RETVAL_C99) and that 6016 /* We can avoid passing %n and instead rely on SNPRINTF's
4999 snprintf always produces NUL-terminated strings 6017 return value if
5000 (HAVE_SNPRINTF_TRUNCATION_C99), it is possible to avoid 6018 - !WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR, because otherwise,
5001 using %n. And it is desirable to do so, because more and 6019 when WIDE_CHAR_VERSION && DCHAR_IS_TCHAR,
5002 more platforms no longer support %n, for "security reasons". 6020 snwprintf()/_snwprintf() (Windows) and swprintf() (Unix)
5003 In particular, the following platforms: 6021 don't return the needed buffer size,
6022 and
6023 - we're compiling for a system where we know
6024 - that snprintf's return value conforms to ISO C 99
6025 (HAVE_SNPRINTF_RETVAL_C99) and
6026 - that snprintf always produces NUL-terminated strings
6027 (HAVE_SNPRINTF_TRUNCATION_C99).
6028 And it is desirable to do so, because more and more platforms
6029 no longer support %n, for "security reasons". */
6030 /* On specific platforms, listed below, we *must* avoid %n.
6031 In the case
6032 !WIDE_CHAR_VERSION && HAVE_SNPRINTF_RETVAL_C99 && !USE_MSVC__SNPRINTF
6033 we can rely on the return value of snprintf instead. Whereas
6034 in the opposite case
6035 WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
6036 we need to make room based on an estimation, computed by
6037 MAX_ROOM_NEEDED. */
6038 /* The following platforms forbid %n:
5004 - On glibc2 systems from 2004-10-18 or newer, the use of 6039 - On glibc2 systems from 2004-10-18 or newer, the use of
5005 %n in format strings in writable memory may crash the 6040 %n in format strings in writable memory may crash the
5006 program (if compiled with _FORTIFY_SOURCE=2). 6041 program (if compiled with _FORTIFY_SOURCE=2).
5007 - On Mac OS X 10.13 or newer, the use of %n in format 6042 - On macOS 10.13 or newer, the use of %n in format
5008 strings in writable memory by default crashes the 6043 strings in writable memory by default crashes the
5009 program. 6044 program.
6045 - On OpenBSD, since 2021-08-30, the use of %n in format
6046 strings produces an abort (see
6047 <https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/vfprintf.c.diff?r1=1.79&r2=1.80&f=h>,
6048 <https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/vfwprintf.c.diff?r1=1.20&r2=1.21&f=h>).
5010 - On Android, starting on 2018-03-07, the use of %n in 6049 - On Android, starting on 2018-03-07, the use of %n in
5011 format strings produces a fatal error (see 6050 format strings produces a fatal error (see
5012 <https://android.googlesource.com/platform/bionic/+/41398d03b7e8e0dfb951660ae713e682e9fc0336>). 6051 <https://android.googlesource.com/platform/bionic/+/41398d03b7e8e0dfb951660ae713e682e9fc0336>).
5013 On these platforms, HAVE_SNPRINTF_RETVAL_C99 and 6052 - On native Windows systems (such as mingw) where the OS is
5014 HAVE_SNPRINTF_TRUNCATION_C99 are 1. We have listed them 6053 Windows Vista, the use of %n in format strings by default
5015 explicitly in the condition above, in case of cross- 6054 crashes the program. See
5016 compilation (just to be sure). */ 6055 <https://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
5017 /* On native Windows systems (such as mingw), we can avoid using 6056 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/set-printf-count-output>
5018 %n because: 6057 On the first four of these platforms, if !WIDE_CHAR_VERSION,
6058 it is not a big deal to avoid %n, because on these platforms,
6059 HAVE_SNPRINTF_RETVAL_C99 and HAVE_SNPRINTF_TRUNCATION_C99 are
6060 1.
6061 On native Windows, if !WIDE_CHAR_VERSION, it's not a big deal
6062 either because:
5019 - Although the gl_SNPRINTF_TRUNCATION_C99 test fails, 6063 - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
5020 snprintf does not write more than the specified number 6064 snprintf does not write more than the specified number
5021 of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes 6065 of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
5022 '4', '5', '6' into buf, not '4', '5', '\0'.) 6066 '4', '5', '6' into buf, not '4', '5', '\0'.)
5023 - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf 6067 - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
5024 allows us to recognize the case of an insufficient 6068 allows us to recognize the case of an insufficient
5025 buffer size: it returns -1 in this case. 6069 buffer size: it returns -1 in this case. */
5026 On native Windows systems (such as mingw) where the OS is 6070 /* Additionally, in the WIDE_CHAR_VERSION case, we cannot use %n
5027 Windows Vista, the use of %n in format strings by default 6071 on musl libc because we would run into an swprintf() bug.
5028 crashes the program. See 6072 See <https://www.openwall.com/lists/musl/2023/03/19/1>. */
5029 <https://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
5030 <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/set-printf-count-output>
5031 So we should avoid %n in this situation. */
5032 fbp[1] = '\0'; 6073 fbp[1] = '\0';
5033# else /* AIX <= 5.1, HP-UX, IRIX, OSF/1, Solaris <= 9, BeOS */ 6074# else /* AIX <= 5.1, HP-UX, IRIX, OSF/1, Solaris <= 9, BeOS */
5034 fbp[1] = '%'; 6075 fbp[1] = '%';
@@ -5189,6 +6230,102 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5189 SNPRINTF_BUF (arg); 6230 SNPRINTF_BUF (arg);
5190 } 6231 }
5191 break; 6232 break;
6233 case TYPE_INT8_T:
6234 {
6235 int8_t arg = a.arg[dp->arg_index].a.a_int8_t;
6236 SNPRINTF_BUF (arg);
6237 }
6238 break;
6239 case TYPE_UINT8_T:
6240 {
6241 uint8_t arg = a.arg[dp->arg_index].a.a_uint8_t;
6242 SNPRINTF_BUF (arg);
6243 }
6244 break;
6245 case TYPE_INT16_T:
6246 {
6247 int16_t arg = a.arg[dp->arg_index].a.a_int16_t;
6248 SNPRINTF_BUF (arg);
6249 }
6250 break;
6251 case TYPE_UINT16_T:
6252 {
6253 uint16_t arg = a.arg[dp->arg_index].a.a_uint16_t;
6254 SNPRINTF_BUF (arg);
6255 }
6256 break;
6257 case TYPE_INT32_T:
6258 {
6259 int32_t arg = a.arg[dp->arg_index].a.a_int32_t;
6260 SNPRINTF_BUF (arg);
6261 }
6262 break;
6263 case TYPE_UINT32_T:
6264 {
6265 uint32_t arg = a.arg[dp->arg_index].a.a_uint32_t;
6266 SNPRINTF_BUF (arg);
6267 }
6268 break;
6269 case TYPE_INT64_T:
6270 {
6271 int64_t arg = a.arg[dp->arg_index].a.a_int64_t;
6272 SNPRINTF_BUF (arg);
6273 }
6274 break;
6275 case TYPE_UINT64_T:
6276 {
6277 uint64_t arg = a.arg[dp->arg_index].a.a_uint64_t;
6278 SNPRINTF_BUF (arg);
6279 }
6280 break;
6281 case TYPE_INT_FAST8_T:
6282 {
6283 int_fast8_t arg = a.arg[dp->arg_index].a.a_int_fast8_t;
6284 SNPRINTF_BUF (arg);
6285 }
6286 break;
6287 case TYPE_UINT_FAST8_T:
6288 {
6289 uint_fast8_t arg = a.arg[dp->arg_index].a.a_uint_fast8_t;
6290 SNPRINTF_BUF (arg);
6291 }
6292 break;
6293 case TYPE_INT_FAST16_T:
6294 {
6295 int_fast16_t arg = a.arg[dp->arg_index].a.a_int_fast16_t;
6296 SNPRINTF_BUF (arg);
6297 }
6298 break;
6299 case TYPE_UINT_FAST16_T:
6300 {
6301 uint_fast16_t arg = a.arg[dp->arg_index].a.a_uint_fast16_t;
6302 SNPRINTF_BUF (arg);
6303 }
6304 break;
6305 case TYPE_INT_FAST32_T:
6306 {
6307 int_fast32_t arg = a.arg[dp->arg_index].a.a_int_fast32_t;
6308 SNPRINTF_BUF (arg);
6309 }
6310 break;
6311 case TYPE_UINT_FAST32_T:
6312 {
6313 uint_fast32_t arg = a.arg[dp->arg_index].a.a_uint_fast32_t;
6314 SNPRINTF_BUF (arg);
6315 }
6316 break;
6317 case TYPE_INT_FAST64_T:
6318 {
6319 int_fast64_t arg = a.arg[dp->arg_index].a.a_int_fast64_t;
6320 SNPRINTF_BUF (arg);
6321 }
6322 break;
6323 case TYPE_UINT_FAST64_T:
6324 {
6325 uint_fast64_t arg = a.arg[dp->arg_index].a.a_uint_fast64_t;
6326 SNPRINTF_BUF (arg);
6327 }
6328 break;
5192 case TYPE_DOUBLE: 6329 case TYPE_DOUBLE:
5193 { 6330 {
5194 double arg = a.arg[dp->arg_index].a.a_double; 6331 double arg = a.arg[dp->arg_index].a.a_double;
@@ -5271,12 +6408,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5271 /* Look at the snprintf() return value. */ 6408 /* Look at the snprintf() return value. */
5272 if (retcount < 0) 6409 if (retcount < 0)
5273 { 6410 {
5274# if !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF 6411# if (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
5275 /* HP-UX 10.20 snprintf() is doubly deficient: 6412 /* HP-UX 10.20 snprintf() is doubly deficient:
5276 It doesn't understand the '%n' directive, 6413 It doesn't understand the '%n' directive,
5277 *and* it returns -1 (rather than the length 6414 *and* it returns -1 (rather than the length
5278 that would have been required) when the 6415 that would have been required) when the
5279 buffer is too small. 6416 buffer is too small.
6417 Likewise, in case of
6418 WIDE_CHAR_VERSION && DCHAR_IS_TCHAR, the
6419 functions snwprintf()/_snwprintf() (Windows)
6420 or swprintf() (Unix).
5280 But a failure at this point can also come 6421 But a failure at this point can also come
5281 from other reasons than a too small buffer, 6422 from other reasons than a too small buffer,
5282 such as an invalid wide string argument to 6423 such as an invalid wide string argument to
@@ -5312,7 +6453,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5312# endif 6453# endif
5313 } 6454 }
5314 else 6455 else
5315 count = retcount; 6456 {
6457 count = retcount;
6458# if WIDE_CHAR_VERSION && defined __MINGW32__
6459 if (count == 0 && dp->conversion == 'c')
6460 /* snwprintf returned 0 instead of 1. But it
6461 wrote a null wide character. */
6462 count = 1;
6463# endif
6464 }
5316 } 6465 }
5317 } 6466 }
5318#endif 6467#endif
@@ -5370,7 +6519,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5370 } 6519 }
5371#endif 6520#endif
5372 6521
5373#if NEED_PRINTF_UNBOUNDED_PRECISION 6522#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
5374 if (prec_ourselves) 6523 if (prec_ourselves)
5375 { 6524 {
5376 /* Handle the precision. */ 6525 /* Handle the precision. */
@@ -5430,6 +6579,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5430 6579
5431 count += insert; 6580 count += insert;
5432 } 6581 }
6582# if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO
6583 else if (precision == 0
6584 && move == 1
6585 && prec_ptr[prefix_count] == '0')
6586 {
6587 /* Replace the "0" result with an empty string. */
6588 count = prefix_count;
6589 }
6590# endif
5433 } 6591 }
5434#endif 6592#endif
5435 6593
@@ -5442,11 +6600,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5442 6600
5443#if !DCHAR_IS_TCHAR 6601#if !DCHAR_IS_TCHAR
5444 /* Convert from TCHAR_T[] to DCHAR_T[]. */ 6602 /* Convert from TCHAR_T[] to DCHAR_T[]. */
5445 if (dp->conversion == 'c' || dp->conversion == 's') 6603 if (dp->conversion == 'c' || dp->conversion == 's'
6604# if __GLIBC__ >= 2 && !defined __UCLIBC__
6605 || (flags & FLAG_LOCALIZED)
6606# endif
6607 )
5446 { 6608 {
5447 /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING 6609 /* The result string is not guaranteed to be ASCII. */
5448 TYPE_WIDE_STRING.
5449 The result string is not certainly ASCII. */
5450 const TCHAR_T *tmpsrc; 6610 const TCHAR_T *tmpsrc;
5451 DCHAR_T *tmpdst; 6611 DCHAR_T *tmpdst;
5452 size_t tmpdst_len; 6612 size_t tmpdst_len;
@@ -5457,6 +6617,56 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5457# else 6617# else
5458 tmpsrc = tmp; 6618 tmpsrc = tmp;
5459# endif 6619# endif
6620# if WIDE_CHAR_VERSION
6621 /* Convert tmpsrc[0..count-1] to a freshly allocated
6622 wide character array. */
6623 mbstate_t state;
6624
6625 mbszero (&state);
6626 tmpdst_len = 0;
6627 {
6628 const TCHAR_T *src = tmpsrc;
6629 size_t srclen = count;
6630
6631 for (; srclen > 0; tmpdst_len++)
6632 {
6633 /* Parse the next multibyte character. */
6634 size_t ret = mbrtowc (NULL, src, srclen, &state);
6635 if (ret == (size_t)(-2) || ret == (size_t)(-1))
6636 goto fail_with_EILSEQ;
6637 if (ret == 0)
6638 ret = 1;
6639 src += ret;
6640 srclen -= ret;
6641 }
6642 }
6643
6644 tmpdst =
6645 (wchar_t *) malloc ((tmpdst_len + 1) * sizeof (wchar_t));
6646 if (tmpdst == NULL)
6647 goto out_of_memory;
6648
6649 mbszero (&state);
6650 {
6651 DCHAR_T *destptr = tmpdst;
6652 const TCHAR_T *src = tmpsrc;
6653 size_t srclen = count;
6654
6655 for (; srclen > 0; destptr++)
6656 {
6657 /* Parse the next multibyte character. */
6658 size_t ret = mbrtowc (destptr, src, srclen, &state);
6659 if (ret == (size_t)(-2) || ret == (size_t)(-1))
6660 /* Should already have been caught in the first
6661 loop, above. */
6662 abort ();
6663 if (ret == 0)
6664 ret = 1;
6665 src += ret;
6666 srclen -= ret;
6667 }
6668 }
6669# else
5460 tmpdst = 6670 tmpdst =
5461 DCHAR_CONV_FROM_ENCODING (locale_charset (), 6671 DCHAR_CONV_FROM_ENCODING (locale_charset (),
5462 iconveh_question_mark, 6672 iconveh_question_mark,
@@ -5465,6 +6675,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5465 NULL, &tmpdst_len); 6675 NULL, &tmpdst_len);
5466 if (tmpdst == NULL) 6676 if (tmpdst == NULL)
5467 goto fail_with_errno; 6677 goto fail_with_errno;
6678# endif
5468 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len), 6679 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
5469 { free (tmpdst); goto out_of_memory; }); 6680 { free (tmpdst); goto out_of_memory; });
5470 DCHAR_CPY (result + length, tmpdst, tmpdst_len); 6681 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
@@ -5531,7 +6742,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5531 /* Here count <= allocated - length. */ 6742 /* Here count <= allocated - length. */
5532 6743
5533 /* Perform padding. */ 6744 /* Perform padding. */
5534#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION 6745#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
5535 if (pad_ourselves && has_width) 6746 if (pad_ourselves && has_width)
5536 { 6747 {
5537 size_t w; 6748 size_t w;
@@ -5590,6 +6801,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5590 if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z') 6801 if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
5591 || (*pad_ptr >= 'a' && *pad_ptr <= 'z')) 6802 || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
5592 pad_ptr = NULL; 6803 pad_ptr = NULL;
6804 else
6805 /* Do the zero-padding after the "0x" or
6806 "0b" prefix, not before. */
6807 if (p - rp >= 2
6808 && *rp == '0'
6809 && (((dp->conversion == 'a'
6810 || dp->conversion == 'x')
6811 && rp[1] == 'x')
6812 || ((dp->conversion == 'A'
6813 || dp->conversion == 'X')
6814 && rp[1] == 'X')
6815 || (dp->conversion == 'b'
6816 && rp[1] == 'b')
6817 || (dp->conversion == 'B'
6818 && rp[1] == 'B')))
6819 pad_ptr += 2;
5593 } 6820 }
5594 /* The generated string now extends from rp to p, 6821 /* The generated string now extends from rp to p,
5595 with the zero padding insertion point being at 6822 with the zero padding insertion point being at
@@ -5603,7 +6830,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5603 for (; pad > 0; pad--) 6830 for (; pad > 0; pad--)
5604 *p++ = ' '; 6831 *p++ = ' ';
5605 } 6832 }
5606 else if ((flags & FLAG_ZERO) && pad_ptr != NULL) 6833 else if ((flags & FLAG_ZERO) && pad_ptr != NULL
6834 /* ISO C says: "For d, i, o, u, x, and X
6835 conversions, if a precision is
6836 specified, the 0 flag is ignored. */
6837 && !(has_precision
6838 && (dp->conversion == 'd'
6839 || dp->conversion == 'i'
6840 || dp->conversion == 'o'
6841 || dp->conversion == 'u'
6842 || dp->conversion == 'x'
6843 || dp->conversion == 'X'
6844 /* Although ISO C does not
6845 require it, treat 'b' and 'B'
6846 like 'x' and 'X'. */
6847 || dp->conversion == 'b'
6848 || dp->conversion == 'B')))
5607 { 6849 {
5608 /* Pad with zeroes. */ 6850 /* Pad with zeroes. */
5609 DCHAR_T *q = end; 6851 DCHAR_T *q = end;
@@ -5697,7 +6939,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5697 errno = ENOMEM; 6939 errno = ENOMEM;
5698 goto fail_with_errno; 6940 goto fail_with_errno;
5699 6941
5700#if ENABLE_UNISTDIO || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL) || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T) 6942#if ENABLE_UNISTDIO || ((!USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS || ENABLE_WCHAR_FALLBACK) && HAVE_WCHAR_T) || ((NEED_PRINTF_DIRECTIVE_LC || ENABLE_WCHAR_FALLBACK) && HAVE_WINT_T && !WIDE_CHAR_VERSION) || (NEED_WPRINTF_DIRECTIVE_C && WIDE_CHAR_VERSION)
5701 fail_with_EILSEQ: 6943 fail_with_EILSEQ:
5702 errno = EILSEQ; 6944 errno = EILSEQ;
5703 goto fail_with_errno; 6945 goto fail_with_errno;