diff options
Diffstat (limited to 'gl/vasnprintf.c')
-rw-r--r-- | gl/vasnprintf.c | 1668 |
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 |
288 | static size_t | 294 | static size_t |
289 | wctomb_fallback (char *s, wchar_t wc) | 295 | wctomb_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. */ |
384 | static int | 390 | static 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. */ |
395 | static int | 401 | static 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) | |||
1380 | static char * | 1396 | static char * |
1381 | scale10_round_decimal_long_double (long double x, int n) | 1397 | scale10_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) | |||
1398 | static char * | 1417 | static char * |
1399 | scale10_round_decimal_double (double x, int n) | 1418 | scale10_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; |