summaryrefslogtreecommitdiffstats
path: root/gl/vasnprintf.c
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-12-28 12:13:40 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-12-28 12:13:40 +0100
commitb0afb8fe0ff1d87165af9df61501197a06240dda (patch)
tree274ac6a96c53ef4c19ab4974ce24a06a233128c5 /gl/vasnprintf.c
parent68fc05381ee5fa0aee1413118fbb3d81ca888b09 (diff)
downloadmonitoring-plugins-b0afb8fe0ff1d87165af9df61501197a06240dda.tar.gz
Sync with Gnulib stable-202507 code (a8ac9f9ce5)
Diffstat (limited to 'gl/vasnprintf.c')
-rw-r--r--gl/vasnprintf.c1451
1 files changed, 1258 insertions, 193 deletions
diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c
index de204458..f46e8701 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-2024 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2002-2025 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
@@ -29,6 +29,7 @@
29 Depends on FCHAR_T. 29 Depends on FCHAR_T.
30 DCHAR_CPY memcpy like function for DCHAR_T[] arrays. 30 DCHAR_CPY memcpy like function for DCHAR_T[] arrays.
31 DCHAR_SET memset like function for DCHAR_T[] arrays. 31 DCHAR_SET memset like function for DCHAR_T[] arrays.
32 DCHAR_STRLEN strlen like function for DCHAR_T[] arrays.
32 DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays. 33 DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays.
33 SNPRINTF The system's snprintf (or similar) function. 34 SNPRINTF The system's snprintf (or similar) function.
34 This may be either snprintf or swprintf. 35 This may be either snprintf or swprintf.
@@ -64,7 +65,7 @@
64/* As of GCC 11.2.1, gcc -Wanalyzer-too-complex reports that main's 65/* As of GCC 11.2.1, gcc -Wanalyzer-too-complex reports that main's
65 use of CHECK macros expands to code that is too complicated for gcc 66 use of CHECK macros expands to code that is too complicated for gcc
66 -fanalyzer. Suppress the resulting bogus warnings. */ 67 -fanalyzer. Suppress the resulting bogus warnings. */
67#if 10 <= __GNUC__ 68#if _GL_GNUC_PREREQ (10, 0)
68# pragma GCC diagnostic ignored "-Wanalyzer-null-argument" 69# pragma GCC diagnostic ignored "-Wanalyzer-null-argument"
69#endif 70#endif
70 71
@@ -80,14 +81,15 @@
80#endif 81#endif
81 82
82#include <locale.h> /* localeconv() */ 83#include <locale.h> /* localeconv() */
84#include <stdint.h> /* PTRDIFF_MAX */
83#include <stdio.h> /* snprintf(), sprintf() */ 85#include <stdio.h> /* snprintf(), sprintf() */
84#include <stdlib.h> /* abort(), malloc(), realloc(), free() */ 86#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
85#include <string.h> /* memcpy(), strlen() */ 87#include <string.h> /* memcpy(), strlen() */
86#include <wchar.h> /* mbstate_t, mbrtowc(), mbrlen(), wcrtomb(), mbszero() */ 88#include <wchar.h> /* mbstate_t, mbrtowc(), mbrlen(), wcrtomb(), mbszero() */
87#include <errno.h> /* errno */ 89#include <errno.h> /* errno */
88#include <limits.h> /* CHAR_BIT, INT_WIDTH, LONG_WIDTH */ 90#include <limits.h> /* CHAR_BIT, INT_MAX, INT_WIDTH, LONG_WIDTH */
89#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */ 91#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP, LDBL_MANT_DIG */
90#if HAVE_NL_LANGINFO 92#if HAVE_NL_LANGINFO || __GLIBC__ >= 2 || defined __CYGWIN__
91# include <langinfo.h> 93# include <langinfo.h>
92#endif 94#endif
93#ifndef VASNPRINTF 95#ifndef VASNPRINTF
@@ -182,6 +184,20 @@
182# define TCHAR_T char 184# define TCHAR_T char
183# endif 185# endif
184#endif 186#endif
187#ifndef DCHAR_STRLEN
188# if WIDE_CHAR_VERSION
189# define DCHAR_STRLEN local_wcslen
190# else
191# define DCHAR_STRLEN strlen
192# endif
193#endif
194#ifndef DCHAR_MBSNLEN
195# if WIDE_CHAR_VERSION
196# define DCHAR_MBSNLEN wcsnlen
197# else
198# define DCHAR_MBSNLEN mbsnlen
199# endif
200#endif
185#if !WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR 201#if !WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR
186 /* TCHAR_T is char. */ 202 /* TCHAR_T is char. */
187 /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'. 203 /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
@@ -216,6 +232,12 @@
216/* Here we need to call the native sprintf, not rpl_sprintf. */ 232/* Here we need to call the native sprintf, not rpl_sprintf. */
217#undef sprintf 233#undef sprintf
218 234
235/* macOS 12's "warning: 'sprintf' is deprecated" is pointless,
236 as sprintf is used safely here. */
237#if defined __APPLE__ && defined __MACH__ && _GL_GNUC_PREREQ (4, 2)
238# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
239#endif
240
219/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized" 241/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
220 warnings in this file. Use -Dlint to suppress them. */ 242 warnings in this file. Use -Dlint to suppress them. */
221#if defined GCC_LINT || defined lint 243#if defined GCC_LINT || defined lint
@@ -224,6 +246,11 @@
224# define IF_LINT(Code) /* empty */ 246# define IF_LINT(Code) /* empty */
225#endif 247#endif
226 248
249/* Here we need only the most basic fields of 'struct lconv', and can
250 therefore use the system's localeconv() function, without needing a
251 dependency on module 'localeconv'. */
252#undef localeconv
253
227/* Avoid some warnings from "gcc -Wshadow". 254/* Avoid some warnings from "gcc -Wshadow".
228 This file doesn't use the exp() and remainder() functions. */ 255 This file doesn't use the exp() and remainder() functions. */
229#undef exp 256#undef exp
@@ -231,7 +258,7 @@
231#undef remainder 258#undef remainder
232#define remainder rem 259#define remainder rem
233 260
234#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && !WIDE_CHAR_VERSION 261#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (PTRDIFF_MAX > INT_MAX)) && !WIDE_CHAR_VERSION
235# if (HAVE_STRNLEN && !defined _AIX) 262# if (HAVE_STRNLEN && !defined _AIX)
236# define local_strnlen strnlen 263# define local_strnlen strnlen
237# else 264# else
@@ -247,7 +274,7 @@ local_strnlen (const char *string, size_t maxlen)
247# endif 274# endif
248#endif 275#endif
249 276
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 277#if ((!USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (PTRDIFF_MAX > INT_MAX) || !DCHAR_IS_TCHAR || NEED_WPRINTF_DIRECTIVE_LC) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || (PTRDIFF_MAX > INT_MAX) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)
251# if HAVE_WCSLEN 278# if HAVE_WCSLEN
252# define local_wcslen wcslen 279# define local_wcslen wcslen
253# else 280# else
@@ -270,7 +297,7 @@ local_wcslen (const wchar_t *s)
270# endif 297# endif
271#endif 298#endif
272 299
273#if (!USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && HAVE_WCHAR_T && WIDE_CHAR_VERSION 300#if (!USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && WIDE_CHAR_VERSION
274# if HAVE_WCSNLEN && HAVE_DECL_WCSNLEN 301# if HAVE_WCSNLEN && HAVE_DECL_WCSNLEN
275# define local_wcsnlen wcsnlen 302# define local_wcsnlen wcsnlen
276# else 303# else
@@ -289,7 +316,7 @@ local_wcsnlen (const wchar_t *s, size_t maxlen)
289# endif 316# endif
290#endif 317#endif
291 318
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 319#if ((!USE_SNPRINTF || (PTRDIFF_MAX > INT_MAX) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS || ENABLE_WCHAR_FALLBACK) || ((NEED_PRINTF_DIRECTIVE_LC || ENABLE_WCHAR_FALLBACK) && HAVE_WINT_T)) && !WIDE_CHAR_VERSION
293# if ENABLE_WCHAR_FALLBACK 320# if ENABLE_WCHAR_FALLBACK
294static size_t 321static size_t
295wctomb_fallback (char *s, wchar_t wc) 322wctomb_fallback (char *s, wchar_t wc)
@@ -357,7 +384,7 @@ local_wctomb (char *s, wchar_t wc)
357# endif 384# endif
358#endif 385#endif
359 386
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) 387#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) || (NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT)
361/* Determine the decimal-point character according to the current locale. */ 388/* Determine the decimal-point character according to the current locale. */
362# ifndef decimal_point_char_defined 389# ifndef decimal_point_char_defined
363# define decimal_point_char_defined 1 390# define decimal_point_char_defined 1
@@ -384,6 +411,217 @@ decimal_point_char (void)
384# endif 411# endif
385#endif 412#endif
386 413
414#if (!WIDE_CHAR_VERSION && (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE)) || ((!WIDE_CHAR_VERSION || !DCHAR_IS_TCHAR) && (NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT))
415/* Determine the thousands-separator character according to the current
416 locale.
417 It is a single multibyte character.
418 In glibc: 35x ".", 90x ",", 23x U+202F, 1x U+2019, 1x U+066C, on other
419 systems also U+00A0. */
420# ifndef thousands_separator_char_defined
421# define thousands_separator_char_defined 1
422static const char *
423thousands_separator_char (char stackbuf[10])
424{
425 /* Determine it in a multithread-safe way.
426 We know nl_langinfo is multithread-safe on glibc systems, on Mac OS X
427 systems, and on NetBSD, but is not required to be multithread-safe by
428 POSIX.
429 localeconv() is not guaranteed to be multithread-safe by POSIX either;
430 however, on native Windows it is (cf. test-localeconv-mt).
431 sprintf(), however, is multithread-safe. */
432# if HAVE_NL_LANGINFO && (__GLIBC__ || defined __UCLIBC__ || (defined __APPLE__ && defined __MACH__) || defined __NetBSD__)
433 return nl_langinfo (THOUSEP);
434# elif defined _WIN32 && !defined __CYGWIN__
435 return localeconv () -> thousands_sep;
436# else
437 sprintf (stackbuf, "%'.0f", 1000.0);
438 /* Now stackbuf = "1<thousep>000". */
439 stackbuf[strlen (stackbuf) - 3] = '\0';
440# if defined __sun
441 /* Solaris specific hack: Replace wrong result (0xC2 means U+00A0). */
442 if (strcmp (&stackbuf[1], "\302") == 0)
443 strcpy (&stackbuf[1], MB_CUR_MAX > 1 ? "\302\240" : "\240");
444# endif
445 return &stackbuf[1];
446# endif
447}
448# endif
449#endif
450#if !WIDE_CHAR_VERSION && defined DCHAR_CONV_FROM_ENCODING && (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE)
451/* Determine the thousands-separator character, as a DCHAR_T[] array,
452 according to the current locale.
453 It is a single Unicode character. */
454# ifndef thousands_separator_DCHAR_defined
455# define thousands_separator_DCHAR_defined 1
456static const DCHAR_T *
457thousands_separator_DCHAR (DCHAR_T stackbuf[10])
458{
459 /* Determine it in a multithread-safe way. */
460 char tmpbuf[10];
461 const char *tmp = thousands_separator_char (tmpbuf);
462 if (*tmp != '\0')
463 {
464 /* Convert it from char[] to DCHAR_T[]. */
465 size_t converted_len = 10;
466 DCHAR_T *converted =
467 DCHAR_CONV_FROM_ENCODING (locale_charset (),
468 iconveh_question_mark,
469 tmp, strlen (tmp) + 1,
470 NULL,
471 stackbuf, &converted_len);
472 if (converted != NULL)
473 {
474 if (converted != stackbuf)
475 /* It should not be so long. */
476 abort ();
477 return stackbuf;
478 }
479 }
480 stackbuf[0] = 0;
481 return stackbuf;
482}
483# endif
484#endif
485/* Maximum number of 'char' in the char[] or DCHAR_T[] representation of the
486 thousands separator. */
487#define THOUSEP_CHAR_MAXLEN 3
488
489#if WIDE_CHAR_VERSION && ((NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) || ((NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT) && DCHAR_IS_TCHAR))
490/* Determine the thousands-separator character, as a wide character, according
491 to the current locale.
492 It is a single wide character. */
493# ifndef thousands_separator_wchar_defined
494# define thousands_separator_wchar_defined 1
495static const wchar_t *
496thousands_separator_wchar (wchar_t stackbuf[10])
497{
498# if __GLIBC__ >= 2 || defined __CYGWIN__
499 /* On glibc, in the unibyte locale fr_FR, the *wprintf routines use U+202F
500 as separator, which cannot be represented in the locale encoding. */
501 stackbuf[0] =
502 (wchar_t) (unsigned long) nl_langinfo (_NL_NUMERIC_THOUSANDS_SEP_WC);
503 stackbuf[1] = L'\0';
504 return stackbuf;
505# elif defined _WIN32 && !defined __CYGWIN__
506 const char *tmp = localeconv () -> thousands_sep;
507 if (*tmp != '\0')
508 {
509 mbstate_t state;
510 mbszero (&state);
511 if ((int) mbrtowc (&stackbuf[0], tmp, strlen (tmp), &state) > 0)
512 stackbuf[1] = L'\0';
513 else
514 stackbuf[0] = L'\0';
515 }
516 else
517 stackbuf[0] = L'\0';
518 return stackbuf;
519# elif defined __sun
520 /* Use sprintf, because swprintf retrieves a wrong value for the
521 thousands-separator wide character (e.g. (wchar_t) 0xffffffa0). */
522 char tmp[10];
523 sprintf (tmp, "%'.0f", 1000.0);
524 /* Now tmp = L"1<thousep>000". */
525 tmp[strlen (tmp) - 3] = '\0';
526 /* Solaris specific hack: Replace wrong result (0xC2 means U+00A0). */
527 if (strcmp (&tmp[1], "\302") == 0)
528 strcpy (&tmp[1], MB_CUR_MAX > 1 ? "\302\240" : "\240");
529 if (tmp[1] != '\0')
530 {
531 mbstate_t state;
532 mbszero (&state);
533 if ((int) mbrtowc (&stackbuf[0], &tmp[1], strlen (&tmp[1]), &state) > 0)
534 stackbuf[1] = L'\0';
535 else
536 stackbuf[0] = L'\0';
537 }
538 else
539 stackbuf[0] = L'\0';
540 return stackbuf;
541# else
542 swprintf (stackbuf, 10, L"%'.0f", 1000.0);
543 /* Now stackbuf = L"1<thousep>000". */
544 stackbuf[local_wcslen (stackbuf) - 3] = '\0';
545 return &stackbuf[1];
546# endif
547}
548# endif
549#endif
550/* Maximum number of 'wchar_t' in the wchar_t[] representation of the thousands
551 separator. */
552#define THOUSEP_WCHAR_MAXLEN 1
553
554#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) || (NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT)
555# ifndef grouping_rule_defined
556# define grouping_rule_defined 1
557/* Determine the grouping rule.
558 * As specified in POSIX
559 * <https://pubs.opengroup.org/onlinepubs/9799919799/functions/localeconv.html>
560 * <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html#tag_07_03_04>
561 * it is a string whose elements are 'signed char' values, where
562 * "Each integer specifies the number of digits in each group, with the initial
563 * integer defining the size of the group immediately preceding the decimal
564 * delimiter, and the following integers defining the preceding groups. If
565 * the last integer is not -1, then the size of the previous group (if any)
566 * shall be repeatedly used for the remainder of the digits. If the last
567 * integer is -1, then no further grouping shall be performed."
568 * Platforms that have locales with grouping:
569 * glibc, FreeBSD, NetBSD, AIX, Solaris, Cygwin, Haiku.
570 * Platforms that don't:
571 * musl libc, macOS, OpenBSD, Android, mingw, MSVC.
572 * Typical grouping rules on glibc:
573 * 136x 3 (fr_FR etc.)
574 * 4x 4 (cmn_TW etc.)
575 * 9x 3;2 (ta_IN etc.)
576 * 1x 2;2;2;3 (umn_US)
577 * 21x -1 (C etc.)
578 */
579static const signed char *
580grouping_rule (void)
581{
582 /* We know nl_langinfo is multithread-safe on glibc systems and on Cygwin,
583 but is not required to be multithread-safe by POSIX.
584 localeconv() is not guaranteed to be multithread-safe by POSIX either;
585 however, on all known systems it is (cf. test-localeconv-mt). */
586# if __GLIBC__ >= 2
587 return (const signed char *) nl_langinfo (GROUPING);
588# elif defined __CYGWIN__
589 return (const signed char *) nl_langinfo (_NL_NUMERIC_GROUPING);
590# else
591 return (const signed char *) localeconv () -> grouping;
592# endif
593}
594/* Determines the number of thousands-separators to be inserted in a digit
595 sequence with ndigits digits (before the decimal point). */
596static size_t
597num_thousands_separators (const signed char *grouping, size_t ndigits)
598{
599 const signed char *g = grouping;
600 int h = *g;
601 if (h <= 0 || ndigits == 0)
602 return 0;
603 size_t insert = 0;
604 for (;;)
605 {
606 /* Invariant: here h == *g, h > 0, ndigits > 0. */
607 if (g[1] == 0)
608 /* h repeats endlessly. */
609 return insert + (ndigits - 1) / h;
610 /* h does not repeat. */
611 if (ndigits <= h)
612 return insert;
613 ndigits -= h;
614 insert++;
615 g++;
616 h = *g;
617 if (h < 0)
618 /* No further grouping. */
619 return insert;
620 }
621}
622# endif
623#endif
624
387#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE 625#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE
388 626
389/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ 627/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
@@ -406,8 +644,45 @@ is_infinite_or_zerol (long double x)
406 644
407#endif 645#endif
408 646
647#if NEED_PRINTF_LONG_DOUBLE
648
649/* Like frexpl, except that it supports even "unsupported" numbers. */
650# if (LDBL_MANT_DIG == 64 && (defined __ia64 || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))) && (defined __APPLE__ && defined __MACH__)
651/* Don't assume that frexpl can handle pseudo-denormals; it does not on
652 macOS 12/x86_64. Therefore test for a pseudo-denormal explicitly. */
653
654static
655long double safe_frexpl (long double x, int *exp)
656{
657 union
658 {
659 long double value;
660 struct { unsigned int mant_word[2]; unsigned short sign_exp_word; } r;
661 }
662 u;
663 u.value = x;
664 if (u.r.sign_exp_word == 0 && (u.r.mant_word[1] & 0x80000000u) != 0)
665 {
666 /* Pseudo-Denormal. */
667 *exp = LDBL_MIN_EXP;
668 u.r.sign_exp_word = 1 - LDBL_MIN_EXP;
669 return u.value;
670 }
671 else
672 return frexpl (x, exp);
673}
674
675# else
676# define safe_frexpl frexpl
677# endif
678
679#endif
680
409#if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE 681#if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE
410 682
683/* An indicator for a failed memory allocation. */
684# define NOMEM_PTR ((void *) (-1))
685
411/* Converting 'long double' to decimal without rare rounding bugs requires 686/* Converting 'long double' to decimal without rare rounding bugs requires
412 real bignums. We use the naming conventions of GNU gmp, but vastly simpler 687 real bignums. We use the naming conventions of GNU gmp, but vastly simpler
413 (and slower) algorithms. */ 688 (and slower) algorithms. */
@@ -428,8 +703,8 @@ typedef struct
428} mpn_t; 703} mpn_t;
429 704
430/* Compute the product of two bignums >= 0. 705/* Compute the product of two bignums >= 0.
431 Return the allocated memory in case of success, NULL in case of memory 706 Return the allocated memory (possibly NULL) in case of success, NOMEM_PTR
432 allocation failure. */ 707 in case of memory allocation failure. */
433static void * 708static void *
434multiply (mpn_t src1, mpn_t src2, mpn_t *dest) 709multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
435{ 710{
@@ -457,7 +732,7 @@ multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
457 { 732 {
458 /* src1 or src2 is zero. */ 733 /* src1 or src2 is zero. */
459 dest->nlimbs = 0; 734 dest->nlimbs = 0;
460 dest->limbs = (mp_limb_t *) malloc (1); 735 dest->limbs = NULL;
461 } 736 }
462 else 737 else
463 { 738 {
@@ -469,7 +744,7 @@ multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
469 dlen = len1 + len2; 744 dlen = len1 + len2;
470 dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t)); 745 dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
471 if (dp == NULL) 746 if (dp == NULL)
472 return NULL; 747 return NOMEM_PTR;
473 for (k = len2; k > 0; ) 748 for (k = len2; k > 0; )
474 dp[--k] = 0; 749 dp[--k] = 0;
475 for (i = 0; i < len1; i++) 750 for (i = 0; i < len1; i++)
@@ -500,8 +775,8 @@ multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
500 the remainder. 775 the remainder.
501 Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd, 776 Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
502 q is incremented. 777 q is incremented.
503 Return the allocated memory in case of success, NULL in case of memory 778 Return the allocated memory (possibly NULL) in case of success, NOMEM_PTR
504 allocation failure. */ 779 in case of memory allocation failure. */
505static void * 780static void *
506divide (mpn_t a, mpn_t b, mpn_t *q) 781divide (mpn_t a, mpn_t b, mpn_t *q)
507{ 782{
@@ -572,7 +847,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
572 final rounding of q.) */ 847 final rounding of q.) */
573 roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t)); 848 roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
574 if (roomptr == NULL) 849 if (roomptr == NULL)
575 return NULL; 850 return NOMEM_PTR;
576 851
577 /* Normalise a. */ 852 /* Normalise a. */
578 while (a_len > 0 && a_ptr[a_len - 1] == 0) 853 while (a_len > 0 && a_ptr[a_len - 1] == 0)
@@ -708,7 +983,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
708 if (tmp_roomptr == NULL) 983 if (tmp_roomptr == NULL)
709 { 984 {
710 free (roomptr); 985 free (roomptr);
711 return NULL; 986 return NOMEM_PTR;
712 } 987 }
713 { 988 {
714 const mp_limb_t *sourceptr = b_ptr; 989 const mp_limb_t *sourceptr = b_ptr;
@@ -930,7 +1205,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
930/* Avoid pointless GCC warning "argument 1 value '18446744073709551615' exceeds 1205/* Avoid pointless GCC warning "argument 1 value '18446744073709551615' exceeds
931 maximum object size 9223372036854775807", triggered by the use of xsum as 1206 maximum object size 9223372036854775807", triggered by the use of xsum as
932 argument of malloc. */ 1207 argument of malloc. */
933# if __GNUC__ >= 7 1208# if _GL_GNUC_PREREQ (7, 0)
934# pragma GCC diagnostic push 1209# pragma GCC diagnostic push
935# pragma GCC diagnostic ignored "-Walloc-size-larger-than=" 1210# pragma GCC diagnostic ignored "-Walloc-size-larger-than="
936# endif 1211# endif
@@ -991,7 +1266,7 @@ convert_to_decimal (mpn_t a, size_t extra_zeroes)
991 return c_ptr; 1266 return c_ptr;
992} 1267}
993 1268
994# if __GNUC__ >= 7 1269# if _GL_GNUC_PREREQ (7, 0)
995# pragma GCC diagnostic pop 1270# pragma GCC diagnostic pop
996# endif 1271# endif
997 1272
@@ -1015,7 +1290,7 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
1015 if (m.limbs == NULL) 1290 if (m.limbs == NULL)
1016 return NULL; 1291 return NULL;
1017 /* Split into exponential part and mantissa. */ 1292 /* Split into exponential part and mantissa. */
1018 y = frexpl (x, &exp); 1293 y = safe_frexpl (x, &exp);
1019 if (!(y >= 0.0L && y < 1.0L)) 1294 if (!(y >= 0.0L && y < 1.0L))
1020 abort (); 1295 abort ();
1021 /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the 1296 /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the
@@ -1306,7 +1581,7 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1306 mpn_t denominator; 1581 mpn_t denominator;
1307 void *tmp_memory; 1582 void *tmp_memory;
1308 tmp_memory = multiply (m, pow5, &numerator); 1583 tmp_memory = multiply (m, pow5, &numerator);
1309 if (tmp_memory == NULL) 1584 if (tmp_memory == NOMEM_PTR)
1310 { 1585 {
1311 free (pow5_ptr); 1586 free (pow5_ptr);
1312 free (memory); 1587 free (memory);
@@ -1379,7 +1654,7 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1379 1654
1380 /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */ 1655 /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */
1381 1656
1382 if (z_memory == NULL) 1657 if (z_memory == NOMEM_PTR)
1383 return NULL; 1658 return NULL;
1384 digits = convert_to_decimal (z, extra_zeroes); 1659 digits = convert_to_decimal (z, extra_zeroes);
1385 free (z_memory); 1660 free (z_memory);
@@ -1442,7 +1717,7 @@ floorlog10l (long double x)
1442 double l; 1717 double l;
1443 1718
1444 /* Split into exponential part and mantissa. */ 1719 /* Split into exponential part and mantissa. */
1445 y = frexpl (x, &exp); 1720 y = safe_frexpl (x, &exp);
1446 if (!(y >= 0.0L && y < 1.0L)) 1721 if (!(y >= 0.0L && y < 1.0L))
1447 abort (); 1722 abort ();
1448 if (y == 0.0L) 1723 if (y == 0.0L)
@@ -1801,8 +2076,17 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
1801 } 2076 }
1802 if (tmp_length < precision) 2077 if (tmp_length < precision)
1803 tmp_length = precision; 2078 tmp_length = precision;
1804 /* Multiply by 2, as an estimate for FLAG_GROUP. */ 2079 /* Account for thousands separators. */
1805 tmp_length = xsum (tmp_length, tmp_length); 2080 if (flags & FLAG_GROUP)
2081 {
2082 /* A thousands separator needs to be inserted at most every 2 digits.
2083 This is the case in the ta_IN locale. */
2084# if WIDE_CHAR_VERSION
2085 tmp_length = xsum (tmp_length, tmp_length / 2 * THOUSEP_WCHAR_MAXLEN);
2086# else
2087 tmp_length = xsum (tmp_length, tmp_length / 2 * THOUSEP_CHAR_MAXLEN);
2088# endif
2089 }
1806 /* Add 1, to account for a leading sign. */ 2090 /* Add 1, to account for a leading sign. */
1807 tmp_length = xsum (tmp_length, 1); 2091 tmp_length = xsum (tmp_length, 1);
1808 break; 2092 break;
@@ -2050,12 +2334,18 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2050 tmp_length = xsum (tmp_length, 2); 2334 tmp_length = xsum (tmp_length, 2);
2051 break; 2335 break;
2052 2336
2337 case 'e': case 'E':
2338 tmp_length =
2339 12; /* sign, decimal point, exponent etc. */
2340 tmp_length = xsum (tmp_length, precision);
2341 break;
2342
2053 case 'f': case 'F': 2343 case 'f': case 'F':
2054 if (type == TYPE_LONGDOUBLE) 2344 if (type == TYPE_LONGDOUBLE)
2055 tmp_length = 2345 tmp_length =
2056 (unsigned int) (LDBL_MAX_EXP 2346 (unsigned int) (LDBL_MAX_EXP
2057 * 0.30103 /* binary -> decimal */ 2347 * 0.30103 /* binary -> decimal */
2058 * 2 /* estimate for FLAG_GROUP */ 2348 * 0.5 * 3 /* estimate for FLAG_GROUP */
2059 ) 2349 )
2060 + 1 /* turn floor into ceil */ 2350 + 1 /* turn floor into ceil */
2061 + 10; /* sign, decimal point etc. */ 2351 + 10; /* sign, decimal point etc. */
@@ -2063,17 +2353,20 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2063 tmp_length = 2353 tmp_length =
2064 (unsigned int) (DBL_MAX_EXP 2354 (unsigned int) (DBL_MAX_EXP
2065 * 0.30103 /* binary -> decimal */ 2355 * 0.30103 /* binary -> decimal */
2066 * 2 /* estimate for FLAG_GROUP */ 2356 * 0.5 * 3 /* estimate for FLAG_GROUP */
2067 ) 2357 )
2068 + 1 /* turn floor into ceil */ 2358 + 1 /* turn floor into ceil */
2069 + 10; /* sign, decimal point etc. */ 2359 + 10; /* sign, decimal point etc. */
2070 tmp_length = xsum (tmp_length, precision); 2360 tmp_length = xsum (tmp_length, precision);
2071 break; 2361 break;
2072 2362
2073 case 'e': case 'E': case 'g': case 'G': 2363 case 'g': case 'G':
2074 tmp_length = 2364 tmp_length =
2075 12; /* sign, decimal point, exponent etc. */ 2365 12; /* sign, decimal point, exponent etc. */
2076 tmp_length = xsum (tmp_length, precision); 2366 tmp_length = xsum (tmp_length,
2367 precision
2368 * 0.5 * 3 /* estimate for FLAG_GROUP */
2369 );
2077 break; 2370 break;
2078 2371
2079 case 'a': case 'A': 2372 case 'a': case 'A':
@@ -2111,10 +2404,9 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2111 break; 2404 break;
2112 2405
2113 case 's': 2406 case 's':
2114# if HAVE_WCHAR_T
2115 if (type == TYPE_WIDE_STRING) 2407 if (type == TYPE_WIDE_STRING)
2116 { 2408 {
2117# if WIDE_CHAR_VERSION 2409# if WIDE_CHAR_VERSION
2118 /* ISO C says about %ls in fwprintf: 2410 /* ISO C says about %ls in fwprintf:
2119 "If the precision is not specified or is greater than the size 2411 "If the precision is not specified or is greater than the size
2120 of the array, the array shall contain a null wide character." 2412 of the array, the array shall contain a null wide character."
@@ -2125,7 +2417,7 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2125 tmp_length = local_wcsnlen (arg, precision); 2417 tmp_length = local_wcsnlen (arg, precision);
2126 else 2418 else
2127 tmp_length = local_wcslen (arg); 2419 tmp_length = local_wcslen (arg);
2128# else 2420# else
2129 /* ISO C says about %ls in fprintf: 2421 /* ISO C says about %ls in fprintf:
2130 "If a precision is specified, no more than that many bytes are 2422 "If a precision is specified, no more than that many bytes are
2131 written (including shift sequences, if any), and the array 2423 written (including shift sequences, if any), and the array
@@ -2136,10 +2428,9 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2136 So if there is a precision, we must not use wcslen. */ 2428 So if there is a precision, we must not use wcslen. */
2137 /* This case has already been handled separately in VASNPRINTF. */ 2429 /* This case has already been handled separately in VASNPRINTF. */
2138 abort (); 2430 abort ();
2139# endif 2431# endif
2140 } 2432 }
2141 else 2433 else
2142# endif
2143 { 2434 {
2144# if WIDE_CHAR_VERSION 2435# if WIDE_CHAR_VERSION
2145 /* ISO C says about %s in fwprintf: 2436 /* ISO C says about %s in fwprintf:
@@ -2226,7 +2517,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2226 TCHAR_T *buf; 2517 TCHAR_T *buf;
2227 TCHAR_T *buf_malloced; 2518 TCHAR_T *buf_malloced;
2228 const FCHAR_T *cp; 2519 const FCHAR_T *cp;
2229 size_t i; 2520 size_t di;
2230 DIRECTIVE *dp; 2521 DIRECTIVE *dp;
2231 /* Output string accumulator. */ 2522 /* Output string accumulator. */
2232 DCHAR_T *result; 2523 DCHAR_T *result;
@@ -2290,7 +2581,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2290#define ENSURE_ALLOCATION(needed) \ 2581#define ENSURE_ALLOCATION(needed) \
2291 ENSURE_ALLOCATION_ELSE((needed), goto out_of_memory; ) 2582 ENSURE_ALLOCATION_ELSE((needed), goto out_of_memory; )
2292 2583
2293 for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) 2584 for (cp = format, di = 0, dp = &d.dir[0]; ; cp = dp->dir_end, di++, dp++)
2294 { 2585 {
2295 if (cp != dp->dir_start) 2586 if (cp != dp->dir_start)
2296 { 2587 {
@@ -2313,7 +2604,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2313 while (--n > 0); 2604 while (--n > 0);
2314 } 2605 }
2315 } 2606 }
2316 if (i == d.count) 2607 if (di == d.count)
2317 break; 2608 break;
2318 2609
2319 /* Execute a single directive. */ 2610 /* Execute a single directive. */
@@ -2423,6 +2714,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2423 width = xsum (xtimes (width, 10), *digitp++ - '0'); 2714 width = xsum (xtimes (width, 10), *digitp++ - '0');
2424 while (digitp != dp->width_end); 2715 while (digitp != dp->width_end);
2425 } 2716 }
2717 if (width > (size_t) INT_MAX)
2718 goto overflow;
2426 has_width = 1; 2719 has_width = 1;
2427 } 2720 }
2428 2721
@@ -2501,7 +2794,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2501 { 2794 {
2502 /* Use the entire string. */ 2795 /* Use the entire string. */
2503 arg_end = arg + u8_strlen (arg); 2796 arg_end = arg + u8_strlen (arg);
2504 /* The number of characters doesn't matter. */ 2797 /* The number of characters doesn't matter,
2798 because !has_width and therefore width==0. */
2505 characters = 0; 2799 characters = 0;
2506 } 2800 }
2507 2801
@@ -2542,7 +2836,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2542 if (converted != result + length) 2836 if (converted != result + length)
2543 { 2837 {
2544 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len), 2838 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
2545 { free (converted); goto out_of_memory; }); 2839 { free (converted); goto out_of_memory; });
2546 DCHAR_CPY (result + length, converted, converted_len); 2840 DCHAR_CPY (result + length, converted, converted_len);
2547 free (converted); 2841 free (converted);
2548 } 2842 }
@@ -2603,7 +2897,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2603 { 2897 {
2604 /* Use the entire string. */ 2898 /* Use the entire string. */
2605 arg_end = arg + u16_strlen (arg); 2899 arg_end = arg + u16_strlen (arg);
2606 /* The number of characters doesn't matter. */ 2900 /* The number of characters doesn't matter,
2901 because !has_width and therefore width==0. */
2607 characters = 0; 2902 characters = 0;
2608 } 2903 }
2609 2904
@@ -2644,7 +2939,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2644 if (converted != result + length) 2939 if (converted != result + length)
2645 { 2940 {
2646 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len), 2941 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
2647 { free (converted); goto out_of_memory; }); 2942 { free (converted); goto out_of_memory; });
2648 DCHAR_CPY (result + length, converted, converted_len); 2943 DCHAR_CPY (result + length, converted, converted_len);
2649 free (converted); 2944 free (converted);
2650 } 2945 }
@@ -2705,7 +3000,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2705 { 3000 {
2706 /* Use the entire string. */ 3001 /* Use the entire string. */
2707 arg_end = arg + u32_strlen (arg); 3002 arg_end = arg + u32_strlen (arg);
2708 /* The number of characters doesn't matter. */ 3003 /* The number of characters doesn't matter,
3004 because !has_width and therefore width==0. */
2709 characters = 0; 3005 characters = 0;
2710 } 3006 }
2711 3007
@@ -2746,7 +3042,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2746 if (converted != result + length) 3042 if (converted != result + length)
2747 { 3043 {
2748 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len), 3044 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
2749 { free (converted); goto out_of_memory; }); 3045 { free (converted); goto out_of_memory; });
2750 DCHAR_CPY (result + length, converted, converted_len); 3046 DCHAR_CPY (result + length, converted, converted_len);
2751 free (converted); 3047 free (converted);
2752 } 3048 }
@@ -2769,7 +3065,190 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2769 } 3065 }
2770 } 3066 }
2771#endif 3067#endif
2772#if WIDE_CHAR_VERSION && (!DCHAR_IS_TCHAR || NEED_WPRINTF_DIRECTIVE_LC) 3068#if !WIDE_CHAR_VERSION && (PTRDIFF_MAX > INT_MAX)
3069 else if (dp->conversion == 's'
3070 && a.arg[dp->arg_index].type != TYPE_WIDE_STRING)
3071 {
3072 /* %s in vasnprintf. See the specification of fprintf.
3073 We handle it ourselves here, because the string may be longer
3074 than INT_MAX characters, whence snprintf or sprintf would
3075 fail to process it. */
3076 int flags = dp->flags;
3077 int has_width;
3078 size_t width;
3079 int has_precision;
3080 size_t precision;
3081
3082 has_width = 0;
3083 width = 0;
3084 if (dp->width_start != dp->width_end)
3085 {
3086 if (dp->width_arg_index != ARG_NONE)
3087 {
3088 int arg;
3089
3090 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3091 abort ();
3092 arg = a.arg[dp->width_arg_index].a.a_int;
3093 width = arg;
3094 if (arg < 0)
3095 {
3096 /* "A negative field width is taken as a '-' flag
3097 followed by a positive field width." */
3098 flags |= FLAG_LEFT;
3099 width = -width;
3100 }
3101 }
3102 else
3103 {
3104 const FCHAR_T *digitp = dp->width_start;
3105
3106 do
3107 width = xsum (xtimes (width, 10), *digitp++ - '0');
3108 while (digitp != dp->width_end);
3109 }
3110 if (width > (size_t) INT_MAX)
3111 goto overflow;
3112 has_width = 1;
3113 }
3114
3115 has_precision = 0;
3116 precision = 6;
3117 if (dp->precision_start != dp->precision_end)
3118 {
3119 if (dp->precision_arg_index != ARG_NONE)
3120 {
3121 int arg;
3122
3123 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
3124 abort ();
3125 arg = a.arg[dp->precision_arg_index].a.a_int;
3126 /* "A negative precision is taken as if the precision
3127 were omitted." */
3128 if (arg >= 0)
3129 {
3130 precision = arg;
3131 has_precision = 1;
3132 }
3133 }
3134 else
3135 {
3136 const FCHAR_T *digitp = dp->precision_start + 1;
3137
3138 precision = 0;
3139 while (digitp != dp->precision_end)
3140 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
3141 has_precision = 1;
3142 }
3143 }
3144
3145 {
3146 const char *arg = a.arg[dp->arg_index].a.a_string;
3147 size_t bytes;
3148# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3149 size_t characters;
3150# endif
3151# if !DCHAR_IS_TCHAR
3152 /* This code assumes that TCHAR_T is 'char'. */
3153 static_assert (sizeof (TCHAR_T) == 1);
3154 DCHAR_T *tmpdst;
3155 size_t tmpdst_len;
3156# endif
3157 size_t w;
3158
3159 if (has_precision)
3160 {
3161 /* Use only at most PRECISION bytes, from the left. */
3162 bytes = local_strnlen (arg, precision);
3163 }
3164 else
3165 {
3166 /* Use the entire string, and count the number of
3167 bytes. */
3168 bytes = strlen (arg);
3169 }
3170
3171# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3172 if (has_width)
3173 characters = mbsnlen (arg, bytes);
3174 else
3175 {
3176 /* The number of characters doesn't matter,
3177 because !has_width and therefore width==0. */
3178 characters = 0;
3179 }
3180# endif
3181
3182# if !DCHAR_IS_TCHAR
3183 /* Convert from TCHAR_T[] to DCHAR_T[]. */
3184 tmpdst =
3185 DCHAR_CONV_FROM_ENCODING (locale_charset (),
3186 iconveh_question_mark,
3187 arg, bytes,
3188 NULL,
3189 NULL, &tmpdst_len);
3190 if (tmpdst == NULL)
3191 goto fail_with_errno;
3192# endif
3193
3194 if (has_width)
3195 {
3196# if ENABLE_UNISTDIO
3197 /* Outside POSIX, it's preferable to compare the width
3198 against the number of _characters_ of the converted
3199 value. */
3200# if DCHAR_IS_TCHAR
3201 w = characters;
3202# else
3203 w = DCHAR_MBSNLEN (tmpdst, tmpdst_len);
3204# endif
3205# else
3206 /* The width is compared against the number of _bytes_
3207 of the converted value, says POSIX. */
3208 w = bytes;
3209# endif
3210 }
3211 else
3212 /* w doesn't matter. */
3213 w = 0;
3214
3215 {
3216# if DCHAR_IS_TCHAR
3217 size_t total = bytes + (w < width ? width - w : 0);
3218 ENSURE_ALLOCATION (xsum (length, total));
3219# else
3220 size_t total = tmpdst_len + (w < width ? width - w : 0);
3221 ENSURE_ALLOCATION_ELSE (xsum (length, total),
3222 { free (tmpdst); goto out_of_memory; });
3223# endif
3224
3225 if (w < width && !(flags & FLAG_LEFT))
3226 {
3227 size_t n = width - w;
3228 DCHAR_SET (result + length, ' ', n);
3229 length += n;
3230 }
3231
3232# if DCHAR_IS_TCHAR
3233 memcpy (result + length, arg, bytes);
3234 length += bytes;
3235# else
3236 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
3237 free (tmpdst);
3238 length += tmpdst_len;
3239# endif
3240
3241 if (w < width && (flags & FLAG_LEFT))
3242 {
3243 size_t n = width - w;
3244 DCHAR_SET (result + length, ' ', n);
3245 length += n;
3246 }
3247 }
3248 }
3249 }
3250#endif
3251#if WIDE_CHAR_VERSION && ((PTRDIFF_MAX > INT_MAX) || !DCHAR_IS_TCHAR || NEED_WPRINTF_DIRECTIVE_LC)
2773 else if ((dp->conversion == 's' 3252 else if ((dp->conversion == 's'
2774 && a.arg[dp->arg_index].type == TYPE_WIDE_STRING) 3253 && a.arg[dp->arg_index].type == TYPE_WIDE_STRING)
2775 || (dp->conversion == 'c' 3254 || (dp->conversion == 'c'
@@ -2810,6 +3289,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2810 width = xsum (xtimes (width, 10), *digitp++ - '0'); 3289 width = xsum (xtimes (width, 10), *digitp++ - '0');
2811 while (digitp != dp->width_end); 3290 while (digitp != dp->width_end);
2812 } 3291 }
3292 if (width > (size_t) INT_MAX)
3293 goto overflow;
2813 } 3294 }
2814 3295
2815 { 3296 {
@@ -2912,7 +3393,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2912 } 3393 }
2913 } 3394 }
2914#endif 3395#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 3396#if WIDE_CHAR_VERSION || !USE_SNPRINTF || (PTRDIFF_MAX > INT_MAX) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS || ENABLE_WCHAR_FALLBACK
2916 else if (dp->conversion == 's' 3397 else if (dp->conversion == 's'
2917# if WIDE_CHAR_VERSION 3398# if WIDE_CHAR_VERSION
2918 && a.arg[dp->arg_index].type != TYPE_WIDE_STRING 3399 && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
@@ -2965,6 +3446,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2965 width = xsum (xtimes (width, 10), *digitp++ - '0'); 3446 width = xsum (xtimes (width, 10), *digitp++ - '0');
2966 while (digitp != dp->width_end); 3447 while (digitp != dp->width_end);
2967 } 3448 }
3449 if (width > (size_t) INT_MAX)
3450 goto overflow;
2968 has_width = 1; 3451 has_width = 1;
2969 } 3452 }
2970 3453
@@ -3145,11 +3628,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3145 { 3628 {
3146 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; 3629 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
3147 const wchar_t *arg_end; 3630 const wchar_t *arg_end;
3631 size_t bytes;
3632# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3148 size_t characters; 3633 size_t characters;
3634# endif
3149# if !DCHAR_IS_TCHAR 3635# if !DCHAR_IS_TCHAR
3150 /* This code assumes that TCHAR_T is 'char'. */ 3636 /* This code assumes that TCHAR_T is 'char'. */
3151 static_assert (sizeof (TCHAR_T) == 1); 3637 static_assert (sizeof (TCHAR_T) == 1);
3152 TCHAR_T *tmpsrc;
3153 DCHAR_T *tmpdst; 3638 DCHAR_T *tmpdst;
3154 size_t tmpdst_len; 3639 size_t tmpdst_len;
3155# endif 3640# endif
@@ -3164,7 +3649,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3164 mbszero (&state); 3649 mbszero (&state);
3165# endif 3650# endif
3166 arg_end = arg; 3651 arg_end = arg;
3652 bytes = 0;
3653# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3167 characters = 0; 3654 characters = 0;
3655# endif
3168 while (precision > 0) 3656 while (precision > 0)
3169 { 3657 {
3170 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ 3658 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
@@ -3180,7 +3668,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3180 if (precision < (unsigned int) count) 3668 if (precision < (unsigned int) count)
3181 break; 3669 break;
3182 arg_end++; 3670 arg_end++;
3183 characters += count; 3671 bytes += count;
3672# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3673 characters += mbsnlen (cbuf, count);
3674# endif
3184 precision -= count; 3675 precision -= count;
3185 } 3676 }
3186 } 3677 }
@@ -3197,7 +3688,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3197 mbszero (&state); 3688 mbszero (&state);
3198# endif 3689# endif
3199 arg_end = arg; 3690 arg_end = arg;
3691 bytes = 0;
3692# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3200 characters = 0; 3693 characters = 0;
3694# endif
3201 for (;;) 3695 for (;;)
3202 { 3696 {
3203 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ 3697 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
@@ -3211,7 +3705,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3211 /* Cannot convert. */ 3705 /* Cannot convert. */
3212 goto fail_with_EILSEQ; 3706 goto fail_with_EILSEQ;
3213 arg_end++; 3707 arg_end++;
3214 characters += count; 3708 bytes += count;
3709# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3710 characters += mbsnlen (cbuf, count);
3711# endif
3215 } 3712 }
3216 } 3713 }
3217# if DCHAR_IS_TCHAR 3714# if DCHAR_IS_TCHAR
@@ -3219,56 +3716,64 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3219 { 3716 {
3220 /* Use the entire string. */ 3717 /* Use the entire string. */
3221 arg_end = arg + local_wcslen (arg); 3718 arg_end = arg + local_wcslen (arg);
3222 /* The number of bytes doesn't matter. */ 3719 /* The number of bytes and characters doesn't matter,
3720 because !has_width and therefore width==0. */
3721 bytes = 0;
3722# if ENABLE_UNISTDIO
3223 characters = 0; 3723 characters = 0;
3724# endif
3224 } 3725 }
3225# endif 3726# endif
3226 3727
3227# if !DCHAR_IS_TCHAR 3728# if !DCHAR_IS_TCHAR
3228 /* Convert the string into a piece of temporary memory. */
3229 tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
3230 if (tmpsrc == NULL)
3231 goto out_of_memory;
3232 { 3729 {
3233 TCHAR_T *tmpptr = tmpsrc; 3730 TCHAR_T *tmpsrc;
3234 size_t remaining; 3731
3732 /* Convert the string into a piece of temporary memory. */
3733 tmpsrc = (TCHAR_T *) malloc (bytes * sizeof (TCHAR_T));
3734 if (tmpsrc == NULL)
3735 goto out_of_memory;
3736 {
3737 TCHAR_T *tmpptr = tmpsrc;
3738 size_t remaining;
3235# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3739# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
3236 mbstate_t state; 3740 mbstate_t state;
3237 mbszero (&state); 3741 mbszero (&state);
3238# endif 3742# endif
3239 for (remaining = characters; remaining > 0; ) 3743 for (remaining = bytes; remaining > 0; )
3240 { 3744 {
3241 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ 3745 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3242 int count; 3746 int count;
3243 3747
3244 if (*arg == 0) 3748 if (*arg == 0)
3245 abort (); 3749 abort ();
3246 count = local_wcrtomb (cbuf, *arg, &state); 3750 count = local_wcrtomb (cbuf, *arg, &state);
3247 if (count <= 0) 3751 if (count <= 0)
3248 /* Inconsistency. */ 3752 /* Inconsistency. */
3249 abort (); 3753 abort ();
3250 memcpy (tmpptr, cbuf, count); 3754 memcpy (tmpptr, cbuf, count);
3251 tmpptr += count; 3755 tmpptr += count;
3252 arg++; 3756 arg++;
3253 remaining -= count; 3757 remaining -= count;
3758 }
3759 if (!(arg == arg_end))
3760 abort ();
3761 }
3762
3763 /* Convert from TCHAR_T[] to DCHAR_T[]. */
3764 tmpdst =
3765 DCHAR_CONV_FROM_ENCODING (locale_charset (),
3766 iconveh_question_mark,
3767 tmpsrc, bytes,
3768 NULL,
3769 NULL, &tmpdst_len);
3770 if (tmpdst == NULL)
3771 {
3772 free (tmpsrc);
3773 goto fail_with_errno;
3254 } 3774 }
3255 if (!(arg == arg_end)) 3775 free (tmpsrc);
3256 abort ();
3257 } 3776 }
3258
3259 /* Convert from TCHAR_T[] to DCHAR_T[]. */
3260 tmpdst =
3261 DCHAR_CONV_FROM_ENCODING (locale_charset (),
3262 iconveh_question_mark,
3263 tmpsrc, characters,
3264 NULL,
3265 NULL, &tmpdst_len);
3266 if (tmpdst == NULL)
3267 {
3268 free (tmpsrc);
3269 goto fail_with_errno;
3270 }
3271 free (tmpsrc);
3272# endif 3777# endif
3273 3778
3274 if (has_width) 3779 if (has_width)
@@ -3277,11 +3782,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3277 /* Outside POSIX, it's preferable to compare the width 3782 /* Outside POSIX, it's preferable to compare the width
3278 against the number of _characters_ of the converted 3783 against the number of _characters_ of the converted
3279 value. */ 3784 value. */
3280 w = DCHAR_MBSNLEN (result + length, characters); 3785# if DCHAR_IS_TCHAR
3786 w = characters;
3787# else
3788 w = DCHAR_MBSNLEN (tmpdst, tmpdst_len);
3789# endif
3281# else 3790# else
3282 /* The width is compared against the number of _bytes_ 3791 /* The width is compared against the number of _bytes_
3283 of the converted value, says POSIX. */ 3792 of the converted value, says POSIX. */
3284 w = characters; 3793 w = bytes;
3285# endif 3794# endif
3286 } 3795 }
3287 else 3796 else
@@ -3291,7 +3800,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3291 if (w < width && !(flags & FLAG_LEFT)) 3800 if (w < width && !(flags & FLAG_LEFT))
3292 { 3801 {
3293 size_t n = width - w; 3802 size_t n = width - w;
3803# if DCHAR_IS_TCHAR
3294 ENSURE_ALLOCATION (xsum (length, n)); 3804 ENSURE_ALLOCATION (xsum (length, n));
3805# else
3806 ENSURE_ALLOCATION_ELSE (xsum (length, n),
3807 { free (tmpdst); goto out_of_memory; });
3808# endif
3295 DCHAR_SET (result + length, ' ', n); 3809 DCHAR_SET (result + length, ' ', n);
3296 length += n; 3810 length += n;
3297 } 3811 }
@@ -3305,8 +3819,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3305 mbstate_t state; 3819 mbstate_t state;
3306 mbszero (&state); 3820 mbszero (&state);
3307# endif 3821# endif
3308 ENSURE_ALLOCATION (xsum (length, characters)); 3822 ENSURE_ALLOCATION (xsum (length, bytes));
3309 for (remaining = characters; remaining > 0; ) 3823 for (remaining = bytes; remaining > 0; )
3310 { 3824 {
3311 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ 3825 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3312 int count; 3826 int count;
@@ -3350,7 +3864,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3350 } 3864 }
3351# else 3865# else
3352 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len), 3866 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
3353 { free (tmpdst); goto out_of_memory; }); 3867 { free (tmpdst); goto out_of_memory; });
3354 DCHAR_CPY (result + length, tmpdst, tmpdst_len); 3868 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
3355 free (tmpdst); 3869 free (tmpdst);
3356 length += tmpdst_len; 3870 length += tmpdst_len;
@@ -3406,17 +3920,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3406 width = xsum (xtimes (width, 10), *digitp++ - '0'); 3920 width = xsum (xtimes (width, 10), *digitp++ - '0');
3407 while (digitp != dp->width_end); 3921 while (digitp != dp->width_end);
3408 } 3922 }
3923 if (width > (size_t) INT_MAX)
3924 goto overflow;
3409 has_width = 1; 3925 has_width = 1;
3410 } 3926 }
3411 3927
3412 /* %lc in vasnprintf. See the specification of fprintf. */ 3928 /* %lc in vasnprintf. See the specification of fprintf. */
3413 { 3929 {
3414 wchar_t arg = (wchar_t) a.arg[dp->arg_index].a.a_wide_char; 3930 wchar_t arg = (wchar_t) a.arg[dp->arg_index].a.a_wide_char;
3931 size_t bytes;
3932# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3415 size_t characters; 3933 size_t characters;
3934# endif
3416# if !DCHAR_IS_TCHAR 3935# if !DCHAR_IS_TCHAR
3417 /* This code assumes that TCHAR_T is 'char'. */ 3936 /* This code assumes that TCHAR_T is 'char'. */
3418 static_assert (sizeof (TCHAR_T) == 1); 3937 static_assert (sizeof (TCHAR_T) == 1);
3419 TCHAR_T tmpsrc[64]; /* Assume MB_CUR_MAX <= 64. */
3420 DCHAR_T *tmpdst; 3938 DCHAR_T *tmpdst;
3421 size_t tmpdst_len; 3939 size_t tmpdst_len;
3422# endif 3940# endif
@@ -3427,7 +3945,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3427# endif 3945# endif
3428 { 3946 {
3429 /* Count the number of bytes. */ 3947 /* Count the number of bytes. */
3430 characters = 0;
3431 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ 3948 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3432 int count; 3949 int count;
3433# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3950# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
@@ -3439,43 +3956,54 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3439 if (count < 0) 3956 if (count < 0)
3440 /* Cannot convert. */ 3957 /* Cannot convert. */
3441 goto fail_with_EILSEQ; 3958 goto fail_with_EILSEQ;
3442 characters = count; 3959 bytes = count;
3960# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3961 characters = mbsnlen (cbuf, count);
3962# endif
3443 } 3963 }
3444# if DCHAR_IS_TCHAR 3964# if DCHAR_IS_TCHAR
3445 else 3965 else
3446 { 3966 {
3447 /* The number of bytes doesn't matter. */ 3967 /* The number of bytes and characters doesn't matter,
3968 because !has_width and therefore width==0. */
3969 bytes = 0;
3970# if ENABLE_UNISTDIO
3448 characters = 0; 3971 characters = 0;
3972# endif
3449 } 3973 }
3450# endif 3974# endif
3451 3975
3452# if !DCHAR_IS_TCHAR 3976# if !DCHAR_IS_TCHAR
3453 /* Convert the string into a piece of temporary memory. */ 3977 {
3454 if (characters > 0) 3978 TCHAR_T tmpsrc[64]; /* Assume MB_CUR_MAX <= 64. */
3455 { 3979
3456 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ 3980 /* Convert the string into a piece of temporary memory. */
3457 int count; 3981 if (bytes > 0)
3982 {
3983 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3984 int count;
3458# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3985# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
3459 mbstate_t state; 3986 mbstate_t state;
3460 mbszero (&state); 3987 mbszero (&state);
3461# endif 3988# endif
3462 3989
3463 count = local_wcrtomb (cbuf, arg, &state); 3990 count = local_wcrtomb (cbuf, arg, &state);
3464 if (count <= 0) 3991 if (count <= 0)
3465 /* Inconsistency. */ 3992 /* Inconsistency. */
3466 abort (); 3993 abort ();
3467 memcpy (tmpsrc, cbuf, count); 3994 memcpy (tmpsrc, cbuf, count);
3468 } 3995 }
3469 3996
3470 /* Convert from TCHAR_T[] to DCHAR_T[]. */ 3997 /* Convert from TCHAR_T[] to DCHAR_T[]. */
3471 tmpdst = 3998 tmpdst =
3472 DCHAR_CONV_FROM_ENCODING (locale_charset (), 3999 DCHAR_CONV_FROM_ENCODING (locale_charset (),
3473 iconveh_question_mark, 4000 iconveh_question_mark,
3474 tmpsrc, characters, 4001 tmpsrc, bytes,
3475 NULL, 4002 NULL,
3476 NULL, &tmpdst_len); 4003 NULL, &tmpdst_len);
3477 if (tmpdst == NULL) 4004 if (tmpdst == NULL)
3478 goto fail_with_errno; 4005 goto fail_with_errno;
4006 }
3479# endif 4007# endif
3480 4008
3481 if (has_width) 4009 if (has_width)
@@ -3484,11 +4012,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3484 /* Outside POSIX, it's preferable to compare the width 4012 /* Outside POSIX, it's preferable to compare the width
3485 against the number of _characters_ of the converted 4013 against the number of _characters_ of the converted
3486 value. */ 4014 value. */
3487 w = DCHAR_MBSNLEN (result + length, characters); 4015# if DCHAR_IS_TCHAR
4016 w = characters;
4017# else
4018 w = DCHAR_MBSNLEN (tmpdst, tmpdst_len);
4019# endif
3488# else 4020# else
3489 /* The width is compared against the number of _bytes_ 4021 /* The width is compared against the number of _bytes_
3490 of the converted value, says POSIX. */ 4022 of the converted value, says POSIX. */
3491 w = characters; 4023 w = bytes;
3492# endif 4024# endif
3493 } 4025 }
3494 else 4026 else
@@ -3498,7 +4030,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3498 if (w < width && !(flags & FLAG_LEFT)) 4030 if (w < width && !(flags & FLAG_LEFT))
3499 { 4031 {
3500 size_t n = width - w; 4032 size_t n = width - w;
4033# if DCHAR_IS_TCHAR
3501 ENSURE_ALLOCATION (xsum (length, n)); 4034 ENSURE_ALLOCATION (xsum (length, n));
4035# else
4036 ENSURE_ALLOCATION_ELSE (xsum (length, n),
4037 { free (tmpdst); goto out_of_memory; });
4038# endif
3502 DCHAR_SET (result + length, ' ', n); 4039 DCHAR_SET (result + length, ' ', n);
3503 length += n; 4040 length += n;
3504 } 4041 }
@@ -3507,8 +4044,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3507 if (has_width) 4044 if (has_width)
3508 { 4045 {
3509 /* We know the number of bytes in advance. */ 4046 /* We know the number of bytes in advance. */
3510 ENSURE_ALLOCATION (xsum (length, characters)); 4047 ENSURE_ALLOCATION (xsum (length, bytes));
3511 if (characters > 0) 4048 if (bytes > 0)
3512 { 4049 {
3513 int count; 4050 int count;
3514# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 4051# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
@@ -3542,7 +4079,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3542 } 4079 }
3543# else 4080# else
3544 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len), 4081 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
3545 { free (tmpdst); goto out_of_memory; }); 4082 { free (tmpdst); goto out_of_memory; });
3546 DCHAR_CPY (result + length, tmpdst, tmpdst_len); 4083 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
3547 free (tmpdst); 4084 free (tmpdst);
3548 length += tmpdst_len; 4085 length += tmpdst_len;
@@ -3594,6 +4131,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3594 width = xsum (xtimes (width, 10), *digitp++ - '0'); 4131 width = xsum (xtimes (width, 10), *digitp++ - '0');
3595 while (digitp != dp->width_end); 4132 while (digitp != dp->width_end);
3596 } 4133 }
4134 if (width > (size_t) INT_MAX)
4135 goto overflow;
3597 } 4136 }
3598 4137
3599 /* %c in vasnwprintf. See the specification of fwprintf. */ 4138 /* %c in vasnwprintf. See the specification of fwprintf. */
@@ -3608,24 +4147,26 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3608 /* Invalid or incomplete multibyte character. */ 4147 /* Invalid or incomplete multibyte character. */
3609 goto fail_with_EILSEQ; 4148 goto fail_with_EILSEQ;
3610 4149
3611 if (1 < width && !(flags & FLAG_LEFT)) 4150 {
3612 { 4151 size_t total = (1 < width ? width : 1);
3613 size_t n = width - 1; 4152 ENSURE_ALLOCATION (xsum (length, total));
3614 ENSURE_ALLOCATION (xsum (length, n)); 4153
3615 DCHAR_SET (result + length, ' ', n); 4154 if (1 < width && !(flags & FLAG_LEFT))
3616 length += n; 4155 {
3617 } 4156 size_t n = width - 1;
4157 DCHAR_SET (result + length, ' ', n);
4158 length += n;
4159 }
3618 4160
3619 ENSURE_ALLOCATION (xsum (length, 1)); 4161 result[length++] = wc;
3620 result[length++] = wc;
3621 4162
3622 if (1 < width && (flags & FLAG_LEFT)) 4163 if (1 < width && (flags & FLAG_LEFT))
3623 { 4164 {
3624 size_t n = width - 1; 4165 size_t n = width - 1;
3625 ENSURE_ALLOCATION (xsum (length, n)); 4166 DCHAR_SET (result + length, ' ', n);
3626 DCHAR_SET (result + length, ' ', n); 4167 length += n;
3627 length += n; 4168 }
3628 } 4169 }
3629 } 4170 }
3630 } 4171 }
3631#endif 4172#endif
@@ -3682,6 +4223,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3682 width = xsum (xtimes (width, 10), *digitp++ - '0'); 4223 width = xsum (xtimes (width, 10), *digitp++ - '0');
3683 while (digitp != dp->width_end); 4224 while (digitp != dp->width_end);
3684 } 4225 }
4226 if (width > (size_t) INT_MAX)
4227 goto overflow;
3685 has_width = 1; 4228 has_width = 1;
3686 } 4229 }
3687 4230
@@ -3933,7 +4476,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3933 { 4476 {
3934 size_t n = xsum (length, count); 4477 size_t n = xsum (length, count);
3935 4478
3936 ENSURE_ALLOCATION (n); 4479 ENSURE_ALLOCATION_ELSE (n,
4480 { if (tmp != tmpbuf) free (tmp); goto out_of_memory; });
3937 } 4481 }
3938 4482
3939 /* Append the result. */ 4483 /* Append the result. */
@@ -3996,6 +4540,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3996 width = xsum (xtimes (width, 10), *digitp++ - '0'); 4540 width = xsum (xtimes (width, 10), *digitp++ - '0');
3997 while (digitp != dp->width_end); 4541 while (digitp != dp->width_end);
3998 } 4542 }
4543 if (width > (size_t) INT_MAX)
4544 goto overflow;
3999 } 4545 }
4000 4546
4001 has_precision = 0; 4547 has_precision = 0;
@@ -4423,7 +4969,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4423 { 4969 {
4424 size_t n = xsum (length, count); 4970 size_t n = xsum (length, count);
4425 4971
4426 ENSURE_ALLOCATION (n); 4972 ENSURE_ALLOCATION_ELSE (n,
4973 { if (tmp != tmpbuf) free (tmp); goto out_of_memory; });
4427 } 4974 }
4428 4975
4429 /* Append the result. */ 4976 /* Append the result. */
@@ -4501,6 +5048,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4501 width = xsum (xtimes (width, 10), *digitp++ - '0'); 5048 width = xsum (xtimes (width, 10), *digitp++ - '0');
4502 while (digitp != dp->width_end); 5049 while (digitp != dp->width_end);
4503 } 5050 }
5051 if (width > (size_t) INT_MAX)
5052 goto overflow;
4504 } 5053 }
4505 5054
4506 has_precision = 0; 5055 has_precision = 0;
@@ -4587,6 +5136,17 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4587 } 5136 }
4588 } 5137 }
4589# endif 5138# endif
5139 /* Account for thousands separators. */
5140 if (flags & FLAG_GROUP)
5141 {
5142 /* A thousands separator needs to be inserted at most every 2 digits.
5143 This is the case in the ta_IN locale. */
5144# if WIDE_CHAR_VERSION
5145 tmp_length = xsum (tmp_length, tmp_length / 2 * THOUSEP_WCHAR_MAXLEN);
5146# else
5147 tmp_length = xsum (tmp_length, tmp_length / 2 * THOUSEP_CHAR_MAXLEN);
5148# endif
5149 }
4590 /* Account for sign, decimal point etc. */ 5150 /* Account for sign, decimal point etc. */
4591 tmp_length = xsum (tmp_length, 12); 5151 tmp_length = xsum (tmp_length, 12);
4592 5152
@@ -4682,12 +5242,84 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4682 ndigits = strlen (digits); 5242 ndigits = strlen (digits);
4683 5243
4684 if (ndigits > precision) 5244 if (ndigits > precision)
4685 do 5245 {
4686 { 5246 /* Number of digits before the decimal point. */
4687 --ndigits; 5247 size_t intpart_digits = ndigits - precision;
4688 *p++ = digits[ndigits]; 5248
4689 } 5249 const DCHAR_T *thousep = NULL;
4690 while (ndigits > precision); 5250 DCHAR_T thousep_buf[10];
5251# if !WIDE_CHAR_VERSION
5252 size_t thousep_len = 0;
5253# endif
5254 const signed char *grouping;
5255 size_t insert = 0;
5256
5257 if ((flags & FLAG_GROUP) && (intpart_digits > 1))
5258 {
5259 /* Determine the thousands separator and
5260 the grouping rule of the current locale. */
5261# if WIDE_CHAR_VERSION
5262 /* DCHAR_T is wchar_t. */
5263 thousep = thousands_separator_wchar (thousep_buf);
5264# define thousep_len 1
5265# elif defined DCHAR_CONV_FROM_ENCODING
5266 /* DCHAR_T is uintN_t. */
5267 thousep = thousands_separator_DCHAR (thousep_buf);
5268 thousep_len = DCHAR_STRLEN (thousep);
5269# else
5270 /* DCHAR_T is char. */
5271 thousep = thousands_separator_char (thousep_buf);
5272 thousep_len = strlen (thousep);
5273# endif
5274 if (*thousep == 0)
5275 thousep = NULL;
5276 if (thousep != NULL)
5277 {
5278 grouping = grouping_rule ();
5279 insert =
5280 num_thousands_separators (grouping, intpart_digits);
5281 }
5282 }
5283
5284 const char *digitp = digits + precision;
5285 DCHAR_T *p_before_intpart = p;
5286 p += intpart_digits + insert * thousep_len;
5287 DCHAR_T *p_after_intpart = p;
5288 if (insert > 0) /* implies (flag & FLAG_GROUP) && (thousep != NULL) */
5289 {
5290 const signed char *g = grouping;
5291 for (;;)
5292 {
5293 int h = *g;
5294 if (h <= 0)
5295 abort ();
5296 int i = h;
5297 do
5298 *--p = *digitp++;
5299 while (--i > 0);
5300# if WIDE_CHAR_VERSION
5301 *--p = thousep[0];
5302# else
5303 p -= thousep_len;
5304 DCHAR_CPY (p, thousep, thousep_len);
5305# endif
5306 insert--;
5307 if (insert == 0)
5308 break;
5309 if (g[1] != 0)
5310 g++;
5311 }
5312 }
5313 for (;;)
5314 {
5315 *--p = *digitp++;
5316 if (p == p_before_intpart)
5317 break;
5318 }
5319 p = p_after_intpart;
5320 ndigits = precision;
5321# undef thousep_len
5322 }
4691 else 5323 else
4692 *p++ = '0'; 5324 *p++ = '0';
4693 /* Here ndigits <= precision. */ 5325 /* Here ndigits <= precision. */
@@ -4940,10 +5572,84 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4940 digits without trailing zeroes. */ 5572 digits without trailing zeroes. */
4941 if (exponent >= 0) 5573 if (exponent >= 0)
4942 { 5574 {
4943 size_t ecount = exponent + 1; 5575 /* Number of digits before the decimal point. */
4944 /* Note: count <= precision = ndigits. */ 5576 size_t intpart_digits = exponent + 1;
4945 for (; ecount > 0; ecount--) 5577 /* Note: intpart_digits <= precision = ndigits. */
4946 *p++ = digits[--ndigits]; 5578
5579 const DCHAR_T *thousep = NULL;
5580 DCHAR_T thousep_buf[10];
5581# if !WIDE_CHAR_VERSION
5582 size_t thousep_len = 0;
5583# endif
5584 const signed char *grouping;
5585 size_t insert = 0;
5586
5587 if ((flags & FLAG_GROUP) && (intpart_digits > 1))
5588 {
5589 /* Determine the thousands separator and
5590 the grouping rule of the current locale. */
5591# if WIDE_CHAR_VERSION
5592 /* DCHAR_T is wchar_t. */
5593 thousep = thousands_separator_wchar (thousep_buf);
5594# define thousep_len 1
5595# elif defined DCHAR_CONV_FROM_ENCODING
5596 /* DCHAR_T is uintN_t. */
5597 thousep = thousands_separator_DCHAR (thousep_buf);
5598 thousep_len = DCHAR_STRLEN (thousep);
5599# else
5600 /* DCHAR_T is char. */
5601 thousep = thousands_separator_char (thousep_buf);
5602 thousep_len = strlen (thousep);
5603# endif
5604 if (*thousep == 0)
5605 thousep = NULL;
5606 if (thousep != NULL)
5607 {
5608 grouping = grouping_rule ();
5609 insert =
5610 num_thousands_separators (grouping, intpart_digits);
5611 }
5612 }
5613
5614 const char *digitp = digits + ndigits - intpart_digits;
5615 DCHAR_T *p_before_intpart = p;
5616 p += intpart_digits + insert * thousep_len;
5617 DCHAR_T *p_after_intpart = p;
5618 if (insert > 0) /* implies (flag & FLAG_GROUP) && (thousep != NULL) */
5619 {
5620 const signed char *g = grouping;
5621 for (;;)
5622 {
5623 int h = *g;
5624 if (h <= 0)
5625 abort ();
5626 int i = h;
5627 do
5628 *--p = *digitp++;
5629 while (--i > 0);
5630# if WIDE_CHAR_VERSION
5631 *--p = thousep[0];
5632# else
5633 p -= thousep_len;
5634 DCHAR_CPY (p, thousep, thousep_len);
5635# endif
5636 insert--;
5637 if (insert == 0)
5638 break;
5639 if (g[1] != 0)
5640 g++;
5641 }
5642 }
5643 for (;;)
5644 {
5645 *--p = *digitp++;
5646 if (p == p_before_intpart)
5647 break;
5648 }
5649 p = p_after_intpart;
5650 ndigits -= intpart_digits;
5651# undef thousep_len
5652
4947 if ((flags & FLAG_ALT) || ndigits > nzeroes) 5653 if ((flags & FLAG_ALT) || ndigits > nzeroes)
4948 { 5654 {
4949 *p++ = decimal_point_char (); 5655 *p++ = decimal_point_char ();
@@ -5144,12 +5850,84 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5144 ndigits = strlen (digits); 5850 ndigits = strlen (digits);
5145 5851
5146 if (ndigits > precision) 5852 if (ndigits > precision)
5147 do 5853 {
5148 { 5854 /* Number of digits before the decimal point. */
5149 --ndigits; 5855 size_t intpart_digits = ndigits - precision;
5150 *p++ = digits[ndigits]; 5856
5151 } 5857 const DCHAR_T *thousep = NULL;
5152 while (ndigits > precision); 5858 DCHAR_T thousep_buf[10];
5859# if !WIDE_CHAR_VERSION
5860 size_t thousep_len = 0;
5861# endif
5862 const signed char *grouping;
5863 size_t insert = 0;
5864
5865 if ((flags & FLAG_GROUP) && (intpart_digits > 1))
5866 {
5867 /* Determine the thousands separator and
5868 the grouping rule of the current locale. */
5869# if WIDE_CHAR_VERSION
5870 /* DCHAR_T is wchar_t. */
5871 thousep = thousands_separator_wchar (thousep_buf);
5872# define thousep_len 1
5873# elif defined DCHAR_CONV_FROM_ENCODING
5874 /* DCHAR_T is uintN_t. */
5875 thousep = thousands_separator_DCHAR (thousep_buf);
5876 thousep_len = DCHAR_STRLEN (thousep);
5877# else
5878 /* DCHAR_T is char. */
5879 thousep = thousands_separator_char (thousep_buf);
5880 thousep_len = strlen (thousep);
5881# endif
5882 if (*thousep == 0)
5883 thousep = NULL;
5884 if (thousep != NULL)
5885 {
5886 grouping = grouping_rule ();
5887 insert =
5888 num_thousands_separators (grouping, intpart_digits);
5889 }
5890 }
5891
5892 const char *digitp = digits + precision;
5893 DCHAR_T *p_before_intpart = p;
5894 p += intpart_digits + insert * thousep_len;
5895 DCHAR_T *p_after_intpart = p;
5896 if (insert > 0) /* implies (flag & FLAG_GROUP) && (thousep != NULL) */
5897 {
5898 const signed char *g = grouping;
5899 for (;;)
5900 {
5901 int h = *g;
5902 if (h <= 0)
5903 abort ();
5904 int i = h;
5905 do
5906 *--p = *digitp++;
5907 while (--i > 0);
5908# if WIDE_CHAR_VERSION
5909 *--p = thousep[0];
5910# else
5911 p -= thousep_len;
5912 DCHAR_CPY (p, thousep, thousep_len);
5913# endif
5914 insert--;
5915 if (insert == 0)
5916 break;
5917 if (g[1] != 0)
5918 g++;
5919 }
5920 }
5921 for (;;)
5922 {
5923 *--p = *digitp++;
5924 if (p == p_before_intpart)
5925 break;
5926 }
5927 p = p_after_intpart;
5928 ndigits = precision;
5929# undef thousep_len
5930 }
5153 else 5931 else
5154 *p++ = '0'; 5932 *p++ = '0';
5155 /* Here ndigits <= precision. */ 5933 /* Here ndigits <= precision. */
@@ -5410,10 +6188,84 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5410 digits without trailing zeroes. */ 6188 digits without trailing zeroes. */
5411 if (exponent >= 0) 6189 if (exponent >= 0)
5412 { 6190 {
5413 size_t ecount = exponent + 1; 6191 /* Number of digits before the decimal point. */
5414 /* Note: ecount <= precision = ndigits. */ 6192 size_t intpart_digits = exponent + 1;
5415 for (; ecount > 0; ecount--) 6193 /* Note: intpart_digits <= precision = ndigits. */
5416 *p++ = digits[--ndigits]; 6194
6195 const DCHAR_T *thousep = NULL;
6196 DCHAR_T thousep_buf[10];
6197# if !WIDE_CHAR_VERSION
6198 size_t thousep_len = 0;
6199# endif
6200 const signed char *grouping;
6201 size_t insert = 0;
6202
6203 if ((flags & FLAG_GROUP) && (intpart_digits > 1))
6204 {
6205 /* Determine the thousands separator and
6206 the grouping rule of the current locale. */
6207# if WIDE_CHAR_VERSION
6208 /* DCHAR_T is wchar_t. */
6209 thousep = thousands_separator_wchar (thousep_buf);
6210# define thousep_len 1
6211# elif defined DCHAR_CONV_FROM_ENCODING
6212 /* DCHAR_T is uintN_t. */
6213 thousep = thousands_separator_DCHAR (thousep_buf);
6214 thousep_len = DCHAR_STRLEN (thousep);
6215# else
6216 /* DCHAR_T is char. */
6217 thousep = thousands_separator_char (thousep_buf);
6218 thousep_len = strlen (thousep);
6219# endif
6220 if (*thousep == 0)
6221 thousep = NULL;
6222 if (thousep != NULL)
6223 {
6224 grouping = grouping_rule ();
6225 insert =
6226 num_thousands_separators (grouping, intpart_digits);
6227 }
6228 }
6229
6230 const char *digitp = digits + ndigits - intpart_digits;
6231 DCHAR_T *p_before_intpart = p;
6232 p += intpart_digits + insert * thousep_len;
6233 DCHAR_T *p_after_intpart = p;
6234 if (insert > 0) /* implies (flag & FLAG_GROUP) && (thousep != NULL) */
6235 {
6236 const signed char *g = grouping;
6237 for (;;)
6238 {
6239 int h = *g;
6240 if (h <= 0)
6241 abort ();
6242 int i = h;
6243 do
6244 *--p = *digitp++;
6245 while (--i > 0);
6246# if WIDE_CHAR_VERSION
6247 *--p = thousep[0];
6248# else
6249 p -= thousep_len;
6250 DCHAR_CPY (p, thousep, thousep_len);
6251# endif
6252 insert--;
6253 if (insert == 0)
6254 break;
6255 if (g[1] != 0)
6256 g++;
6257 }
6258 }
6259 for (;;)
6260 {
6261 *--p = *digitp++;
6262 if (p == p_before_intpart)
6263 break;
6264 }
6265 p = p_after_intpart;
6266 ndigits -= intpart_digits;
6267# undef thousep_len
6268
5417 if ((flags & FLAG_ALT) || ndigits > nzeroes) 6269 if ((flags & FLAG_ALT) || ndigits > nzeroes)
5418 { 6270 {
5419 *p++ = decimal_point_char (); 6271 *p++ = decimal_point_char ();
@@ -5606,7 +6458,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5606 { 6458 {
5607 size_t n = xsum (length, count); 6459 size_t n = xsum (length, count);
5608 6460
5609 ENSURE_ALLOCATION (n); 6461 ENSURE_ALLOCATION_ELSE (n,
6462 { if (tmp != tmpbuf) free (tmp); goto out_of_memory; });
5610 } 6463 }
5611 6464
5612 /* Append the result. */ 6465 /* Append the result. */
@@ -5620,13 +6473,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5620 { 6473 {
5621 arg_type type = a.arg[dp->arg_index].type; 6474 arg_type type = a.arg[dp->arg_index].type;
5622 int flags = dp->flags; 6475 int flags = dp->flags;
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 6476#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 || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
5624 int has_width; 6477 int has_width;
5625#endif 6478#endif
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 6479#if !USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_FLAG_LEFTADJUST || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
5627 size_t width; 6480 size_t width;
5628#endif 6481#endif
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 6482#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (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 || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
5630 int has_precision; 6483 int has_precision;
5631 size_t precision; 6484 size_t precision;
5632#endif 6485#endif
@@ -5635,9 +6488,14 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5635#else 6488#else
5636# define prec_ourselves 0 6489# define prec_ourselves 0
5637#endif 6490#endif
6491#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
6492 int group_ourselves;
6493#else
6494# define group_ourselves 0
6495#endif
5638#if (WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST 6496#if (WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST
5639# define pad_ourselves 1 6497# define pad_ourselves 1
5640#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION 6498#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
5641 int pad_ourselves; 6499 int pad_ourselves;
5642#else 6500#else
5643# define pad_ourselves 0 6501# define pad_ourselves 0
@@ -5652,10 +6510,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5652 TCHAR_T *tmp; 6510 TCHAR_T *tmp;
5653#endif 6511#endif
5654 6512
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 6513#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 || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
5656 has_width = 0; 6514 has_width = 0;
5657#endif 6515#endif
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 6516#if !USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_FLAG_LEFTADJUST || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
5659 width = 0; 6517 width = 0;
5660 if (dp->width_start != dp->width_end) 6518 if (dp->width_start != dp->width_end)
5661 { 6519 {
@@ -5683,13 +6541,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5683 width = xsum (xtimes (width, 10), *digitp++ - '0'); 6541 width = xsum (xtimes (width, 10), *digitp++ - '0');
5684 while (digitp != dp->width_end); 6542 while (digitp != dp->width_end);
5685 } 6543 }
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 6544 if (width > (size_t) INT_MAX)
6545 goto overflow;
6546# define WIDTH_IS_CHECKED 1
6547# 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 || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
5687 has_width = 1; 6548 has_width = 1;
5688# endif 6549# endif
5689 } 6550 }
5690#endif 6551#endif
5691 6552
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 6553#if !USE_SNPRINTF || (WIDE_CHAR_VERSION && DCHAR_IS_TCHAR) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (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 || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
5693 has_precision = 0; 6554 has_precision = 0;
5694 precision = 6; 6555 precision = 6;
5695 if (dp->precision_start != dp->precision_end) 6556 if (dp->precision_start != dp->precision_end)
@@ -5754,8 +6615,37 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5754 } 6615 }
5755#endif 6616#endif
5756 6617
6618 /* Decide whether to add the thousands separators ourselves. */
6619#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
6620 if (flags & FLAG_GROUP)
6621 {
6622 switch (dp->conversion)
6623 {
6624 case 'd': case 'i': case 'u':
6625# if NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
6626 group_ourselves = 1;
6627# else
6628 group_ourselves = prec_ourselves;
6629# endif
6630 break;
6631 case 'f': case 'F': case 'g': case 'G':
6632# if NEED_PRINTF_FLAG_GROUPING
6633 group_ourselves = 1;
6634# else
6635 group_ourselves = prec_ourselves;
6636# endif
6637 break;
6638 default:
6639 group_ourselves = 0;
6640 break;
6641 }
6642 }
6643 else
6644 group_ourselves = 0;
6645#endif
6646
5757 /* Decide whether to perform the padding ourselves. */ 6647 /* Decide whether to perform the padding ourselves. */
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) 6648#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 || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT)
5759 switch (dp->conversion) 6649 switch (dp->conversion)
5760 { 6650 {
5761# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO 6651# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
@@ -5772,7 +6662,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5772 pad_ourselves = 1; 6662 pad_ourselves = 1;
5773 break; 6663 break;
5774 default: 6664 default:
5775 pad_ourselves = prec_ourselves; 6665 pad_ourselves = prec_ourselves | group_ourselves;
5776 break; 6666 break;
5777 } 6667 }
5778#endif 6668#endif
@@ -5805,14 +6695,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5805 sprintf. */ 6695 sprintf. */
5806 fbp = buf; 6696 fbp = buf;
5807 *fbp++ = '%'; 6697 *fbp++ = '%';
5808#if NEED_PRINTF_FLAG_GROUPING 6698 if ((flags & FLAG_GROUP) && !group_ourselves)
5809 /* The underlying implementation doesn't support the ' flag.
5810 Produce no grouping characters in this case; this is
5811 acceptable because the grouping is locale dependent. */
5812#else
5813 if (flags & FLAG_GROUP)
5814 *fbp++ = '\''; 6699 *fbp++ = '\'';
5815#endif
5816 if (flags & FLAG_LEFT) 6700 if (flags & FLAG_LEFT)
5817 *fbp++ = '-'; 6701 *fbp++ = '-';
5818 if (flags & FLAG_SHOWSIGN) 6702 if (flags & FLAG_SHOWSIGN)
@@ -5832,6 +6716,43 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5832 if (dp->width_start != dp->width_end) 6716 if (dp->width_start != dp->width_end)
5833 { 6717 {
5834 size_t n = dp->width_end - dp->width_start; 6718 size_t n = dp->width_end - dp->width_start;
6719#if !WIDTH_IS_CHECKED
6720 size_t width;
6721 /* Reject an out-of-range width.
6722 The underlying SNPRINTF already does this on some
6723 platforms (glibc, musl, macOS, FreeBSD, NetBSD,
6724 OpenBSD, Cygwin, Solaris, MSVC). However, on others
6725 (AIX, mingw), it doesn't; thus this vasnprintf
6726 invocation would succeed and produce a wrong result.
6727 So, this is redundant on some platforms, but it's a
6728 quick check anyway. */
6729 if (dp->width_arg_index != ARG_NONE)
6730 {
6731 int arg;
6732
6733 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
6734 abort ();
6735 arg = a.arg[dp->width_arg_index].a.a_int;
6736 width = arg;
6737 if (arg < 0)
6738 {
6739 /* "A negative field width is taken as a '-' flag
6740 followed by a positive field width." */
6741 width = -width;
6742 }
6743 }
6744 else
6745 {
6746 const FCHAR_T *digitp = dp->width_start;
6747
6748 width = 0;
6749 do
6750 width = xsum (xtimes (width, 10), *digitp++ - '0');
6751 while (digitp != dp->width_end);
6752 }
6753 if (width > (size_t) INT_MAX)
6754 goto overflow;
6755#endif
5835 /* The width specification is known to consist only 6756 /* The width specification is known to consist only
5836 of standard ASCII characters. */ 6757 of standard ASCII characters. */
5837 if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) 6758 if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
@@ -5870,7 +6791,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5870 } 6791 }
5871 } 6792 }
5872 6793
5873 switch (type) 6794 switch (+type)
5874 { 6795 {
5875 case TYPE_LONGLONGINT: 6796 case TYPE_LONGLONGINT:
5876 case TYPE_ULONGLONGINT: 6797 case TYPE_ULONGLONGINT:
@@ -5984,9 +6905,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5984 #if HAVE_WINT_T 6905 #if HAVE_WINT_T
5985 case TYPE_WIDE_CHAR: 6906 case TYPE_WIDE_CHAR:
5986 #endif 6907 #endif
5987 #if HAVE_WCHAR_T
5988 case TYPE_WIDE_STRING: 6908 case TYPE_WIDE_STRING:
5989 #endif
5990 *fbp++ = 'l'; 6909 *fbp++ = 'l';
5991 break; 6910 break;
5992 case TYPE_LONGDOUBLE: 6911 case TYPE_LONGDOUBLE:
@@ -6168,7 +7087,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6168#endif 7087#endif
6169 7088
6170 errno = 0; 7089 errno = 0;
6171 switch (type) 7090 switch (+type)
6172 { 7091 {
6173 case TYPE_SCHAR: 7092 case TYPE_SCHAR:
6174 { 7093 {
@@ -6358,14 +7277,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6358 SNPRINTF_BUF (arg); 7277 SNPRINTF_BUF (arg);
6359 } 7278 }
6360 break; 7279 break;
6361#if HAVE_WCHAR_T
6362 case TYPE_WIDE_STRING: 7280 case TYPE_WIDE_STRING:
6363 { 7281 {
6364 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; 7282 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
6365 SNPRINTF_BUF (arg); 7283 SNPRINTF_BUF (arg);
6366 } 7284 }
6367 break; 7285 break;
6368#endif
6369 case TYPE_POINTER: 7286 case TYPE_POINTER:
6370 { 7287 {
6371 void *arg = a.arg[dp->arg_index].a.a_pointer; 7288 void *arg = a.arg[dp->arg_index].a.a_pointer;
@@ -6539,10 +7456,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6539 || *prec_ptr == ' ')) 7456 || *prec_ptr == ' '))
6540 prefix_count = 1; 7457 prefix_count = 1;
6541 /* Put the additional zeroes after the 0x prefix if 7458 /* Put the additional zeroes after the 0x prefix if
6542 (flags & FLAG_ALT) || (dp->conversion == 'p'). */ 7459 (flags & FLAG_ALT) || (dp->conversion == 'p'), or
7460 after the 0b prefix if (flags & FLAG_ALT). */
6543 else if (count >= 2 7461 else if (count >= 2
6544 && prec_ptr[0] == '0' 7462 && prec_ptr[0] == '0'
6545 && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X')) 7463 && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'
7464 || prec_ptr[1] == 'b'
7465 || prec_ptr[1] == 'B'))
6546 prefix_count = 2; 7466 prefix_count = 2;
6547 7467
6548 move = count - prefix_count; 7468 move = count - prefix_count;
@@ -6591,6 +7511,135 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6591 } 7511 }
6592#endif 7512#endif
6593 7513
7514#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
7515 if (group_ourselves) /* implies (flags & FLAG_GROUP) */
7516 /* Handle the grouping. */
7517 switch (dp->conversion)
7518 {
7519 /* These are the only conversion to which grouping
7520 applies. */
7521 case 'd': case 'i': case 'u':
7522 case 'f': case 'F': case 'g': case 'G':
7523 {
7524 /* Determine the thousands separator of the current
7525 locale. */
7526 const TCHAR_T *thousep;
7527 TCHAR_T thousep_buf[10];
7528
7529# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
7530 /* TCHAR_T is wchar_t. */
7531 thousep = thousands_separator_wchar (thousep_buf);
7532# else
7533 /* TCHAR_T is char. */
7534 thousep = thousands_separator_char (thousep_buf);
7535# endif
7536
7537 /* Nothing to do in locales where thousep is the empty
7538 string. */
7539 if (*thousep != 0)
7540 {
7541 /* Since FLAG_LOCALIZED is only supported on glibc
7542 systems, here we can assume that all digits are
7543 the ASCII digits '0'..'9'. */
7544 TCHAR_T *number_ptr =
7545# if USE_SNPRINTF
7546 (TCHAR_T *) (result + length);
7547# else
7548 tmp;
7549# endif
7550 TCHAR_T *end_ptr = number_ptr + count;
7551
7552 /* Find where the leading digits start. */
7553 TCHAR_T *digits_ptr = number_ptr;
7554 if (count >= 1
7555 && (*digits_ptr == '-' || *digits_ptr == '+'
7556 || *digits_ptr == ' '))
7557 digits_ptr++;
7558
7559 /* Find where the leading digits end. */
7560 TCHAR_T *digits_end_ptr;
7561 switch (dp->conversion)
7562 {
7563 case 'd': case 'i': case 'u':
7564 digits_end_ptr = end_ptr;
7565 break;
7566 case 'f': case 'F': case 'g': case 'G':
7567 {
7568 TCHAR_T decimal_point = decimal_point_char ();
7569 for (digits_end_ptr = digits_ptr;
7570 digits_end_ptr < end_ptr;
7571 digits_end_ptr++)
7572 if (*digits_end_ptr == decimal_point
7573 || *digits_end_ptr == 'e')
7574 break;
7575 }
7576 break;
7577 }
7578
7579 /* Determine the number of thousands separators
7580 to insert. */
7581 const signed char *grouping = grouping_rule ();
7582 size_t insert =
7583 num_thousands_separators (grouping, digits_end_ptr - digits_ptr);
7584 if (insert > 0)
7585 {
7586# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
7587# define thousep_len 1
7588# else
7589 size_t thousep_len = strlen (thousep);
7590# endif
7591# if USE_SNPRINTF
7592 size_t digits_offset = digits_ptr - number_ptr;
7593 size_t digits_end_offset = digits_end_ptr - number_ptr;
7594 size_t n =
7595 xsum (length,
7596 (count + insert * thousep_len + TCHARS_PER_DCHAR - 1)
7597 / TCHARS_PER_DCHAR);
7598 length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
7599 ENSURE_ALLOCATION (n);
7600 length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
7601 number_ptr = (TCHAR_T *) (result + length);
7602 end_ptr = number_ptr + count;
7603 digits_ptr = number_ptr + digits_offset;
7604 digits_end_ptr = number_ptr + digits_end_offset;
7605# endif
7606
7607 count += insert * thousep_len;
7608
7609 const TCHAR_T *p = end_ptr;
7610 TCHAR_T *q = end_ptr + insert * thousep_len;
7611 while (p > digits_end_ptr)
7612 *--q = *--p;
7613 const signed char *g = grouping;
7614 for (;;)
7615 {
7616 int h = *g;
7617 if (h <= 0)
7618 abort ();
7619 int i = h;
7620 do
7621 *--q = *--p;
7622 while (--i > 0);
7623# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
7624 *--q = *thousep;
7625# else
7626 q -= thousep_len;
7627 memcpy (q, thousep, thousep_len);
7628# endif
7629 insert--;
7630 if (insert == 0)
7631 break;
7632 if (g[1] != 0)
7633 g++;
7634 }
7635 /* Here q == p. Done with the insertions. */
7636 }
7637 }
7638 }
7639 break;
7640 }
7641#endif
7642
6594#if !USE_SNPRINTF 7643#if !USE_SNPRINTF
6595 if (count >= tmp_length) 7644 if (count >= tmp_length)
6596 /* tmp_length was incorrectly calculated - fix the 7645 /* tmp_length was incorrectly calculated - fix the
@@ -6601,6 +7650,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6601#if !DCHAR_IS_TCHAR 7650#if !DCHAR_IS_TCHAR
6602 /* Convert from TCHAR_T[] to DCHAR_T[]. */ 7651 /* Convert from TCHAR_T[] to DCHAR_T[]. */
6603 if (dp->conversion == 'c' || dp->conversion == 's' 7652 if (dp->conversion == 'c' || dp->conversion == 's'
7653 || (flags & FLAG_GROUP)
6604# if __GLIBC__ >= 2 && !defined __UCLIBC__ 7654# if __GLIBC__ >= 2 && !defined __UCLIBC__
6605 || (flags & FLAG_LOCALIZED) 7655 || (flags & FLAG_LOCALIZED)
6606# endif 7656# endif
@@ -6677,7 +7727,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6677 goto fail_with_errno; 7727 goto fail_with_errno;
6678# endif 7728# endif
6679 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len), 7729 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
6680 { free (tmpdst); goto out_of_memory; }); 7730 { free (tmpdst); goto out_of_memory; });
6681 DCHAR_CPY (result + length, tmpdst, tmpdst_len); 7731 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
6682 free (tmpdst); 7732 free (tmpdst);
6683 count = tmpdst_len; 7733 count = tmpdst_len;
@@ -6742,7 +7792,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6742 /* Here count <= allocated - length. */ 7792 /* Here count <= allocated - length. */
6743 7793
6744 /* Perform padding. */ 7794 /* Perform padding. */
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 7795#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 || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
6746 if (pad_ourselves && has_width) 7796 if (pad_ourselves && has_width)
6747 { 7797 {
6748 size_t w; 7798 size_t w;
@@ -6751,6 +7801,23 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6751 against the number of _characters_ of the converted 7801 against the number of _characters_ of the converted
6752 value. */ 7802 value. */
6753 w = DCHAR_MBSNLEN (result + length, count); 7803 w = DCHAR_MBSNLEN (result + length, count);
7804# elif __GLIBC__ >= 2
7805 /* glibc prefers to compare the width against the number
7806 of characters as well, but only for numeric conversion
7807 specifiers. See
7808 <https://sourceware.org/bugzilla/show_bug.cgi?id=28943>
7809 <https://sourceware.org/bugzilla/show_bug.cgi?id=30883>
7810 <https://sourceware.org/bugzilla/show_bug.cgi?id=31542> */
7811 switch (dp->conversion)
7812 {
7813 case 'd': case 'i': case 'u':
7814 case 'f': case 'F': case 'g': case 'G':
7815 w = DCHAR_MBSNLEN (result + length, count);
7816 break;
7817 default:
7818 w = count;
7819 break;
7820 }
6754# else 7821# else
6755 /* The width is compared against the number of _bytes_ 7822 /* The width is compared against the number of _bytes_
6756 of the converted value, says POSIX. */ 7823 of the converted value, says POSIX. */
@@ -6929,17 +7996,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6929 not have this limitation. */ 7996 not have this limitation. */
6930 return result; 7997 return result;
6931 7998
6932#if USE_SNPRINTF
6933 overflow: 7999 overflow:
6934 errno = EOVERFLOW; 8000 errno = EOVERFLOW;
6935 goto fail_with_errno; 8001 goto fail_with_errno;
6936#endif
6937 8002
6938 out_of_memory: 8003 out_of_memory:
6939 errno = ENOMEM; 8004 errno = ENOMEM;
6940 goto fail_with_errno; 8005 goto fail_with_errno;
6941 8006
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) 8007#if ENABLE_UNISTDIO || (WIDE_CHAR_VERSION || !USE_SNPRINTF || (PTRDIFF_MAX > INT_MAX) || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_DIRECTIVE_LS || ENABLE_WCHAR_FALLBACK) || ((NEED_PRINTF_DIRECTIVE_LC || ENABLE_WCHAR_FALLBACK) && HAVE_WINT_T && !WIDE_CHAR_VERSION) || (NEED_WPRINTF_DIRECTIVE_C && WIDE_CHAR_VERSION)
6943 fail_with_EILSEQ: 8008 fail_with_EILSEQ:
6944 errno = EILSEQ; 8009 errno = EILSEQ;
6945 goto fail_with_errno; 8010 goto fail_with_errno;