summaryrefslogtreecommitdiffstats
path: root/gl/vasnprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/vasnprintf.c')
-rw-r--r--gl/vasnprintf.c2019
1 files changed, 1441 insertions, 578 deletions
diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c
index de204458..85e30b90 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-2026 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
@@ -178,10 +180,24 @@
178# define SNPRINTF swprintf 180# define SNPRINTF swprintf
179# endif 181# endif
180# else 182# else
181 /* Old platforms such as NetBSD 3.0, OpenBSD 3.8, HP-UX 11.00, IRIX 6.5. */ 183 /* Old platforms such as NetBSD 3.0, OpenBSD 3.8, HP-UX 11.00. */
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 (streq (&stackbuf[1], "\302"))
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 (streq (&tmp[1], "\302"))
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,26 +732,25 @@ 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 {
464 /* Here 1 <= len1 <= len2. */ 739 /* Here 1 <= len1 <= len2. */
465 size_t dlen; 740 size_t dlen;
466 mp_limb_t *dp; 741 mp_limb_t *dp;
467 size_t k, i, j;
468 742
469 dlen = len1 + len2; 743 dlen = len1 + len2;
470 dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t)); 744 dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
471 if (dp == NULL) 745 if (dp == NULL)
472 return NULL; 746 return NOMEM_PTR;
473 for (k = len2; k > 0; ) 747 for (size_t k = len2; k > 0; )
474 dp[--k] = 0; 748 dp[--k] = 0;
475 for (i = 0; i < len1; i++) 749 for (size_t i = 0; i < len1; i++)
476 { 750 {
477 mp_limb_t digit1 = p1[i]; 751 mp_limb_t digit1 = p1[i];
478 mp_twolimb_t carry = 0; 752 mp_twolimb_t carry = 0;
479 for (j = 0; j < len2; j++) 753 for (size_t j = 0; j < len2; j++)
480 { 754 {
481 mp_limb_t digit2 = p2[j]; 755 mp_limb_t digit2 = p2[j];
482 carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2; 756 carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
@@ -500,8 +774,8 @@ multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
500 the remainder. 774 the remainder.
501 Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd, 775 Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
502 q is incremented. 776 q is incremented.
503 Return the allocated memory in case of success, NULL in case of memory 777 Return the allocated memory (possibly NULL) in case of success, NOMEM_PTR
504 allocation failure. */ 778 in case of memory allocation failure. */
505static void * 779static void *
506divide (mpn_t a, mpn_t b, mpn_t *q) 780divide (mpn_t a, mpn_t b, mpn_t *q)
507{ 781{
@@ -560,7 +834,6 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
560 size_t a_len = a.nlimbs; 834 size_t a_len = a.nlimbs;
561 const mp_limb_t *b_ptr = b.limbs; 835 const mp_limb_t *b_ptr = b.limbs;
562 size_t b_len = b.nlimbs; 836 size_t b_len = b.nlimbs;
563 mp_limb_t *roomptr;
564 mp_limb_t *tmp_roomptr = NULL; 837 mp_limb_t *tmp_roomptr = NULL;
565 mp_limb_t *q_ptr; 838 mp_limb_t *q_ptr;
566 size_t q_len; 839 size_t q_len;
@@ -570,9 +843,9 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
570 /* Allocate room for a_len+2 digits. 843 /* Allocate room for a_len+2 digits.
571 (Need a_len+1 digits for the real division and 1 more digit for the 844 (Need a_len+1 digits for the real division and 1 more digit for the
572 final rounding of q.) */ 845 final rounding of q.) */
573 roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t)); 846 mp_limb_t *roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
574 if (roomptr == NULL) 847 if (roomptr == NULL)
575 return NULL; 848 return NOMEM_PTR;
576 849
577 /* Normalise a. */ 850 /* Normalise a. */
578 while (a_len > 0 && a_ptr[a_len - 1] == 0) 851 while (a_len > 0 && a_ptr[a_len - 1] == 0)
@@ -612,8 +885,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
612 mp_limb_t remainder = 0; 885 mp_limb_t remainder = 0;
613 const mp_limb_t *sourceptr = a_ptr + a_len; 886 const mp_limb_t *sourceptr = a_ptr + a_len;
614 mp_limb_t *destptr = q_ptr + a_len; 887 mp_limb_t *destptr = q_ptr + a_len;
615 size_t count; 888 for (size_t count = a_len; count > 0; count--)
616 for (count = a_len; count > 0; count--)
617 { 889 {
618 mp_twolimb_t num = 890 mp_twolimb_t num =
619 ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr; 891 ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
@@ -708,14 +980,13 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
708 if (tmp_roomptr == NULL) 980 if (tmp_roomptr == NULL)
709 { 981 {
710 free (roomptr); 982 free (roomptr);
711 return NULL; 983 return NOMEM_PTR;
712 } 984 }
713 { 985 {
714 const mp_limb_t *sourceptr = b_ptr; 986 const mp_limb_t *sourceptr = b_ptr;
715 mp_limb_t *destptr = tmp_roomptr; 987 mp_limb_t *destptr = tmp_roomptr;
716 mp_twolimb_t accu = 0; 988 mp_twolimb_t accu = 0;
717 size_t count; 989 for (size_t count = b_len; count > 0; count--)
718 for (count = b_len; count > 0; count--)
719 { 990 {
720 accu += (mp_twolimb_t) *sourceptr++ << s; 991 accu += (mp_twolimb_t) *sourceptr++ << s;
721 *destptr++ = (mp_limb_t) accu; 992 *destptr++ = (mp_limb_t) accu;
@@ -742,8 +1013,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
742 const mp_limb_t *sourceptr = a_ptr; 1013 const mp_limb_t *sourceptr = a_ptr;
743 mp_limb_t *destptr = r_ptr; 1014 mp_limb_t *destptr = r_ptr;
744 mp_twolimb_t accu = 0; 1015 mp_twolimb_t accu = 0;
745 size_t count; 1016 for (size_t count = a_len; count > 0; count--)
746 for (count = a_len; count > 0; count--)
747 { 1017 {
748 accu += (mp_twolimb_t) *sourceptr++ << s; 1018 accu += (mp_twolimb_t) *sourceptr++ << s;
749 *destptr++ = (mp_limb_t) accu; 1019 *destptr++ = (mp_limb_t) accu;
@@ -819,8 +1089,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
819 const mp_limb_t *sourceptr = b_ptr; 1089 const mp_limb_t *sourceptr = b_ptr;
820 mp_limb_t *destptr = r_ptr + j; 1090 mp_limb_t *destptr = r_ptr + j;
821 mp_twolimb_t carry = 0; 1091 mp_twolimb_t carry = 0;
822 size_t count; 1092 for (size_t count = b_len; count > 0; count--)
823 for (count = b_len; count > 0; count--)
824 { 1093 {
825 /* Here 0 <= carry <= q*. */ 1094 /* Here 0 <= carry <= q*. */
826 carry = 1095 carry =
@@ -844,8 +1113,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
844 const mp_limb_t *sourceptr = b_ptr; 1113 const mp_limb_t *sourceptr = b_ptr;
845 mp_limb_t *destptr = r_ptr + j; 1114 mp_limb_t *destptr = r_ptr + j;
846 mp_limb_t carry = 0; 1115 mp_limb_t carry = 0;
847 size_t count; 1116 for (size_t count = b_len; count > 0; count--)
848 for (count = b_len; count > 0; count--)
849 { 1117 {
850 mp_limb_t source1 = *sourceptr++; 1118 mp_limb_t source1 = *sourceptr++;
851 mp_limb_t source2 = *destptr; 1119 mp_limb_t source2 = *destptr;
@@ -877,8 +1145,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
877 { 1145 {
878 mp_limb_t ptr = r_ptr + r_len; 1146 mp_limb_t ptr = r_ptr + r_len;
879 mp_twolimb_t accu = 0; 1147 mp_twolimb_t accu = 0;
880 size_t count; 1148 for (size_t count = r_len; count > 0; count--)
881 for (count = r_len; count > 0; count--)
882 { 1149 {
883 accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS; 1150 accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
884 accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s); 1151 accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
@@ -893,29 +1160,25 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
893 /* Compare r << 1 with b. */ 1160 /* Compare r << 1 with b. */
894 if (r_len > b_len) 1161 if (r_len > b_len)
895 goto increment_q; 1162 goto increment_q;
896 { 1163 for (size_t i = b_len;;)
897 size_t i; 1164 {
898 for (i = b_len;;) 1165 mp_limb_t r_i =
899 { 1166 (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
900 mp_limb_t r_i = 1167 | (i < r_len ? r_ptr[i] << 1 : 0);
901 (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0) 1168 mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
902 | (i < r_len ? r_ptr[i] << 1 : 0); 1169 if (r_i > b_i)
903 mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0); 1170 goto increment_q;
904 if (r_i > b_i) 1171 if (r_i < b_i)
905 goto increment_q; 1172 goto keep_q;
906 if (r_i < b_i) 1173 if (i == 0)
907 goto keep_q; 1174 break;
908 if (i == 0) 1175 i--;
909 break; 1176 }
910 i--;
911 }
912 }
913 if (q_len > 0 && ((q_ptr[0] & 1) != 0)) 1177 if (q_len > 0 && ((q_ptr[0] & 1) != 0))
914 /* q is odd. */ 1178 /* q is odd. */
915 increment_q: 1179 increment_q:
916 { 1180 {
917 size_t i; 1181 for (size_t i = 0; i < q_len; i++)
918 for (i = 0; i < q_len; i++)
919 if (++(q_ptr[i]) != 0) 1182 if (++(q_ptr[i]) != 0)
920 goto keep_q; 1183 goto keep_q;
921 q_ptr[q_len++] = 1; 1184 q_ptr[q_len++] = 1;
@@ -930,7 +1193,7 @@ divide (mpn_t a, mpn_t b, mpn_t *q)
930/* Avoid pointless GCC warning "argument 1 value '18446744073709551615' exceeds 1193/* Avoid pointless GCC warning "argument 1 value '18446744073709551615' exceeds
931 maximum object size 9223372036854775807", triggered by the use of xsum as 1194 maximum object size 9223372036854775807", triggered by the use of xsum as
932 argument of malloc. */ 1195 argument of malloc. */
933# if __GNUC__ >= 7 1196# if _GL_GNUC_PREREQ (7, 0)
934# pragma GCC diagnostic push 1197# pragma GCC diagnostic push
935# pragma GCC diagnostic ignored "-Walloc-size-larger-than=" 1198# pragma GCC diagnostic ignored "-Walloc-size-larger-than="
936# endif 1199# endif
@@ -961,8 +1224,7 @@ convert_to_decimal (mpn_t a, size_t extra_zeroes)
961 /* Divide a by 10^9, in-place. */ 1224 /* Divide a by 10^9, in-place. */
962 mp_limb_t remainder = 0; 1225 mp_limb_t remainder = 0;
963 mp_limb_t *ptr = a_ptr + a_len; 1226 mp_limb_t *ptr = a_ptr + a_len;
964 size_t count; 1227 for (size_t count = a_len; count > 0; count--)
965 for (count = a_len; count > 0; count--)
966 { 1228 {
967 mp_twolimb_t num = 1229 mp_twolimb_t num =
968 ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr; 1230 ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
@@ -970,7 +1232,7 @@ convert_to_decimal (mpn_t a, size_t extra_zeroes)
970 remainder = num % 1000000000; 1232 remainder = num % 1000000000;
971 } 1233 }
972 /* Store the remainder as 9 decimal digits. */ 1234 /* Store the remainder as 9 decimal digits. */
973 for (count = 9; count > 0; count--) 1235 for (size_t count = 9; count > 0; count--)
974 { 1236 {
975 *d_ptr++ = '0' + (remainder % 10); 1237 *d_ptr++ = '0' + (remainder % 10);
976 remainder = remainder / 10; 1238 remainder = remainder / 10;
@@ -991,7 +1253,7 @@ convert_to_decimal (mpn_t a, size_t extra_zeroes)
991 return c_ptr; 1253 return c_ptr;
992} 1254}
993 1255
994# if __GNUC__ >= 7 1256# if _GL_GNUC_PREREQ (7, 0)
995# pragma GCC diagnostic pop 1257# pragma GCC diagnostic pop
996# endif 1258# endif
997 1259
@@ -1004,18 +1266,15 @@ convert_to_decimal (mpn_t a, size_t extra_zeroes)
1004static void * 1266static void *
1005decode_long_double (long double x, int *ep, mpn_t *mp) 1267decode_long_double (long double x, int *ep, mpn_t *mp)
1006{ 1268{
1007 mpn_t m;
1008 int exp;
1009 long double y;
1010 size_t i;
1011
1012 /* Allocate memory for result. */ 1269 /* Allocate memory for result. */
1270 mpn_t m;
1013 m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; 1271 m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
1014 m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t)); 1272 m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
1015 if (m.limbs == NULL) 1273 if (m.limbs == NULL)
1016 return NULL; 1274 return NULL;
1017 /* Split into exponential part and mantissa. */ 1275 /* Split into exponential part and mantissa. */
1018 y = frexpl (x, &exp); 1276 int exp;
1277 long double y = safe_frexpl (x, &exp);
1019 if (!(y >= 0.0L && y < 1.0L)) 1278 if (!(y >= 0.0L && y < 1.0L))
1020 abort (); 1279 abort ();
1021 /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the 1280 /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * 2^LDBL_MANT_BIT), and the
@@ -1053,7 +1312,7 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
1053 } 1312 }
1054# endif 1313# endif
1055# endif 1314# endif
1056 for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) 1315 for (size_t i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
1057 { 1316 {
1058 mp_limb_t hi, lo; 1317 mp_limb_t hi, lo;
1059 y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); 1318 y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
@@ -1092,18 +1351,15 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
1092static void * 1351static void *
1093decode_double (double x, int *ep, mpn_t *mp) 1352decode_double (double x, int *ep, mpn_t *mp)
1094{ 1353{
1095 mpn_t m;
1096 int exp;
1097 double y;
1098 size_t i;
1099
1100 /* Allocate memory for result. */ 1354 /* Allocate memory for result. */
1355 mpn_t m;
1101 m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; 1356 m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
1102 m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t)); 1357 m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
1103 if (m.limbs == NULL) 1358 if (m.limbs == NULL)
1104 return NULL; 1359 return NULL;
1105 /* Split into exponential part and mantissa. */ 1360 /* Split into exponential part and mantissa. */
1106 y = frexp (x, &exp); 1361 int exp;
1362 double y = frexp (x, &exp);
1107 if (!(y >= 0.0 && y < 1.0)) 1363 if (!(y >= 0.0 && y < 1.0))
1108 abort (); 1364 abort ();
1109 /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the 1365 /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * 2^DBL_MANT_BIT), and the
@@ -1141,7 +1397,7 @@ decode_double (double x, int *ep, mpn_t *mp)
1141 } 1397 }
1142# endif 1398# endif
1143# endif 1399# endif
1144 for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) 1400 for (size_t i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
1145 { 1401 {
1146 mp_limb_t hi, lo; 1402 mp_limb_t hi, lo;
1147 y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); 1403 y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
@@ -1176,24 +1432,11 @@ decode_double (double x, int *ep, mpn_t *mp)
1176static char * 1432static char *
1177scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n) 1433scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1178{ 1434{
1179 int s;
1180 size_t extra_zeroes;
1181 unsigned int abs_n;
1182 unsigned int abs_s;
1183 mp_limb_t *pow5_ptr;
1184 size_t pow5_len;
1185 unsigned int s_limbs;
1186 unsigned int s_bits;
1187 mpn_t pow5;
1188 mpn_t z;
1189 void *z_memory;
1190 char *digits;
1191
1192 /* x = 2^e * m, hence 1435 /* x = 2^e * m, hence
1193 y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m) 1436 y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
1194 = round (2^s * 5^n * m). */ 1437 = round (2^s * 5^n * m). */
1195 s = e + n; 1438 int s = e + n;
1196 extra_zeroes = 0; 1439 size_t extra_zeroes = 0;
1197 /* Factor out a common power of 10 if possible. */ 1440 /* Factor out a common power of 10 if possible. */
1198 if (s > 0 && n > 0) 1441 if (s > 0 && n > 0)
1199 { 1442 {
@@ -1206,11 +1449,12 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1206 z = round (2^s * 5^n * m). */ 1449 z = round (2^s * 5^n * m). */
1207 /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same 1450 /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
1208 sign. 2.322 is slightly larger than log(5)/log(2). */ 1451 sign. 2.322 is slightly larger than log(5)/log(2). */
1209 abs_n = (n >= 0 ? n : -n); 1452 unsigned int abs_n = (n >= 0 ? n : -n);
1210 abs_s = (s >= 0 ? s : -s); 1453 unsigned int abs_s = (s >= 0 ? s : -s);
1211 pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1 1454 mp_limb_t *pow5_ptr =
1212 + abs_s / GMP_LIMB_BITS + 1) 1455 (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
1213 * sizeof (mp_limb_t)); 1456 + abs_s / GMP_LIMB_BITS + 1)
1457 * sizeof (mp_limb_t));
1214 if (pow5_ptr == NULL) 1458 if (pow5_ptr == NULL)
1215 { 1459 {
1216 free (memory); 1460 free (memory);
@@ -1218,7 +1462,7 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1218 } 1462 }
1219 /* Initialize with 1. */ 1463 /* Initialize with 1. */
1220 pow5_ptr[0] = 1; 1464 pow5_ptr[0] = 1;
1221 pow5_len = 1; 1465 size_t pow5_len = 1;
1222 /* Multiply with 5^|n|. */ 1466 /* Multiply with 5^|n|. */
1223 if (abs_n > 0) 1467 if (abs_n > 0)
1224 { 1468 {
@@ -1227,13 +1471,11 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1227 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 1471 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
1228 48828125, 244140625, 1220703125 1472 48828125, 244140625, 1220703125
1229 }; 1473 };
1230 unsigned int n13; 1474 for (unsigned int n13 = 0; n13 <= abs_n; n13 += 13)
1231 for (n13 = 0; n13 <= abs_n; n13 += 13)
1232 { 1475 {
1233 mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13]; 1476 mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
1234 size_t j;
1235 mp_twolimb_t carry = 0; 1477 mp_twolimb_t carry = 0;
1236 for (j = 0; j < pow5_len; j++) 1478 for (size_t j = 0; j < pow5_len; j++)
1237 { 1479 {
1238 mp_limb_t digit2 = pow5_ptr[j]; 1480 mp_limb_t digit2 = pow5_ptr[j];
1239 carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2; 1481 carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
@@ -1244,8 +1486,11 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1244 pow5_ptr[pow5_len++] = (mp_limb_t) carry; 1486 pow5_ptr[pow5_len++] = (mp_limb_t) carry;
1245 } 1487 }
1246 } 1488 }
1247 s_limbs = abs_s / GMP_LIMB_BITS; 1489 unsigned int s_limbs = abs_s / GMP_LIMB_BITS;
1248 s_bits = abs_s % GMP_LIMB_BITS; 1490 unsigned int s_bits = abs_s % GMP_LIMB_BITS;
1491 mpn_t pow5;
1492 mpn_t z;
1493 void *z_memory;
1249 if (n >= 0 ? s >= 0 : s <= 0) 1494 if (n >= 0 ? s >= 0 : s <= 0)
1250 { 1495 {
1251 /* Multiply with 2^|s|. */ 1496 /* Multiply with 2^|s|. */
@@ -1253,8 +1498,7 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1253 { 1498 {
1254 mp_limb_t *ptr = pow5_ptr; 1499 mp_limb_t *ptr = pow5_ptr;
1255 mp_twolimb_t accu = 0; 1500 mp_twolimb_t accu = 0;
1256 size_t count; 1501 for (size_t count = pow5_len; count > 0; count--)
1257 for (count = pow5_len; count > 0; count--)
1258 { 1502 {
1259 accu += (mp_twolimb_t) *ptr << s_bits; 1503 accu += (mp_twolimb_t) *ptr << s_bits;
1260 *ptr++ = (mp_limb_t) accu; 1504 *ptr++ = (mp_limb_t) accu;
@@ -1268,13 +1512,12 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1268 } 1512 }
1269 if (s_limbs > 0) 1513 if (s_limbs > 0)
1270 { 1514 {
1271 size_t count; 1515 for (size_t count = pow5_len; count > 0;)
1272 for (count = pow5_len; count > 0;)
1273 { 1516 {
1274 count--; 1517 count--;
1275 pow5_ptr[s_limbs + count] = pow5_ptr[count]; 1518 pow5_ptr[s_limbs + count] = pow5_ptr[count];
1276 } 1519 }
1277 for (count = s_limbs; count > 0;) 1520 for (size_t count = s_limbs; count > 0;)
1278 { 1521 {
1279 count--; 1522 count--;
1280 pow5_ptr[count] = 0; 1523 pow5_ptr[count] = 0;
@@ -1306,7 +1549,7 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1306 mpn_t denominator; 1549 mpn_t denominator;
1307 void *tmp_memory; 1550 void *tmp_memory;
1308 tmp_memory = multiply (m, pow5, &numerator); 1551 tmp_memory = multiply (m, pow5, &numerator);
1309 if (tmp_memory == NULL) 1552 if (tmp_memory == NOMEM_PTR)
1310 { 1553 {
1311 free (pow5_ptr); 1554 free (pow5_ptr);
1312 free (memory); 1555 free (memory);
@@ -1315,8 +1558,7 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1315 /* Construct 2^|s|. */ 1558 /* Construct 2^|s|. */
1316 { 1559 {
1317 mp_limb_t *ptr = pow5_ptr + pow5_len; 1560 mp_limb_t *ptr = pow5_ptr + pow5_len;
1318 size_t i; 1561 for (size_t i = 0; i < s_limbs; i++)
1319 for (i = 0; i < s_limbs; i++)
1320 ptr[i] = 0; 1562 ptr[i] = 0;
1321 ptr[s_limbs] = (mp_limb_t) 1 << s_bits; 1563 ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
1322 denominator.limbs = ptr; 1564 denominator.limbs = ptr;
@@ -1341,17 +1583,13 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1341 } 1583 }
1342 { 1584 {
1343 mp_limb_t *destptr = num_ptr; 1585 mp_limb_t *destptr = num_ptr;
1344 { 1586 for (size_t i = 0; i < s_limbs; i++)
1345 size_t i; 1587 *destptr++ = 0;
1346 for (i = 0; i < s_limbs; i++)
1347 *destptr++ = 0;
1348 }
1349 if (s_bits > 0) 1588 if (s_bits > 0)
1350 { 1589 {
1351 const mp_limb_t *sourceptr = m.limbs; 1590 const mp_limb_t *sourceptr = m.limbs;
1352 mp_twolimb_t accu = 0; 1591 mp_twolimb_t accu = 0;
1353 size_t count; 1592 for (size_t count = m.nlimbs; count > 0; count--)
1354 for (count = m.nlimbs; count > 0; count--)
1355 { 1593 {
1356 accu += (mp_twolimb_t) *sourceptr++ << s_bits; 1594 accu += (mp_twolimb_t) *sourceptr++ << s_bits;
1357 *destptr++ = (mp_limb_t) accu; 1595 *destptr++ = (mp_limb_t) accu;
@@ -1363,8 +1601,7 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1363 else 1601 else
1364 { 1602 {
1365 const mp_limb_t *sourceptr = m.limbs; 1603 const mp_limb_t *sourceptr = m.limbs;
1366 size_t count; 1604 for (size_t count = m.nlimbs; count > 0; count--)
1367 for (count = m.nlimbs; count > 0; count--)
1368 *destptr++ = *sourceptr++; 1605 *destptr++ = *sourceptr++;
1369 } 1606 }
1370 numerator.limbs = num_ptr; 1607 numerator.limbs = num_ptr;
@@ -1379,9 +1616,9 @@ scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
1379 1616
1380 /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */ 1617 /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */
1381 1618
1382 if (z_memory == NULL) 1619 if (z_memory == NOMEM_PTR)
1383 return NULL; 1620 return NULL;
1384 digits = convert_to_decimal (z, extra_zeroes); 1621 char *digits = convert_to_decimal (z, extra_zeroes);
1385 free (z_memory); 1622 free (z_memory);
1386 return digits; 1623 return digits;
1387} 1624}
@@ -1436,13 +1673,9 @@ scale10_round_decimal_double (double x, int n)
1436static int 1673static int
1437floorlog10l (long double x) 1674floorlog10l (long double x)
1438{ 1675{
1439 int exp;
1440 long double y;
1441 double z;
1442 double l;
1443
1444 /* Split into exponential part and mantissa. */ 1676 /* Split into exponential part and mantissa. */
1445 y = frexpl (x, &exp); 1677 int exp;
1678 long double y = safe_frexpl (x, &exp);
1446 if (!(y >= 0.0L && y < 1.0L)) 1679 if (!(y >= 0.0L && y < 1.0L))
1447 abort (); 1680 abort ();
1448 if (y == 0.0L) 1681 if (y == 0.0L)
@@ -1483,8 +1716,8 @@ floorlog10l (long double x)
1483 if (!(y >= 0.5L && y < 1.0L)) 1716 if (!(y >= 0.5L && y < 1.0L))
1484 abort (); 1717 abort ();
1485 /* Compute an approximation for l = log2(x) = exp + log2(y). */ 1718 /* Compute an approximation for l = log2(x) = exp + log2(y). */
1486 l = exp; 1719 double l = exp;
1487 z = y; 1720 double z = y;
1488 if (z < 0.70710678118654752444) 1721 if (z < 0.70710678118654752444)
1489 { 1722 {
1490 z *= 1.4142135623730950488; 1723 z *= 1.4142135623730950488;
@@ -1527,13 +1760,9 @@ floorlog10l (long double x)
1527static int 1760static int
1528floorlog10 (double x) 1761floorlog10 (double x)
1529{ 1762{
1530 int exp;
1531 double y;
1532 double z;
1533 double l;
1534
1535 /* Split into exponential part and mantissa. */ 1763 /* Split into exponential part and mantissa. */
1536 y = frexp (x, &exp); 1764 int exp;
1765 double y = frexp (x, &exp);
1537 if (!(y >= 0.0 && y < 1.0)) 1766 if (!(y >= 0.0 && y < 1.0))
1538 abort (); 1767 abort ();
1539 if (y == 0.0) 1768 if (y == 0.0)
@@ -1574,8 +1803,8 @@ floorlog10 (double x)
1574 if (!(y >= 0.5 && y < 1.0)) 1803 if (!(y >= 0.5 && y < 1.0))
1575 abort (); 1804 abort ();
1576 /* Compute an approximation for l = log2(x) = exp + log2(y). */ 1805 /* Compute an approximation for l = log2(x) = exp + log2(y). */
1577 l = exp; 1806 double l = exp;
1578 z = y; 1807 double z = y;
1579 if (z < 0.70710678118654752444) 1808 if (z < 0.70710678118654752444)
1580 { 1809 {
1581 z *= 1.4142135623730950488; 1810 z *= 1.4142135623730950488;
@@ -1801,8 +2030,17 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
1801 } 2030 }
1802 if (tmp_length < precision) 2031 if (tmp_length < precision)
1803 tmp_length = precision; 2032 tmp_length = precision;
1804 /* Multiply by 2, as an estimate for FLAG_GROUP. */ 2033 /* Account for thousands separators. */
1805 tmp_length = xsum (tmp_length, tmp_length); 2034 if (flags & FLAG_GROUP)
2035 {
2036 /* A thousands separator needs to be inserted at most every 2 digits.
2037 This is the case in the ta_IN locale. */
2038# if WIDE_CHAR_VERSION
2039 tmp_length = xsum (tmp_length, tmp_length / 2 * THOUSEP_WCHAR_MAXLEN);
2040# else
2041 tmp_length = xsum (tmp_length, tmp_length / 2 * THOUSEP_CHAR_MAXLEN);
2042# endif
2043 }
1806 /* Add 1, to account for a leading sign. */ 2044 /* Add 1, to account for a leading sign. */
1807 tmp_length = xsum (tmp_length, 1); 2045 tmp_length = xsum (tmp_length, 1);
1808 break; 2046 break;
@@ -2050,12 +2288,18 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2050 tmp_length = xsum (tmp_length, 2); 2288 tmp_length = xsum (tmp_length, 2);
2051 break; 2289 break;
2052 2290
2291 case 'e': case 'E':
2292 tmp_length =
2293 12; /* sign, decimal point, exponent etc. */
2294 tmp_length = xsum (tmp_length, precision);
2295 break;
2296
2053 case 'f': case 'F': 2297 case 'f': case 'F':
2054 if (type == TYPE_LONGDOUBLE) 2298 if (type == TYPE_LONGDOUBLE)
2055 tmp_length = 2299 tmp_length =
2056 (unsigned int) (LDBL_MAX_EXP 2300 (unsigned int) (LDBL_MAX_EXP
2057 * 0.30103 /* binary -> decimal */ 2301 * 0.30103 /* binary -> decimal */
2058 * 2 /* estimate for FLAG_GROUP */ 2302 * 0.5 * 3 /* estimate for FLAG_GROUP */
2059 ) 2303 )
2060 + 1 /* turn floor into ceil */ 2304 + 1 /* turn floor into ceil */
2061 + 10; /* sign, decimal point etc. */ 2305 + 10; /* sign, decimal point etc. */
@@ -2063,17 +2307,20 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2063 tmp_length = 2307 tmp_length =
2064 (unsigned int) (DBL_MAX_EXP 2308 (unsigned int) (DBL_MAX_EXP
2065 * 0.30103 /* binary -> decimal */ 2309 * 0.30103 /* binary -> decimal */
2066 * 2 /* estimate for FLAG_GROUP */ 2310 * 0.5 * 3 /* estimate for FLAG_GROUP */
2067 ) 2311 )
2068 + 1 /* turn floor into ceil */ 2312 + 1 /* turn floor into ceil */
2069 + 10; /* sign, decimal point etc. */ 2313 + 10; /* sign, decimal point etc. */
2070 tmp_length = xsum (tmp_length, precision); 2314 tmp_length = xsum (tmp_length, precision);
2071 break; 2315 break;
2072 2316
2073 case 'e': case 'E': case 'g': case 'G': 2317 case 'g': case 'G':
2074 tmp_length = 2318 tmp_length =
2075 12; /* sign, decimal point, exponent etc. */ 2319 12; /* sign, decimal point, exponent etc. */
2076 tmp_length = xsum (tmp_length, precision); 2320 tmp_length = xsum (tmp_length,
2321 precision
2322 * 0.5 * 3 /* estimate for FLAG_GROUP */
2323 );
2077 break; 2324 break;
2078 2325
2079 case 'a': case 'A': 2326 case 'a': case 'A':
@@ -2111,10 +2358,9 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2111 break; 2358 break;
2112 2359
2113 case 's': 2360 case 's':
2114# if HAVE_WCHAR_T
2115 if (type == TYPE_WIDE_STRING) 2361 if (type == TYPE_WIDE_STRING)
2116 { 2362 {
2117# if WIDE_CHAR_VERSION 2363# if WIDE_CHAR_VERSION
2118 /* ISO C says about %ls in fwprintf: 2364 /* ISO C says about %ls in fwprintf:
2119 "If the precision is not specified or is greater than the size 2365 "If the precision is not specified or is greater than the size
2120 of the array, the array shall contain a null wide character." 2366 of the array, the array shall contain a null wide character."
@@ -2125,7 +2371,7 @@ MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
2125 tmp_length = local_wcsnlen (arg, precision); 2371 tmp_length = local_wcsnlen (arg, precision);
2126 else 2372 else
2127 tmp_length = local_wcslen (arg); 2373 tmp_length = local_wcslen (arg);
2128# else 2374# else
2129 /* ISO C says about %ls in fprintf: 2375 /* ISO C says about %ls in fprintf:
2130 "If a precision is specified, no more than that many bytes are 2376 "If a precision is specified, no more than that many bytes are
2131 written (including shift sequences, if any), and the array 2377 written (including shift sequences, if any), and the array
@@ -2136,10 +2382,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. */ 2382 So if there is a precision, we must not use wcslen. */
2137 /* This case has already been handled separately in VASNPRINTF. */ 2383 /* This case has already been handled separately in VASNPRINTF. */
2138 abort (); 2384 abort ();
2139# endif 2385# endif
2140 } 2386 }
2141 else 2387 else
2142# endif
2143 { 2388 {
2144# if WIDE_CHAR_VERSION 2389# if WIDE_CHAR_VERSION
2145 /* ISO C says about %s in fwprintf: 2390 /* ISO C says about %s in fwprintf:
@@ -2222,21 +2467,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2222 goto fail_1_with_EINVAL; 2467 goto fail_1_with_EINVAL;
2223 2468
2224 { 2469 {
2225 size_t buf_neededlength;
2226 TCHAR_T *buf;
2227 TCHAR_T *buf_malloced;
2228 const FCHAR_T *cp;
2229 size_t i;
2230 DIRECTIVE *dp;
2231 /* Output string accumulator. */
2232 DCHAR_T *result;
2233 size_t allocated;
2234 size_t length;
2235
2236 /* Allocate a small buffer that will hold a directive passed to 2470 /* Allocate a small buffer that will hold a directive passed to
2237 sprintf or snprintf. */ 2471 sprintf or snprintf. */
2238 buf_neededlength = 2472 size_t buf_neededlength =
2239 xsum4 (7, d.max_width_length, d.max_precision_length, 6); 2473 xsum4 (7, d.max_width_length, d.max_precision_length, 6);
2474 TCHAR_T *buf;
2475 TCHAR_T *buf_malloced;
2240#if HAVE_ALLOCA 2476#if HAVE_ALLOCA
2241 if (buf_neededlength < 4000 / sizeof (TCHAR_T)) 2477 if (buf_neededlength < 4000 / sizeof (TCHAR_T))
2242 { 2478 {
@@ -2255,9 +2491,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2255 buf_malloced = buf; 2491 buf_malloced = buf;
2256 } 2492 }
2257 2493
2258 result = resultbuf; 2494 /* Output string accumulator. */
2259 allocated = (resultbuf != NULL ? *lengthp : 0); 2495 DCHAR_T *result = resultbuf;
2260 length = 0; 2496 size_t allocated = (resultbuf != NULL ? *lengthp : 0);
2497 size_t length = 0;
2498
2261 /* Invariants: 2499 /* Invariants:
2262 result is either == resultbuf or malloc-allocated. 2500 result is either == resultbuf or malloc-allocated.
2263 If result == NULL, resultbuf is == NULL as well. 2501 If result == NULL, resultbuf is == NULL as well.
@@ -2268,15 +2506,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2268#define ENSURE_ALLOCATION_ELSE(needed, oom_statement) \ 2506#define ENSURE_ALLOCATION_ELSE(needed, oom_statement) \
2269 if ((needed) > allocated) \ 2507 if ((needed) > allocated) \
2270 { \ 2508 { \
2271 size_t memory_size; \
2272 DCHAR_T *memory; \
2273 \
2274 allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ 2509 allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
2275 if ((needed) > allocated) \ 2510 if ((needed) > allocated) \
2276 allocated = (needed); \ 2511 allocated = (needed); \
2277 memory_size = xtimes (allocated, sizeof (DCHAR_T)); \ 2512 size_t memory_size = xtimes (allocated, sizeof (DCHAR_T)); \
2278 if (size_overflow_p (memory_size)) \ 2513 if (size_overflow_p (memory_size)) \
2279 oom_statement \ 2514 oom_statement \
2515 DCHAR_T *memory; \
2280 if (result == resultbuf) \ 2516 if (result == resultbuf) \
2281 memory = (DCHAR_T *) malloc (memory_size); \ 2517 memory = (DCHAR_T *) malloc (memory_size); \
2282 else \ 2518 else \
@@ -2290,7 +2526,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2290#define ENSURE_ALLOCATION(needed) \ 2526#define ENSURE_ALLOCATION(needed) \
2291 ENSURE_ALLOCATION_ELSE((needed), goto out_of_memory; ) 2527 ENSURE_ALLOCATION_ELSE((needed), goto out_of_memory; )
2292 2528
2293 for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) 2529 const FCHAR_T *cp;
2530 size_t di;
2531 DIRECTIVE *dp;
2532 for (cp = format, di = 0, dp = &d.dir[0]; ; cp = dp->dir_end, di++, dp++)
2294 { 2533 {
2295 if (cp != dp->dir_start) 2534 if (cp != dp->dir_start)
2296 { 2535 {
@@ -2313,7 +2552,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2313 while (--n > 0); 2552 while (--n > 0);
2314 } 2553 }
2315 } 2554 }
2316 if (i == d.count) 2555 if (di == d.count)
2317 break; 2556 break;
2318 2557
2319 /* Execute a single directive. */ 2558 /* Execute a single directive. */
@@ -2390,22 +2629,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2390 { 2629 {
2391 arg_type type = a.arg[dp->arg_index].type; 2630 arg_type type = a.arg[dp->arg_index].type;
2392 int flags = dp->flags; 2631 int flags = dp->flags;
2393 int has_width;
2394 size_t width;
2395 int has_precision;
2396 size_t precision;
2397 2632
2398 has_width = 0; 2633 int has_width = 0;
2399 width = 0; 2634 size_t width = 0;
2400 if (dp->width_start != dp->width_end) 2635 if (dp->width_start != dp->width_end)
2401 { 2636 {
2402 if (dp->width_arg_index != ARG_NONE) 2637 if (dp->width_arg_index != ARG_NONE)
2403 { 2638 {
2404 int arg;
2405
2406 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 2639 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2407 abort (); 2640 abort ();
2408 arg = a.arg[dp->width_arg_index].a.a_int; 2641 int arg = a.arg[dp->width_arg_index].a.a_int;
2409 width = arg; 2642 width = arg;
2410 if (arg < 0) 2643 if (arg < 0)
2411 { 2644 {
@@ -2423,20 +2656,20 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2423 width = xsum (xtimes (width, 10), *digitp++ - '0'); 2656 width = xsum (xtimes (width, 10), *digitp++ - '0');
2424 while (digitp != dp->width_end); 2657 while (digitp != dp->width_end);
2425 } 2658 }
2659 if (width > (size_t) INT_MAX)
2660 goto overflow;
2426 has_width = 1; 2661 has_width = 1;
2427 } 2662 }
2428 2663
2429 has_precision = 0; 2664 int has_precision = 0;
2430 precision = 0; 2665 size_t precision = 0;
2431 if (dp->precision_start != dp->precision_end) 2666 if (dp->precision_start != dp->precision_end)
2432 { 2667 {
2433 if (dp->precision_arg_index != ARG_NONE) 2668 if (dp->precision_arg_index != ARG_NONE)
2434 { 2669 {
2435 int arg;
2436
2437 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 2670 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2438 abort (); 2671 abort ();
2439 arg = a.arg[dp->precision_arg_index].a.a_int; 2672 int arg = a.arg[dp->precision_arg_index].a.a_int;
2440 /* "A negative precision is taken as if the precision 2673 /* "A negative precision is taken as if the precision
2441 were omitted." */ 2674 were omitted." */
2442 if (arg >= 0) 2675 if (arg >= 0)
@@ -2501,7 +2734,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2501 { 2734 {
2502 /* Use the entire string. */ 2735 /* Use the entire string. */
2503 arg_end = arg + u8_strlen (arg); 2736 arg_end = arg + u8_strlen (arg);
2504 /* The number of characters doesn't matter. */ 2737 /* The number of characters doesn't matter,
2738 because !has_width and therefore width==0. */
2505 characters = 0; 2739 characters = 0;
2506 } 2740 }
2507 2741
@@ -2542,7 +2776,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2542 if (converted != result + length) 2776 if (converted != result + length)
2543 { 2777 {
2544 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len), 2778 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
2545 { free (converted); goto out_of_memory; }); 2779 { free (converted); goto out_of_memory; });
2546 DCHAR_CPY (result + length, converted, converted_len); 2780 DCHAR_CPY (result + length, converted, converted_len);
2547 free (converted); 2781 free (converted);
2548 } 2782 }
@@ -2603,7 +2837,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2603 { 2837 {
2604 /* Use the entire string. */ 2838 /* Use the entire string. */
2605 arg_end = arg + u16_strlen (arg); 2839 arg_end = arg + u16_strlen (arg);
2606 /* The number of characters doesn't matter. */ 2840 /* The number of characters doesn't matter,
2841 because !has_width and therefore width==0. */
2607 characters = 0; 2842 characters = 0;
2608 } 2843 }
2609 2844
@@ -2644,7 +2879,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2644 if (converted != result + length) 2879 if (converted != result + length)
2645 { 2880 {
2646 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len), 2881 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
2647 { free (converted); goto out_of_memory; }); 2882 { free (converted); goto out_of_memory; });
2648 DCHAR_CPY (result + length, converted, converted_len); 2883 DCHAR_CPY (result + length, converted, converted_len);
2649 free (converted); 2884 free (converted);
2650 } 2885 }
@@ -2705,7 +2940,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2705 { 2940 {
2706 /* Use the entire string. */ 2941 /* Use the entire string. */
2707 arg_end = arg + u32_strlen (arg); 2942 arg_end = arg + u32_strlen (arg);
2708 /* The number of characters doesn't matter. */ 2943 /* The number of characters doesn't matter,
2944 because !has_width and therefore width==0. */
2709 characters = 0; 2945 characters = 0;
2710 } 2946 }
2711 2947
@@ -2746,7 +2982,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2746 if (converted != result + length) 2982 if (converted != result + length)
2747 { 2983 {
2748 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len), 2984 ENSURE_ALLOCATION_ELSE (xsum (length, converted_len),
2749 { free (converted); goto out_of_memory; }); 2985 { free (converted); goto out_of_memory; });
2750 DCHAR_CPY (result + length, converted, converted_len); 2986 DCHAR_CPY (result + length, converted, converted_len);
2751 free (converted); 2987 free (converted);
2752 } 2988 }
@@ -2769,7 +3005,178 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2769 } 3005 }
2770 } 3006 }
2771#endif 3007#endif
2772#if WIDE_CHAR_VERSION && (!DCHAR_IS_TCHAR || NEED_WPRINTF_DIRECTIVE_LC) 3008#if !WIDE_CHAR_VERSION && (PTRDIFF_MAX > INT_MAX)
3009 else if (dp->conversion == 's'
3010 && a.arg[dp->arg_index].type != TYPE_WIDE_STRING)
3011 {
3012 /* %s in vasnprintf. See the specification of fprintf.
3013 We handle it ourselves here, because the string may be longer
3014 than INT_MAX characters, whence snprintf or sprintf would
3015 fail to process it. */
3016 int flags = dp->flags;
3017
3018 int has_width = 0;
3019 size_t width = 0;
3020 if (dp->width_start != dp->width_end)
3021 {
3022 if (dp->width_arg_index != ARG_NONE)
3023 {
3024 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3025 abort ();
3026 int arg = a.arg[dp->width_arg_index].a.a_int;
3027 width = arg;
3028 if (arg < 0)
3029 {
3030 /* "A negative field width is taken as a '-' flag
3031 followed by a positive field width." */
3032 flags |= FLAG_LEFT;
3033 width = -width;
3034 }
3035 }
3036 else
3037 {
3038 const FCHAR_T *digitp = dp->width_start;
3039
3040 do
3041 width = xsum (xtimes (width, 10), *digitp++ - '0');
3042 while (digitp != dp->width_end);
3043 }
3044 if (width > (size_t) INT_MAX)
3045 goto overflow;
3046 has_width = 1;
3047 }
3048
3049 int has_precision = 0;
3050 size_t precision = 6;
3051 if (dp->precision_start != dp->precision_end)
3052 {
3053 if (dp->precision_arg_index != ARG_NONE)
3054 {
3055 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
3056 abort ();
3057 int arg = a.arg[dp->precision_arg_index].a.a_int;
3058 /* "A negative precision is taken as if the precision
3059 were omitted." */
3060 if (arg >= 0)
3061 {
3062 precision = arg;
3063 has_precision = 1;
3064 }
3065 }
3066 else
3067 {
3068 const FCHAR_T *digitp = dp->precision_start + 1;
3069
3070 precision = 0;
3071 while (digitp != dp->precision_end)
3072 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
3073 has_precision = 1;
3074 }
3075 }
3076
3077 {
3078 const char *arg = a.arg[dp->arg_index].a.a_string;
3079
3080 size_t bytes;
3081 if (has_precision)
3082 {
3083 /* Use only at most PRECISION bytes, from the left. */
3084 bytes = local_strnlen (arg, precision);
3085 }
3086 else
3087 {
3088 /* Use the entire string, and count the number of
3089 bytes. */
3090 bytes = strlen (arg);
3091 }
3092
3093# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3094 size_t characters;
3095 if (has_width)
3096 characters = mbsnlen (arg, bytes);
3097 else
3098 {
3099 /* The number of characters doesn't matter,
3100 because !has_width and therefore width==0. */
3101 characters = 0;
3102 }
3103# endif
3104
3105# if !DCHAR_IS_TCHAR
3106 /* This code assumes that TCHAR_T is 'char'. */
3107 static_assert (sizeof (TCHAR_T) == 1);
3108 DCHAR_T *tmpdst;
3109 size_t tmpdst_len;
3110 /* Convert from TCHAR_T[] to DCHAR_T[]. */
3111 tmpdst =
3112 DCHAR_CONV_FROM_ENCODING (locale_charset (),
3113 iconveh_question_mark,
3114 arg, bytes,
3115 NULL,
3116 NULL, &tmpdst_len);
3117 if (tmpdst == NULL)
3118 goto fail_with_errno;
3119# endif
3120
3121 size_t w;
3122 if (has_width)
3123 {
3124# if ENABLE_UNISTDIO
3125 /* Outside POSIX, it's preferable to compare the width
3126 against the number of _characters_ of the converted
3127 value. */
3128# if DCHAR_IS_TCHAR
3129 w = characters;
3130# else
3131 w = DCHAR_MBSNLEN (tmpdst, tmpdst_len);
3132# endif
3133# else
3134 /* The width is compared against the number of _bytes_
3135 of the converted value, says POSIX. */
3136 w = bytes;
3137# endif
3138 }
3139 else
3140 /* w doesn't matter. */
3141 w = 0;
3142
3143 {
3144# if DCHAR_IS_TCHAR
3145 size_t total = bytes + (w < width ? width - w : 0);
3146 ENSURE_ALLOCATION (xsum (length, total));
3147# else
3148 size_t total = tmpdst_len + (w < width ? width - w : 0);
3149 ENSURE_ALLOCATION_ELSE (xsum (length, total),
3150 { free (tmpdst); goto out_of_memory; });
3151# endif
3152
3153 if (w < width && !(flags & FLAG_LEFT))
3154 {
3155 size_t n = width - w;
3156 DCHAR_SET (result + length, ' ', n);
3157 length += n;
3158 }
3159
3160# if DCHAR_IS_TCHAR
3161 memcpy (result + length, arg, bytes);
3162 length += bytes;
3163# else
3164 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
3165 free (tmpdst);
3166 length += tmpdst_len;
3167# endif
3168
3169 if (w < width && (flags & FLAG_LEFT))
3170 {
3171 size_t n = width - w;
3172 DCHAR_SET (result + length, ' ', n);
3173 length += n;
3174 }
3175 }
3176 }
3177 }
3178#endif
3179#if WIDE_CHAR_VERSION && ((PTRDIFF_MAX > INT_MAX) || !DCHAR_IS_TCHAR || NEED_WPRINTF_DIRECTIVE_LC)
2773 else if ((dp->conversion == 's' 3180 else if ((dp->conversion == 's'
2774 && a.arg[dp->arg_index].type == TYPE_WIDE_STRING) 3181 && a.arg[dp->arg_index].type == TYPE_WIDE_STRING)
2775 || (dp->conversion == 'c' 3182 || (dp->conversion == 'c'
@@ -2781,18 +3188,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2781 convert back the result from a char[] to a wchar_t[]. 3188 convert back the result from a char[] to a wchar_t[].
2782 Instead, just copy the argument wchar_t[] to the result. */ 3189 Instead, just copy the argument wchar_t[] to the result. */
2783 int flags = dp->flags; 3190 int flags = dp->flags;
2784 size_t width;
2785 3191
2786 width = 0; 3192 size_t width = 0;
2787 if (dp->width_start != dp->width_end) 3193 if (dp->width_start != dp->width_end)
2788 { 3194 {
2789 if (dp->width_arg_index != ARG_NONE) 3195 if (dp->width_arg_index != ARG_NONE)
2790 { 3196 {
2791 int arg;
2792
2793 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 3197 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2794 abort (); 3198 abort ();
2795 arg = a.arg[dp->width_arg_index].a.a_int; 3199 int arg = a.arg[dp->width_arg_index].a.a_int;
2796 width = arg; 3200 width = arg;
2797 if (arg < 0) 3201 if (arg < 0)
2798 { 3202 {
@@ -2810,6 +3214,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2810 width = xsum (xtimes (width, 10), *digitp++ - '0'); 3214 width = xsum (xtimes (width, 10), *digitp++ - '0');
2811 while (digitp != dp->width_end); 3215 while (digitp != dp->width_end);
2812 } 3216 }
3217 if (width > (size_t) INT_MAX)
3218 goto overflow;
2813 } 3219 }
2814 3220
2815 { 3221 {
@@ -2819,20 +3225,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2819 3225
2820 if (dp->conversion == 's') 3226 if (dp->conversion == 's')
2821 { 3227 {
2822 int has_precision; 3228 int has_precision = 0;
2823 size_t precision; 3229 size_t precision = 6;
2824
2825 has_precision = 0;
2826 precision = 6;
2827 if (dp->precision_start != dp->precision_end) 3230 if (dp->precision_start != dp->precision_end)
2828 { 3231 {
2829 if (dp->precision_arg_index != ARG_NONE) 3232 if (dp->precision_arg_index != ARG_NONE)
2830 { 3233 {
2831 int arg;
2832
2833 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 3234 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2834 abort (); 3235 abort ();
2835 arg = a.arg[dp->precision_arg_index].a.a_int; 3236 int arg = a.arg[dp->precision_arg_index].a.a_int;
2836 /* "A negative precision is taken as if the precision 3237 /* "A negative precision is taken as if the precision
2837 were omitted." */ 3238 were omitted." */
2838 if (arg >= 0) 3239 if (arg >= 0)
@@ -2858,9 +3259,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2858 { 3259 {
2859 /* Use only at most PRECISION wide characters, from 3260 /* Use only at most PRECISION wide characters, from
2860 the left. */ 3261 the left. */
2861 const wchar_t *ls_arg_end; 3262 const wchar_t *ls_arg_end = ls_arg;
2862
2863 ls_arg_end = ls_arg;
2864 characters = 0; 3263 characters = 0;
2865 for (; precision > 0; precision--) 3264 for (; precision > 0; precision--)
2866 { 3265 {
@@ -2912,7 +3311,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2912 } 3311 }
2913 } 3312 }
2914#endif 3313#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 3314#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' 3315 else if (dp->conversion == 's'
2917# if WIDE_CHAR_VERSION 3316# if WIDE_CHAR_VERSION
2918 && a.arg[dp->arg_index].type != TYPE_WIDE_STRING 3317 && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
@@ -2932,22 +3331,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2932 such bugs, we implement the entire processing of the 's' 3331 such bugs, we implement the entire processing of the 's'
2933 directive ourselves. */ 3332 directive ourselves. */
2934 int flags = dp->flags; 3333 int flags = dp->flags;
2935 int has_width;
2936 size_t width;
2937 int has_precision;
2938 size_t precision;
2939 3334
2940 has_width = 0; 3335 int has_width = 0;
2941 width = 0; 3336 size_t width = 0;
2942 if (dp->width_start != dp->width_end) 3337 if (dp->width_start != dp->width_end)
2943 { 3338 {
2944 if (dp->width_arg_index != ARG_NONE) 3339 if (dp->width_arg_index != ARG_NONE)
2945 { 3340 {
2946 int arg;
2947
2948 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 3341 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2949 abort (); 3342 abort ();
2950 arg = a.arg[dp->width_arg_index].a.a_int; 3343 int arg = a.arg[dp->width_arg_index].a.a_int;
2951 width = arg; 3344 width = arg;
2952 if (arg < 0) 3345 if (arg < 0)
2953 { 3346 {
@@ -2965,20 +3358,20 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
2965 width = xsum (xtimes (width, 10), *digitp++ - '0'); 3358 width = xsum (xtimes (width, 10), *digitp++ - '0');
2966 while (digitp != dp->width_end); 3359 while (digitp != dp->width_end);
2967 } 3360 }
3361 if (width > (size_t) INT_MAX)
3362 goto overflow;
2968 has_width = 1; 3363 has_width = 1;
2969 } 3364 }
2970 3365
2971 has_precision = 0; 3366 int has_precision = 0;
2972 precision = 6; 3367 size_t precision = 6;
2973 if (dp->precision_start != dp->precision_end) 3368 if (dp->precision_start != dp->precision_end)
2974 { 3369 {
2975 if (dp->precision_arg_index != ARG_NONE) 3370 if (dp->precision_arg_index != ARG_NONE)
2976 { 3371 {
2977 int arg;
2978
2979 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 3372 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2980 abort (); 3373 abort ();
2981 arg = a.arg[dp->precision_arg_index].a.a_int; 3374 int arg = a.arg[dp->precision_arg_index].a.a_int;
2982 /* "A negative precision is taken as if the precision 3375 /* "A negative precision is taken as if the precision
2983 were omitted." */ 3376 were omitted." */
2984 if (arg >= 0) 3377 if (arg >= 0)
@@ -3080,13 +3473,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3080 if (has_precision || has_width) 3473 if (has_precision || has_width)
3081 { 3474 {
3082 /* We know the number of wide characters in advance. */ 3475 /* We know the number of wide characters in advance. */
3083 size_t remaining;
3084# if HAVE_MBRTOWC 3476# if HAVE_MBRTOWC
3085 mbstate_t state; 3477 mbstate_t state;
3086 mbszero (&state); 3478 mbszero (&state);
3087# endif 3479# endif
3088 ENSURE_ALLOCATION (xsum (length, characters)); 3480 ENSURE_ALLOCATION (xsum (length, characters));
3089 for (remaining = characters; remaining > 0; remaining--) 3481 for (size_t remaining = characters; remaining > 0; remaining--)
3090 { 3482 {
3091 wchar_t wc; 3483 wchar_t wc;
3092 int count; 3484 int count;
@@ -3145,11 +3537,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3145 { 3537 {
3146 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; 3538 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
3147 const wchar_t *arg_end; 3539 const wchar_t *arg_end;
3540 size_t bytes;
3541# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3148 size_t characters; 3542 size_t characters;
3543# endif
3149# if !DCHAR_IS_TCHAR 3544# if !DCHAR_IS_TCHAR
3150 /* This code assumes that TCHAR_T is 'char'. */ 3545 /* This code assumes that TCHAR_T is 'char'. */
3151 static_assert (sizeof (TCHAR_T) == 1); 3546 static_assert (sizeof (TCHAR_T) == 1);
3152 TCHAR_T *tmpsrc;
3153 DCHAR_T *tmpdst; 3547 DCHAR_T *tmpdst;
3154 size_t tmpdst_len; 3548 size_t tmpdst_len;
3155# endif 3549# endif
@@ -3164,23 +3558,27 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3164 mbszero (&state); 3558 mbszero (&state);
3165# endif 3559# endif
3166 arg_end = arg; 3560 arg_end = arg;
3561 bytes = 0;
3562# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3167 characters = 0; 3563 characters = 0;
3564# endif
3168 while (precision > 0) 3565 while (precision > 0)
3169 { 3566 {
3170 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3171 int count;
3172
3173 if (*arg_end == 0) 3567 if (*arg_end == 0)
3174 /* Found the terminating null wide character. */ 3568 /* Found the terminating null wide character. */
3175 break; 3569 break;
3176 count = local_wcrtomb (cbuf, *arg_end, &state); 3570 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3571 int count = local_wcrtomb (cbuf, *arg_end, &state);
3177 if (count < 0) 3572 if (count < 0)
3178 /* Cannot convert. */ 3573 /* Cannot convert. */
3179 goto fail_with_EILSEQ; 3574 goto fail_with_EILSEQ;
3180 if (precision < (unsigned int) count) 3575 if (precision < (unsigned int) count)
3181 break; 3576 break;
3182 arg_end++; 3577 arg_end++;
3183 characters += count; 3578 bytes += count;
3579# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3580 characters += mbsnlen (cbuf, count);
3581# endif
3184 precision -= count; 3582 precision -= count;
3185 } 3583 }
3186 } 3584 }
@@ -3197,21 +3595,25 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3197 mbszero (&state); 3595 mbszero (&state);
3198# endif 3596# endif
3199 arg_end = arg; 3597 arg_end = arg;
3598 bytes = 0;
3599# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3200 characters = 0; 3600 characters = 0;
3601# endif
3201 for (;;) 3602 for (;;)
3202 { 3603 {
3203 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3204 int count;
3205
3206 if (*arg_end == 0) 3604 if (*arg_end == 0)
3207 /* Found the terminating null wide character. */ 3605 /* Found the terminating null wide character. */
3208 break; 3606 break;
3209 count = local_wcrtomb (cbuf, *arg_end, &state); 3607 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3608 int count = local_wcrtomb (cbuf, *arg_end, &state);
3210 if (count < 0) 3609 if (count < 0)
3211 /* Cannot convert. */ 3610 /* Cannot convert. */
3212 goto fail_with_EILSEQ; 3611 goto fail_with_EILSEQ;
3213 arg_end++; 3612 arg_end++;
3214 characters += count; 3613 bytes += count;
3614# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3615 characters += mbsnlen (cbuf, count);
3616# endif
3215 } 3617 }
3216 } 3618 }
3217# if DCHAR_IS_TCHAR 3619# if DCHAR_IS_TCHAR
@@ -3219,56 +3621,59 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3219 { 3621 {
3220 /* Use the entire string. */ 3622 /* Use the entire string. */
3221 arg_end = arg + local_wcslen (arg); 3623 arg_end = arg + local_wcslen (arg);
3222 /* The number of bytes doesn't matter. */ 3624 /* The number of bytes and characters doesn't matter,
3625 because !has_width and therefore width==0. */
3626 bytes = 0;
3627# if ENABLE_UNISTDIO
3223 characters = 0; 3628 characters = 0;
3629# endif
3224 } 3630 }
3225# endif 3631# endif
3226 3632
3227# if !DCHAR_IS_TCHAR 3633# 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 { 3634 {
3233 TCHAR_T *tmpptr = tmpsrc; 3635 /* Convert the string into a piece of temporary memory. */
3234 size_t remaining; 3636 TCHAR_T *tmpsrc = (TCHAR_T *) malloc (bytes * sizeof (TCHAR_T));
3637 if (tmpsrc == NULL)
3638 goto out_of_memory;
3639 {
3640 TCHAR_T *tmpptr = tmpsrc;
3235# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3641# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
3236 mbstate_t state; 3642 mbstate_t state;
3237 mbszero (&state); 3643 mbszero (&state);
3238# endif 3644# endif
3239 for (remaining = characters; remaining > 0; ) 3645 for (size_t remaining = bytes; remaining > 0; )
3240 { 3646 {
3241 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ 3647 if (*arg == 0)
3242 int count; 3648 abort ();
3649 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3650 int count = local_wcrtomb (cbuf, *arg, &state);
3651 if (count <= 0)
3652 /* Inconsistency. */
3653 abort ();
3654 memcpy (tmpptr, cbuf, count);
3655 tmpptr += count;
3656 arg++;
3657 remaining -= count;
3658 }
3659 if (!(arg == arg_end))
3660 abort ();
3661 }
3243 3662
3244 if (*arg == 0) 3663 /* Convert from TCHAR_T[] to DCHAR_T[]. */
3245 abort (); 3664 tmpdst =
3246 count = local_wcrtomb (cbuf, *arg, &state); 3665 DCHAR_CONV_FROM_ENCODING (locale_charset (),
3247 if (count <= 0) 3666 iconveh_question_mark,
3248 /* Inconsistency. */ 3667 tmpsrc, bytes,
3249 abort (); 3668 NULL,
3250 memcpy (tmpptr, cbuf, count); 3669 NULL, &tmpdst_len);
3251 tmpptr += count; 3670 if (tmpdst == NULL)
3252 arg++; 3671 {
3253 remaining -= count; 3672 free (tmpsrc);
3673 goto fail_with_errno;
3254 } 3674 }
3255 if (!(arg == arg_end)) 3675 free (tmpsrc);
3256 abort ();
3257 } 3676 }
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 3677# endif
3273 3678
3274 if (has_width) 3679 if (has_width)
@@ -3277,11 +3682,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3277 /* Outside POSIX, it's preferable to compare the width 3682 /* Outside POSIX, it's preferable to compare the width
3278 against the number of _characters_ of the converted 3683 against the number of _characters_ of the converted
3279 value. */ 3684 value. */
3280 w = DCHAR_MBSNLEN (result + length, characters); 3685# if DCHAR_IS_TCHAR
3686 w = characters;
3687# else
3688 w = DCHAR_MBSNLEN (tmpdst, tmpdst_len);
3689# endif
3281# else 3690# else
3282 /* The width is compared against the number of _bytes_ 3691 /* The width is compared against the number of _bytes_
3283 of the converted value, says POSIX. */ 3692 of the converted value, says POSIX. */
3284 w = characters; 3693 w = bytes;
3285# endif 3694# endif
3286 } 3695 }
3287 else 3696 else
@@ -3291,7 +3700,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3291 if (w < width && !(flags & FLAG_LEFT)) 3700 if (w < width && !(flags & FLAG_LEFT))
3292 { 3701 {
3293 size_t n = width - w; 3702 size_t n = width - w;
3703# if DCHAR_IS_TCHAR
3294 ENSURE_ALLOCATION (xsum (length, n)); 3704 ENSURE_ALLOCATION (xsum (length, n));
3705# else
3706 ENSURE_ALLOCATION_ELSE (xsum (length, n),
3707 { free (tmpdst); goto out_of_memory; });
3708# endif
3295 DCHAR_SET (result + length, ' ', n); 3709 DCHAR_SET (result + length, ' ', n);
3296 length += n; 3710 length += n;
3297 } 3711 }
@@ -3300,20 +3714,17 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3300 if (has_precision || has_width) 3714 if (has_precision || has_width)
3301 { 3715 {
3302 /* We know the number of bytes in advance. */ 3716 /* We know the number of bytes in advance. */
3303 size_t remaining;
3304# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3717# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
3305 mbstate_t state; 3718 mbstate_t state;
3306 mbszero (&state); 3719 mbszero (&state);
3307# endif 3720# endif
3308 ENSURE_ALLOCATION (xsum (length, characters)); 3721 ENSURE_ALLOCATION (xsum (length, bytes));
3309 for (remaining = characters; remaining > 0; ) 3722 for (size_t remaining = bytes; remaining > 0; )
3310 { 3723 {
3311 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3312 int count;
3313
3314 if (*arg == 0) 3724 if (*arg == 0)
3315 abort (); 3725 abort ();
3316 count = local_wcrtomb (cbuf, *arg, &state); 3726 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3727 int count = local_wcrtomb (cbuf, *arg, &state);
3317 if (count <= 0) 3728 if (count <= 0)
3318 /* Inconsistency. */ 3729 /* Inconsistency. */
3319 abort (); 3730 abort ();
@@ -3333,12 +3744,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3333# endif 3744# endif
3334 while (arg < arg_end) 3745 while (arg < arg_end)
3335 { 3746 {
3336 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3337 int count;
3338
3339 if (*arg == 0) 3747 if (*arg == 0)
3340 abort (); 3748 abort ();
3341 count = local_wcrtomb (cbuf, *arg, &state); 3749 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3750 int count = local_wcrtomb (cbuf, *arg, &state);
3342 if (count <= 0) 3751 if (count <= 0)
3343 /* Cannot convert. */ 3752 /* Cannot convert. */
3344 goto fail_with_EILSEQ; 3753 goto fail_with_EILSEQ;
@@ -3350,7 +3759,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3350 } 3759 }
3351# else 3760# else
3352 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len), 3761 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
3353 { free (tmpdst); goto out_of_memory; }); 3762 { free (tmpdst); goto out_of_memory; });
3354 DCHAR_CPY (result + length, tmpdst, tmpdst_len); 3763 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
3355 free (tmpdst); 3764 free (tmpdst);
3356 length += tmpdst_len; 3765 length += tmpdst_len;
@@ -3375,20 +3784,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3375 a correct behaviour for the null wint_t argument and/or the 3784 a correct behaviour for the null wint_t argument and/or the
3376 fallback that avoids EILSEQ. */ 3785 fallback that avoids EILSEQ. */
3377 int flags = dp->flags; 3786 int flags = dp->flags;
3378 int has_width;
3379 size_t width;
3380 3787
3381 has_width = 0; 3788 int has_width = 0;
3382 width = 0; 3789 size_t width = 0;
3383 if (dp->width_start != dp->width_end) 3790 if (dp->width_start != dp->width_end)
3384 { 3791 {
3385 if (dp->width_arg_index != ARG_NONE) 3792 if (dp->width_arg_index != ARG_NONE)
3386 { 3793 {
3387 int arg;
3388
3389 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 3794 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3390 abort (); 3795 abort ();
3391 arg = a.arg[dp->width_arg_index].a.a_int; 3796 int arg = a.arg[dp->width_arg_index].a.a_int;
3392 width = arg; 3797 width = arg;
3393 if (arg < 0) 3798 if (arg < 0)
3394 { 3799 {
@@ -3406,17 +3811,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3406 width = xsum (xtimes (width, 10), *digitp++ - '0'); 3811 width = xsum (xtimes (width, 10), *digitp++ - '0');
3407 while (digitp != dp->width_end); 3812 while (digitp != dp->width_end);
3408 } 3813 }
3814 if (width > (size_t) INT_MAX)
3815 goto overflow;
3409 has_width = 1; 3816 has_width = 1;
3410 } 3817 }
3411 3818
3412 /* %lc in vasnprintf. See the specification of fprintf. */ 3819 /* %lc in vasnprintf. See the specification of fprintf. */
3413 { 3820 {
3414 wchar_t arg = (wchar_t) a.arg[dp->arg_index].a.a_wide_char; 3821 wchar_t arg = (wchar_t) a.arg[dp->arg_index].a.a_wide_char;
3822 size_t bytes;
3823# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3415 size_t characters; 3824 size_t characters;
3825# endif
3416# if !DCHAR_IS_TCHAR 3826# if !DCHAR_IS_TCHAR
3417 /* This code assumes that TCHAR_T is 'char'. */ 3827 /* This code assumes that TCHAR_T is 'char'. */
3418 static_assert (sizeof (TCHAR_T) == 1); 3828 static_assert (sizeof (TCHAR_T) == 1);
3419 TCHAR_T tmpsrc[64]; /* Assume MB_CUR_MAX <= 64. */
3420 DCHAR_T *tmpdst; 3829 DCHAR_T *tmpdst;
3421 size_t tmpdst_len; 3830 size_t tmpdst_len;
3422# endif 3831# endif
@@ -3427,55 +3836,63 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3427# endif 3836# endif
3428 { 3837 {
3429 /* Count the number of bytes. */ 3838 /* Count the number of bytes. */
3430 characters = 0;
3431 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3432 int count;
3433# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3839# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
3434 mbstate_t state; 3840 mbstate_t state;
3435 mbszero (&state); 3841 mbszero (&state);
3436# endif 3842# endif
3437 3843
3438 count = local_wcrtomb (cbuf, arg, &state); 3844 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3845 int count = local_wcrtomb (cbuf, arg, &state);
3439 if (count < 0) 3846 if (count < 0)
3440 /* Cannot convert. */ 3847 /* Cannot convert. */
3441 goto fail_with_EILSEQ; 3848 goto fail_with_EILSEQ;
3442 characters = count; 3849 bytes = count;
3850# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR
3851 characters = mbsnlen (cbuf, count);
3852# endif
3443 } 3853 }
3444# if DCHAR_IS_TCHAR 3854# if DCHAR_IS_TCHAR
3445 else 3855 else
3446 { 3856 {
3447 /* The number of bytes doesn't matter. */ 3857 /* The number of bytes and characters doesn't matter,
3858 because !has_width and therefore width==0. */
3859 bytes = 0;
3860# if ENABLE_UNISTDIO
3448 characters = 0; 3861 characters = 0;
3862# endif
3449 } 3863 }
3450# endif 3864# endif
3451 3865
3452# if !DCHAR_IS_TCHAR 3866# if !DCHAR_IS_TCHAR
3453 /* Convert the string into a piece of temporary memory. */ 3867 {
3454 if (characters > 0) 3868 TCHAR_T tmpsrc[64]; /* Assume MB_CUR_MAX <= 64. */
3455 { 3869
3456 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ 3870 /* Convert the string into a piece of temporary memory. */
3457 int count; 3871 if (bytes > 0)
3872 {
3458# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3873# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
3459 mbstate_t state; 3874 mbstate_t state;
3460 mbszero (&state); 3875 mbszero (&state);
3461# endif 3876# endif
3462 3877
3463 count = local_wcrtomb (cbuf, arg, &state); 3878 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3464 if (count <= 0) 3879 int count = local_wcrtomb (cbuf, arg, &state);
3465 /* Inconsistency. */ 3880 if (count <= 0)
3466 abort (); 3881 /* Inconsistency. */
3467 memcpy (tmpsrc, cbuf, count); 3882 abort ();
3468 } 3883 memcpy (tmpsrc, cbuf, count);
3884 }
3469 3885
3470 /* Convert from TCHAR_T[] to DCHAR_T[]. */ 3886 /* Convert from TCHAR_T[] to DCHAR_T[]. */
3471 tmpdst = 3887 tmpdst =
3472 DCHAR_CONV_FROM_ENCODING (locale_charset (), 3888 DCHAR_CONV_FROM_ENCODING (locale_charset (),
3473 iconveh_question_mark, 3889 iconveh_question_mark,
3474 tmpsrc, characters, 3890 tmpsrc, bytes,
3475 NULL, 3891 NULL,
3476 NULL, &tmpdst_len); 3892 NULL, &tmpdst_len);
3477 if (tmpdst == NULL) 3893 if (tmpdst == NULL)
3478 goto fail_with_errno; 3894 goto fail_with_errno;
3895 }
3479# endif 3896# endif
3480 3897
3481 if (has_width) 3898 if (has_width)
@@ -3484,11 +3901,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3484 /* Outside POSIX, it's preferable to compare the width 3901 /* Outside POSIX, it's preferable to compare the width
3485 against the number of _characters_ of the converted 3902 against the number of _characters_ of the converted
3486 value. */ 3903 value. */
3487 w = DCHAR_MBSNLEN (result + length, characters); 3904# if DCHAR_IS_TCHAR
3905 w = characters;
3906# else
3907 w = DCHAR_MBSNLEN (tmpdst, tmpdst_len);
3908# endif
3488# else 3909# else
3489 /* The width is compared against the number of _bytes_ 3910 /* The width is compared against the number of _bytes_
3490 of the converted value, says POSIX. */ 3911 of the converted value, says POSIX. */
3491 w = characters; 3912 w = bytes;
3492# endif 3913# endif
3493 } 3914 }
3494 else 3915 else
@@ -3498,7 +3919,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3498 if (w < width && !(flags & FLAG_LEFT)) 3919 if (w < width && !(flags & FLAG_LEFT))
3499 { 3920 {
3500 size_t n = width - w; 3921 size_t n = width - w;
3922# if DCHAR_IS_TCHAR
3501 ENSURE_ALLOCATION (xsum (length, n)); 3923 ENSURE_ALLOCATION (xsum (length, n));
3924# else
3925 ENSURE_ALLOCATION_ELSE (xsum (length, n),
3926 { free (tmpdst); goto out_of_memory; });
3927# endif
3502 DCHAR_SET (result + length, ' ', n); 3928 DCHAR_SET (result + length, ' ', n);
3503 length += n; 3929 length += n;
3504 } 3930 }
@@ -3507,16 +3933,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3507 if (has_width) 3933 if (has_width)
3508 { 3934 {
3509 /* We know the number of bytes in advance. */ 3935 /* We know the number of bytes in advance. */
3510 ENSURE_ALLOCATION (xsum (length, characters)); 3936 ENSURE_ALLOCATION (xsum (length, bytes));
3511 if (characters > 0) 3937 if (bytes > 0)
3512 { 3938 {
3513 int count;
3514# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3939# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
3515 mbstate_t state; 3940 mbstate_t state;
3516 mbszero (&state); 3941 mbszero (&state);
3517# endif 3942# endif
3518 3943
3519 count = local_wcrtomb (result + length, arg, &state); 3944 int count = local_wcrtomb (result + length, arg, &state);
3520 if (count <= 0) 3945 if (count <= 0)
3521 /* Inconsistency. */ 3946 /* Inconsistency. */
3522 abort (); 3947 abort ();
@@ -3525,14 +3950,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3525 } 3950 }
3526 else 3951 else
3527 { 3952 {
3528 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3529 int count;
3530# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t 3953# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
3531 mbstate_t state; 3954 mbstate_t state;
3532 mbszero (&state); 3955 mbszero (&state);
3533# endif 3956# endif
3534 3957
3535 count = local_wcrtomb (cbuf, arg, &state); 3958 char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
3959 int count = local_wcrtomb (cbuf, arg, &state);
3536 if (count < 0) 3960 if (count < 0)
3537 /* Cannot convert. */ 3961 /* Cannot convert. */
3538 goto fail_with_EILSEQ; 3962 goto fail_with_EILSEQ;
@@ -3542,7 +3966,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3542 } 3966 }
3543# else 3967# else
3544 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len), 3968 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
3545 { free (tmpdst); goto out_of_memory; }); 3969 { free (tmpdst); goto out_of_memory; });
3546 DCHAR_CPY (result + length, tmpdst, tmpdst_len); 3970 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
3547 free (tmpdst); 3971 free (tmpdst);
3548 length += tmpdst_len; 3972 length += tmpdst_len;
@@ -3565,18 +3989,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3565 /* Implement the 'c' directive ourselves, in order to avoid 3989 /* Implement the 'c' directive ourselves, in order to avoid
3566 EILSEQ in the "C" locale. */ 3990 EILSEQ in the "C" locale. */
3567 int flags = dp->flags; 3991 int flags = dp->flags;
3568 size_t width;
3569 3992
3570 width = 0; 3993 size_t width = 0;
3571 if (dp->width_start != dp->width_end) 3994 if (dp->width_start != dp->width_end)
3572 { 3995 {
3573 if (dp->width_arg_index != ARG_NONE) 3996 if (dp->width_arg_index != ARG_NONE)
3574 { 3997 {
3575 int arg;
3576
3577 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 3998 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3578 abort (); 3999 abort ();
3579 arg = a.arg[dp->width_arg_index].a.a_int; 4000 int arg = a.arg[dp->width_arg_index].a.a_int;
3580 width = arg; 4001 width = arg;
3581 if (arg < 0) 4002 if (arg < 0)
3582 { 4003 {
@@ -3594,38 +4015,42 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3594 width = xsum (xtimes (width, 10), *digitp++ - '0'); 4015 width = xsum (xtimes (width, 10), *digitp++ - '0');
3595 while (digitp != dp->width_end); 4016 while (digitp != dp->width_end);
3596 } 4017 }
4018 if (width > (size_t) INT_MAX)
4019 goto overflow;
3597 } 4020 }
3598 4021
3599 /* %c in vasnwprintf. See the specification of fwprintf. */ 4022 /* %c in vasnwprintf. See the specification of fwprintf. */
3600 { 4023 {
3601 char arg = (char) a.arg[dp->arg_index].a.a_char; 4024 char arg = (char) a.arg[dp->arg_index].a.a_char;
3602 mbstate_t state; 4025 mbstate_t state;
3603 wchar_t wc;
3604
3605 mbszero (&state); 4026 mbszero (&state);
4027
4028 wchar_t wc;
3606 int count = mbrtowc (&wc, &arg, 1, &state); 4029 int count = mbrtowc (&wc, &arg, 1, &state);
3607 if (count < 0) 4030 if (count < 0)
3608 /* Invalid or incomplete multibyte character. */ 4031 /* Invalid or incomplete multibyte character. */
3609 goto fail_with_EILSEQ; 4032 goto fail_with_EILSEQ;
3610 4033
3611 if (1 < width && !(flags & FLAG_LEFT)) 4034 {
3612 { 4035 size_t total = (1 < width ? width : 1);
3613 size_t n = width - 1; 4036 ENSURE_ALLOCATION (xsum (length, total));
3614 ENSURE_ALLOCATION (xsum (length, n));
3615 DCHAR_SET (result + length, ' ', n);
3616 length += n;
3617 }
3618 4037
3619 ENSURE_ALLOCATION (xsum (length, 1)); 4038 if (1 < width && !(flags & FLAG_LEFT))
3620 result[length++] = wc; 4039 {
4040 size_t n = width - 1;
4041 DCHAR_SET (result + length, ' ', n);
4042 length += n;
4043 }
3621 4044
3622 if (1 < width && (flags & FLAG_LEFT)) 4045 result[length++] = wc;
3623 { 4046
3624 size_t n = width - 1; 4047 if (1 < width && (flags & FLAG_LEFT))
3625 ENSURE_ALLOCATION (xsum (length, n)); 4048 {
3626 DCHAR_SET (result + length, ' ', n); 4049 size_t n = width - 1;
3627 length += n; 4050 DCHAR_SET (result + length, ' ', n);
3628 } 4051 length += n;
4052 }
4053 }
3629 } 4054 }
3630 } 4055 }
3631#endif 4056#endif
@@ -3641,30 +4066,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3641 { 4066 {
3642 arg_type type = a.arg[dp->arg_index].type; 4067 arg_type type = a.arg[dp->arg_index].type;
3643 int flags = dp->flags; 4068 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 4069
3657 has_width = 0; 4070 int has_width = 0;
3658 width = 0; 4071 size_t width = 0;
3659 if (dp->width_start != dp->width_end) 4072 if (dp->width_start != dp->width_end)
3660 { 4073 {
3661 if (dp->width_arg_index != ARG_NONE) 4074 if (dp->width_arg_index != ARG_NONE)
3662 { 4075 {
3663 int arg;
3664
3665 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 4076 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3666 abort (); 4077 abort ();
3667 arg = a.arg[dp->width_arg_index].a.a_int; 4078 int arg = a.arg[dp->width_arg_index].a.a_int;
3668 width = arg; 4079 width = arg;
3669 if (arg < 0) 4080 if (arg < 0)
3670 { 4081 {
@@ -3682,20 +4093,20 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3682 width = xsum (xtimes (width, 10), *digitp++ - '0'); 4093 width = xsum (xtimes (width, 10), *digitp++ - '0');
3683 while (digitp != dp->width_end); 4094 while (digitp != dp->width_end);
3684 } 4095 }
4096 if (width > (size_t) INT_MAX)
4097 goto overflow;
3685 has_width = 1; 4098 has_width = 1;
3686 } 4099 }
3687 4100
3688 has_precision = 0; 4101 int has_precision = 0;
3689 precision = 1; 4102 size_t precision = 1;
3690 if (dp->precision_start != dp->precision_end) 4103 if (dp->precision_start != dp->precision_end)
3691 { 4104 {
3692 if (dp->precision_arg_index != ARG_NONE) 4105 if (dp->precision_arg_index != ARG_NONE)
3693 { 4106 {
3694 int arg;
3695
3696 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 4107 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
3697 abort (); 4108 abort ();
3698 arg = a.arg[dp->precision_arg_index].a.a_int; 4109 int arg = a.arg[dp->precision_arg_index].a.a_int;
3699 /* "A negative precision is taken as if the precision 4110 /* "A negative precision is taken as if the precision
3700 were omitted." */ 4111 were omitted." */
3701 if (arg >= 0) 4112 if (arg >= 0)
@@ -3716,6 +4127,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3716 } 4127 }
3717 4128
3718 /* Allocate a temporary buffer of sufficient size. */ 4129 /* Allocate a temporary buffer of sufficient size. */
4130 size_t tmp_length;
3719 switch (type) 4131 switch (type)
3720 { 4132 {
3721 default: 4133 default:
@@ -3782,6 +4194,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3782 if (tmp_length < width) 4194 if (tmp_length < width)
3783 tmp_length = width; 4195 tmp_length = width;
3784 4196
4197 DCHAR_T tmpbuf[700];
4198 DCHAR_T *tmp;
3785 if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) 4199 if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
3786 tmp = tmpbuf; 4200 tmp = tmpbuf;
3787 else 4201 else
@@ -3797,7 +4211,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3797 goto out_of_memory; 4211 goto out_of_memory;
3798 } 4212 }
3799 4213
3800 tmp_end = tmp + tmp_length; 4214 DCHAR_T *tmp_end = tmp + tmp_length;
3801 4215
3802 unsigned long long arg; 4216 unsigned long long arg;
3803 switch (type) 4217 switch (type)
@@ -3846,7 +4260,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3846 } 4260 }
3847 int need_prefix = ((flags & FLAG_ALT) && arg != 0); 4261 int need_prefix = ((flags & FLAG_ALT) && arg != 0);
3848 4262
3849 p = tmp_end; 4263 DCHAR_T *p = tmp_end;
3850 /* "The result of converting a zero value with a precision 4264 /* "The result of converting a zero value with a precision
3851 of zero is no characters." */ 4265 of zero is no characters." */
3852 if (!(has_precision && precision == 0 && arg == 0)) 4266 if (!(has_precision && precision == 0 && arg == 0))
@@ -3866,7 +4280,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3866 *--p = '0'; 4280 *--p = '0';
3867 } 4281 }
3868 4282
3869 pad_ptr = p; 4283 DCHAR_T *pad_ptr = p;
3870 4284
3871 if (need_prefix) 4285 if (need_prefix)
3872 { 4286 {
@@ -3879,12 +4293,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3879# endif 4293# endif
3880 *--p = '0'; 4294 *--p = '0';
3881 } 4295 }
3882 tmp_start = p; 4296 DCHAR_T *tmp_start = p;
3883 4297
3884 /* The generated string now extends from tmp_start to tmp_end, 4298 /* The generated string now extends from tmp_start to tmp_end,
3885 with the zero padding insertion point being at pad_ptr, 4299 with the zero padding insertion point being at pad_ptr,
3886 tmp_start <= pad_ptr <= tmp_end. */ 4300 tmp_start <= pad_ptr <= tmp_end. */
3887 count = tmp_end - tmp_start; 4301 size_t count = tmp_end - tmp_start;
3888 4302
3889 if (count < width) 4303 if (count < width)
3890 { 4304 {
@@ -3933,7 +4347,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3933 { 4347 {
3934 size_t n = xsum (length, count); 4348 size_t n = xsum (length, count);
3935 4349
3936 ENSURE_ALLOCATION (n); 4350 ENSURE_ALLOCATION_ELSE (n,
4351 { if (tmp != tmpbuf) free (tmp); goto out_of_memory; });
3937 } 4352 }
3938 4353
3939 /* Append the result. */ 4354 /* Append the result. */
@@ -3959,26 +4374,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3959 { 4374 {
3960 arg_type type = a.arg[dp->arg_index].type; 4375 arg_type type = a.arg[dp->arg_index].type;
3961 int flags = dp->flags; 4376 int flags = dp->flags;
3962 size_t width;
3963 int has_precision;
3964 size_t precision;
3965 size_t tmp_length;
3966 size_t count;
3967 DCHAR_T tmpbuf[700];
3968 DCHAR_T *tmp;
3969 DCHAR_T *pad_ptr;
3970 DCHAR_T *p;
3971 4377
3972 width = 0; 4378 size_t width = 0;
3973 if (dp->width_start != dp->width_end) 4379 if (dp->width_start != dp->width_end)
3974 { 4380 {
3975 if (dp->width_arg_index != ARG_NONE) 4381 if (dp->width_arg_index != ARG_NONE)
3976 { 4382 {
3977 int arg;
3978
3979 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 4383 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3980 abort (); 4384 abort ();
3981 arg = a.arg[dp->width_arg_index].a.a_int; 4385 int arg = a.arg[dp->width_arg_index].a.a_int;
3982 width = arg; 4386 width = arg;
3983 if (arg < 0) 4387 if (arg < 0)
3984 { 4388 {
@@ -3996,19 +4400,19 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
3996 width = xsum (xtimes (width, 10), *digitp++ - '0'); 4400 width = xsum (xtimes (width, 10), *digitp++ - '0');
3997 while (digitp != dp->width_end); 4401 while (digitp != dp->width_end);
3998 } 4402 }
4403 if (width > (size_t) INT_MAX)
4404 goto overflow;
3999 } 4405 }
4000 4406
4001 has_precision = 0; 4407 int has_precision = 0;
4002 precision = 0; 4408 size_t precision = 0;
4003 if (dp->precision_start != dp->precision_end) 4409 if (dp->precision_start != dp->precision_end)
4004 { 4410 {
4005 if (dp->precision_arg_index != ARG_NONE) 4411 if (dp->precision_arg_index != ARG_NONE)
4006 { 4412 {
4007 int arg;
4008
4009 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 4413 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
4010 abort (); 4414 abort ();
4011 arg = a.arg[dp->precision_arg_index].a.a_int; 4415 int arg = a.arg[dp->precision_arg_index].a.a_int;
4012 /* "A negative precision is taken as if the precision 4416 /* "A negative precision is taken as if the precision
4013 were omitted." */ 4417 were omitted." */
4014 if (arg >= 0) 4418 if (arg >= 0)
@@ -4029,6 +4433,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4029 } 4433 }
4030 4434
4031 /* Allocate a temporary buffer of sufficient size. */ 4435 /* Allocate a temporary buffer of sufficient size. */
4436 size_t tmp_length;
4032 if (type == TYPE_LONGDOUBLE) 4437 if (type == TYPE_LONGDOUBLE)
4033 tmp_length = 4438 tmp_length =
4034 (unsigned int) ((LDBL_DIG + 1) 4439 (unsigned int) ((LDBL_DIG + 1)
@@ -4051,6 +4456,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4051 4456
4052 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ 4457 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
4053 4458
4459 DCHAR_T tmpbuf[700];
4460 DCHAR_T *tmp;
4054 if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) 4461 if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
4055 tmp = tmpbuf; 4462 tmp = tmpbuf;
4056 else 4463 else
@@ -4066,8 +4473,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4066 goto out_of_memory; 4473 goto out_of_memory;
4067 } 4474 }
4068 4475
4069 pad_ptr = NULL; 4476 DCHAR_T *pad_ptr = NULL;
4070 p = tmp; 4477 DCHAR_T *p = tmp;
4071 if (type == TYPE_LONGDOUBLE) 4478 if (type == TYPE_LONGDOUBLE)
4072 { 4479 {
4073# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION) 4480# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION)
@@ -4086,11 +4493,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4086 } 4493 }
4087 else 4494 else
4088 { 4495 {
4089 int sign = 0;
4090 DECL_LONG_DOUBLE_ROUNDING 4496 DECL_LONG_DOUBLE_ROUNDING
4091 4497
4092 BEGIN_LONG_DOUBLE_ROUNDING (); 4498 BEGIN_LONG_DOUBLE_ROUNDING ();
4093 4499
4500 int sign = 0;
4094 if (signbit (arg)) /* arg < 0.0L or negative zero */ 4501 if (signbit (arg)) /* arg < 0.0L or negative zero */
4095 { 4502 {
4096 sign = -1; 4503 sign = -1;
@@ -4119,7 +4526,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4119 { 4526 {
4120 int exponent; 4527 int exponent;
4121 long double mantissa; 4528 long double mantissa;
4122
4123 if (arg > 0.0L) 4529 if (arg > 0.0L)
4124 mantissa = printf_frexpl (arg, &exponent); 4530 mantissa = printf_frexpl (arg, &exponent);
4125 else 4531 else
@@ -4133,9 +4539,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4133 { 4539 {
4134 /* Round the mantissa. */ 4540 /* Round the mantissa. */
4135 long double tail = mantissa; 4541 long double tail = mantissa;
4136 size_t q;
4137 4542
4138 for (q = precision; ; q--) 4543 for (size_t q = precision; ; q--)
4139 { 4544 {
4140 int digit = (int) tail; 4545 int digit = (int) tail;
4141 tail -= digit; 4546 tail -= digit;
@@ -4150,7 +4555,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4150 tail *= 16.0L; 4555 tail *= 16.0L;
4151 } 4556 }
4152 if (tail != 0.0L) 4557 if (tail != 0.0L)
4153 for (q = precision; q > 0; q--) 4558 for (size_t q = precision; q > 0; q--)
4154 tail *= 0.0625L; 4559 tail *= 0.0625L;
4155 mantissa += tail; 4560 mantissa += tail;
4156 } 4561 }
@@ -4159,9 +4564,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4159 *p++ = dp->conversion - 'A' + 'X'; 4564 *p++ = dp->conversion - 'A' + 'X';
4160 pad_ptr = p; 4565 pad_ptr = p;
4161 { 4566 {
4162 int digit; 4567 int digit = (int) mantissa;
4163
4164 digit = (int) mantissa;
4165 mantissa -= digit; 4568 mantissa -= digit;
4166 *p++ = '0' + digit; 4569 *p++ = '0' + digit;
4167 if ((flags & FLAG_ALT) 4570 if ((flags & FLAG_ALT)
@@ -4208,9 +4611,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4208 else 4611 else
4209 { 4612 {
4210 char expbuf[6 + 1]; 4613 char expbuf[6 + 1];
4211 const char *ep;
4212 sprintf (expbuf, "%+d", exponent); 4614 sprintf (expbuf, "%+d", exponent);
4213 for (ep = expbuf; (*p = *ep) != '\0'; ep++) 4615 for (const char *ep = expbuf; (*p = *ep) != '\0'; ep++)
4214 p++; 4616 p++;
4215 } 4617 }
4216# endif 4618# endif
@@ -4241,7 +4643,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4241 else 4643 else
4242 { 4644 {
4243 int sign = 0; 4645 int sign = 0;
4244
4245 if (signbit (arg)) /* arg < 0.0 or negative zero */ 4646 if (signbit (arg)) /* arg < 0.0 or negative zero */
4246 { 4647 {
4247 sign = -1; 4648 sign = -1;
@@ -4270,7 +4671,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4270 { 4671 {
4271 int exponent; 4672 int exponent;
4272 double mantissa; 4673 double mantissa;
4273
4274 if (arg > 0.0) 4674 if (arg > 0.0)
4275 mantissa = printf_frexp (arg, &exponent); 4675 mantissa = printf_frexp (arg, &exponent);
4276 else 4676 else
@@ -4284,9 +4684,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4284 { 4684 {
4285 /* Round the mantissa. */ 4685 /* Round the mantissa. */
4286 double tail = mantissa; 4686 double tail = mantissa;
4287 size_t q;
4288 4687
4289 for (q = precision; ; q--) 4688 for (size_t q = precision; ; q--)
4290 { 4689 {
4291 int digit = (int) tail; 4690 int digit = (int) tail;
4292 tail -= digit; 4691 tail -= digit;
@@ -4301,7 +4700,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4301 tail *= 16.0; 4700 tail *= 16.0;
4302 } 4701 }
4303 if (tail != 0.0) 4702 if (tail != 0.0)
4304 for (q = precision; q > 0; q--) 4703 for (size_t q = precision; q > 0; q--)
4305 tail *= 0.0625; 4704 tail *= 0.0625;
4306 mantissa += tail; 4705 mantissa += tail;
4307 } 4706 }
@@ -4310,9 +4709,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4310 *p++ = dp->conversion - 'A' + 'X'; 4709 *p++ = dp->conversion - 'A' + 'X';
4311 pad_ptr = p; 4710 pad_ptr = p;
4312 { 4711 {
4313 int digit; 4712 int digit = (int) mantissa;
4314
4315 digit = (int) mantissa;
4316 mantissa -= digit; 4713 mantissa -= digit;
4317 *p++ = '0' + digit; 4714 *p++ = '0' + digit;
4318 if ((flags & FLAG_ALT) 4715 if ((flags & FLAG_ALT)
@@ -4359,9 +4756,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4359 else 4756 else
4360 { 4757 {
4361 char expbuf[6 + 1]; 4758 char expbuf[6 + 1];
4362 const char *ep;
4363 sprintf (expbuf, "%+d", exponent); 4759 sprintf (expbuf, "%+d", exponent);
4364 for (ep = expbuf; (*p = *ep) != '\0'; ep++) 4760 for (const char *ep = expbuf; (*p = *ep) != '\0'; ep++)
4365 p++; 4761 p++;
4366 } 4762 }
4367# endif 4763# endif
@@ -4374,7 +4770,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4374 4770
4375 /* The generated string now extends from tmp to p, with the 4771 /* The generated string now extends from tmp to p, with the
4376 zero padding insertion point being at pad_ptr. */ 4772 zero padding insertion point being at pad_ptr. */
4377 count = p - tmp; 4773 size_t count = p - tmp;
4378 4774
4379 if (count < width) 4775 if (count < width)
4380 { 4776 {
@@ -4423,7 +4819,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4423 { 4819 {
4424 size_t n = xsum (length, count); 4820 size_t n = xsum (length, count);
4425 4821
4426 ENSURE_ALLOCATION (n); 4822 ENSURE_ALLOCATION_ELSE (n,
4823 { if (tmp != tmpbuf) free (tmp); goto out_of_memory; });
4427 } 4824 }
4428 4825
4429 /* Append the result. */ 4826 /* Append the result. */
@@ -4454,8 +4851,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4454 || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE 4851 || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
4455 /* Some systems produce wrong output for Inf, 4852 /* Some systems produce wrong output for Inf,
4456 -Inf, and NaN. Some systems in this category 4853 -Inf, and NaN. Some systems in this category
4457 (IRIX 5.3) also do so for -0.0. Therefore we 4854 also do so for -0.0. Therefore we treat this
4458 treat this case here as well. */ 4855 case here as well. */
4459 && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble)) 4856 && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
4460# endif 4857# endif
4461 )) 4858 ))
@@ -4464,26 +4861,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4464 arg_type type = a.arg[dp->arg_index].type; 4861 arg_type type = a.arg[dp->arg_index].type;
4465# endif 4862# endif
4466 int flags = dp->flags; 4863 int flags = dp->flags;
4467 size_t width;
4468 size_t count;
4469 int has_precision;
4470 size_t precision;
4471 size_t tmp_length;
4472 DCHAR_T tmpbuf[700];
4473 DCHAR_T *tmp;
4474 DCHAR_T *pad_ptr;
4475 DCHAR_T *p;
4476 4864
4477 width = 0; 4865 size_t width = 0;
4478 if (dp->width_start != dp->width_end) 4866 if (dp->width_start != dp->width_end)
4479 { 4867 {
4480 if (dp->width_arg_index != ARG_NONE) 4868 if (dp->width_arg_index != ARG_NONE)
4481 { 4869 {
4482 int arg;
4483
4484 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 4870 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
4485 abort (); 4871 abort ();
4486 arg = a.arg[dp->width_arg_index].a.a_int; 4872 int arg = a.arg[dp->width_arg_index].a.a_int;
4487 width = arg; 4873 width = arg;
4488 if (arg < 0) 4874 if (arg < 0)
4489 { 4875 {
@@ -4501,19 +4887,19 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4501 width = xsum (xtimes (width, 10), *digitp++ - '0'); 4887 width = xsum (xtimes (width, 10), *digitp++ - '0');
4502 while (digitp != dp->width_end); 4888 while (digitp != dp->width_end);
4503 } 4889 }
4890 if (width > (size_t) INT_MAX)
4891 goto overflow;
4504 } 4892 }
4505 4893
4506 has_precision = 0; 4894 int has_precision = 0;
4507 precision = 0; 4895 size_t precision = 0;
4508 if (dp->precision_start != dp->precision_end) 4896 if (dp->precision_start != dp->precision_end)
4509 { 4897 {
4510 if (dp->precision_arg_index != ARG_NONE) 4898 if (dp->precision_arg_index != ARG_NONE)
4511 { 4899 {
4512 int arg;
4513
4514 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 4900 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
4515 abort (); 4901 abort ();
4516 arg = a.arg[dp->precision_arg_index].a.a_int; 4902 int arg = a.arg[dp->precision_arg_index].a.a_int;
4517 /* "A negative precision is taken as if the precision 4903 /* "A negative precision is taken as if the precision
4518 were omitted." */ 4904 were omitted." */
4519 if (arg >= 0) 4905 if (arg >= 0)
@@ -4542,6 +4928,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4542 precision = 6; 4928 precision = 6;
4543 4929
4544 /* Allocate a temporary buffer of sufficient size. */ 4930 /* Allocate a temporary buffer of sufficient size. */
4931 size_t tmp_length;
4545# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE 4932# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
4546 tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1); 4933 tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
4547# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE 4934# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
@@ -4587,6 +4974,17 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4587 } 4974 }
4588 } 4975 }
4589# endif 4976# endif
4977 /* Account for thousands separators. */
4978 if (flags & FLAG_GROUP)
4979 {
4980 /* A thousands separator needs to be inserted at most every 2 digits.
4981 This is the case in the ta_IN locale. */
4982# if WIDE_CHAR_VERSION
4983 tmp_length = xsum (tmp_length, tmp_length / 2 * THOUSEP_WCHAR_MAXLEN);
4984# else
4985 tmp_length = xsum (tmp_length, tmp_length / 2 * THOUSEP_CHAR_MAXLEN);
4986# endif
4987 }
4590 /* Account for sign, decimal point etc. */ 4988 /* Account for sign, decimal point etc. */
4591 tmp_length = xsum (tmp_length, 12); 4989 tmp_length = xsum (tmp_length, 12);
4592 4990
@@ -4595,6 +4993,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4595 4993
4596 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ 4994 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
4597 4995
4996 DCHAR_T tmpbuf[700];
4997 DCHAR_T *tmp;
4598 if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) 4998 if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
4599 tmp = tmpbuf; 4999 tmp = tmpbuf;
4600 else 5000 else
@@ -4610,8 +5010,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4610 goto out_of_memory; 5010 goto out_of_memory;
4611 } 5011 }
4612 5012
4613 pad_ptr = NULL; 5013 DCHAR_T *pad_ptr = NULL;
4614 p = tmp; 5014 DCHAR_T *p = tmp;
4615 5015
4616# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE 5016# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
4617# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE 5017# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
@@ -4633,11 +5033,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4633 } 5033 }
4634 else 5034 else
4635 { 5035 {
4636 int sign = 0;
4637 DECL_LONG_DOUBLE_ROUNDING 5036 DECL_LONG_DOUBLE_ROUNDING
4638 5037
4639 BEGIN_LONG_DOUBLE_ROUNDING (); 5038 BEGIN_LONG_DOUBLE_ROUNDING ();
4640 5039
5040 int sign = 0;
4641 if (signbit (arg)) /* arg < 0.0L or negative zero */ 5041 if (signbit (arg)) /* arg < 0.0L or negative zero */
4642 { 5042 {
4643 sign = -1; 5043 sign = -1;
@@ -4669,25 +5069,94 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4669 5069
4670 if (dp->conversion == 'f' || dp->conversion == 'F') 5070 if (dp->conversion == 'f' || dp->conversion == 'F')
4671 { 5071 {
4672 char *digits; 5072 char *digits =
4673 size_t ndigits;
4674
4675 digits =
4676 scale10_round_decimal_long_double (arg, precision); 5073 scale10_round_decimal_long_double (arg, precision);
4677 if (digits == NULL) 5074 if (digits == NULL)
4678 { 5075 {
4679 END_LONG_DOUBLE_ROUNDING (); 5076 END_LONG_DOUBLE_ROUNDING ();
4680 goto out_of_memory; 5077 goto out_of_memory;
4681 } 5078 }
4682 ndigits = strlen (digits); 5079 size_t ndigits = strlen (digits);
4683 5080
4684 if (ndigits > precision) 5081 if (ndigits > precision)
4685 do 5082 {
4686 { 5083 /* Number of digits before the decimal point. */
4687 --ndigits; 5084 size_t intpart_digits = ndigits - precision;
4688 *p++ = digits[ndigits]; 5085
4689 } 5086 const DCHAR_T *thousep = NULL;
4690 while (ndigits > precision); 5087 DCHAR_T thousep_buf[10];
5088# if !WIDE_CHAR_VERSION
5089 size_t thousep_len = 0;
5090# endif
5091 const signed char *grouping;
5092 size_t insert = 0;
5093
5094 if ((flags & FLAG_GROUP) && (intpart_digits > 1))
5095 {
5096 /* Determine the thousands separator and
5097 the grouping rule of the current locale. */
5098# if WIDE_CHAR_VERSION
5099 /* DCHAR_T is wchar_t. */
5100 thousep = thousands_separator_wchar (thousep_buf);
5101# define thousep_len 1
5102# elif defined DCHAR_CONV_FROM_ENCODING
5103 /* DCHAR_T is uintN_t. */
5104 thousep = thousands_separator_DCHAR (thousep_buf);
5105 thousep_len = DCHAR_STRLEN (thousep);
5106# else
5107 /* DCHAR_T is char. */
5108 thousep = thousands_separator_char (thousep_buf);
5109 thousep_len = strlen (thousep);
5110# endif
5111 if (*thousep == 0)
5112 thousep = NULL;
5113 if (thousep != NULL)
5114 {
5115 grouping = grouping_rule ();
5116 insert =
5117 num_thousands_separators (grouping, intpart_digits);
5118 }
5119 }
5120
5121 const char *digitp = digits + precision;
5122 DCHAR_T *p_before_intpart = p;
5123 p += intpart_digits + insert * thousep_len;
5124 DCHAR_T *p_after_intpart = p;
5125 if (insert > 0) /* implies (flag & FLAG_GROUP) && (thousep != NULL) */
5126 {
5127 const signed char *g = grouping;
5128 for (;;)
5129 {
5130 int h = *g;
5131 if (h <= 0)
5132 abort ();
5133 int i = h;
5134 do
5135 *--p = *digitp++;
5136 while (--i > 0);
5137# if WIDE_CHAR_VERSION
5138 *--p = thousep[0];
5139# else
5140 p -= thousep_len;
5141 DCHAR_CPY (p, thousep, thousep_len);
5142# endif
5143 insert--;
5144 if (insert == 0)
5145 break;
5146 if (g[1] != 0)
5147 g++;
5148 }
5149 }
5150 for (;;)
5151 {
5152 *--p = *digitp++;
5153 if (p == p_before_intpart)
5154 break;
5155 }
5156 p = p_after_intpart;
5157 ndigits = precision;
5158# undef thousep_len
5159 }
4691 else 5160 else
4692 *p++ = '0'; 5161 *p++ = '0';
4693 /* Here ndigits <= precision. */ 5162 /* Here ndigits <= precision. */
@@ -4723,12 +5192,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4723 else 5192 else
4724 { 5193 {
4725 /* arg > 0.0L. */ 5194 /* arg > 0.0L. */
4726 int adjusted; 5195 exponent = floorlog10l (arg);
5196 int adjusted = 0;
4727 char *digits; 5197 char *digits;
4728 size_t ndigits; 5198 size_t ndigits;
4729
4730 exponent = floorlog10l (arg);
4731 adjusted = 0;
4732 for (;;) 5199 for (;;)
4733 { 5200 {
4734 digits = 5201 digits =
@@ -4819,9 +5286,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4819 else 5286 else
4820 { 5287 {
4821 char expbuf[6 + 1]; 5288 char expbuf[6 + 1];
4822 const char *ep;
4823 sprintf (expbuf, "%+.2d", exponent); 5289 sprintf (expbuf, "%+.2d", exponent);
4824 for (ep = expbuf; (*p = *ep) != '\0'; ep++) 5290 for (const char *ep = expbuf; (*p = *ep) != '\0'; ep++)
4825 p++; 5291 p++;
4826 } 5292 }
4827# endif 5293# endif
@@ -4857,14 +5323,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4857 else 5323 else
4858 { 5324 {
4859 /* arg > 0.0L. */ 5325 /* arg > 0.0L. */
4860 int exponent; 5326 int exponent = floorlog10l (arg);
4861 int adjusted; 5327 int adjusted = 0;
4862 char *digits; 5328 char *digits;
4863 size_t ndigits; 5329 size_t ndigits;
4864 size_t nzeroes;
4865
4866 exponent = floorlog10l (arg);
4867 adjusted = 0;
4868 for (;;) 5330 for (;;)
4869 { 5331 {
4870 digits = 5332 digits =
@@ -4924,7 +5386,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4924 5386
4925 /* Determine the number of trailing zeroes 5387 /* Determine the number of trailing zeroes
4926 that have to be dropped. */ 5388 that have to be dropped. */
4927 nzeroes = 0; 5389 size_t nzeroes = 0;
4928 if ((flags & FLAG_ALT) == 0) 5390 if ((flags & FLAG_ALT) == 0)
4929 while (nzeroes < ndigits 5391 while (nzeroes < ndigits
4930 && digits[nzeroes] == '0') 5392 && digits[nzeroes] == '0')
@@ -4940,10 +5402,84 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
4940 digits without trailing zeroes. */ 5402 digits without trailing zeroes. */
4941 if (exponent >= 0) 5403 if (exponent >= 0)
4942 { 5404 {
4943 size_t ecount = exponent + 1; 5405 /* Number of digits before the decimal point. */
4944 /* Note: count <= precision = ndigits. */ 5406 size_t intpart_digits = exponent + 1;
4945 for (; ecount > 0; ecount--) 5407 /* Note: intpart_digits <= precision = ndigits. */
4946 *p++ = digits[--ndigits]; 5408
5409 const DCHAR_T *thousep = NULL;
5410 DCHAR_T thousep_buf[10];
5411# if !WIDE_CHAR_VERSION
5412 size_t thousep_len = 0;
5413# endif
5414 const signed char *grouping;
5415 size_t insert = 0;
5416
5417 if ((flags & FLAG_GROUP) && (intpart_digits > 1))
5418 {
5419 /* Determine the thousands separator and
5420 the grouping rule of the current locale. */
5421# if WIDE_CHAR_VERSION
5422 /* DCHAR_T is wchar_t. */
5423 thousep = thousands_separator_wchar (thousep_buf);
5424# define thousep_len 1
5425# elif defined DCHAR_CONV_FROM_ENCODING
5426 /* DCHAR_T is uintN_t. */
5427 thousep = thousands_separator_DCHAR (thousep_buf);
5428 thousep_len = DCHAR_STRLEN (thousep);
5429# else
5430 /* DCHAR_T is char. */
5431 thousep = thousands_separator_char (thousep_buf);
5432 thousep_len = strlen (thousep);
5433# endif
5434 if (*thousep == 0)
5435 thousep = NULL;
5436 if (thousep != NULL)
5437 {
5438 grouping = grouping_rule ();
5439 insert =
5440 num_thousands_separators (grouping, intpart_digits);
5441 }
5442 }
5443
5444 const char *digitp = digits + ndigits - intpart_digits;
5445 DCHAR_T *p_before_intpart = p;
5446 p += intpart_digits + insert * thousep_len;
5447 DCHAR_T *p_after_intpart = p;
5448 if (insert > 0) /* implies (flag & FLAG_GROUP) && (thousep != NULL) */
5449 {
5450 const signed char *g = grouping;
5451 for (;;)
5452 {
5453 int h = *g;
5454 if (h <= 0)
5455 abort ();
5456 int i = h;
5457 do
5458 *--p = *digitp++;
5459 while (--i > 0);
5460# if WIDE_CHAR_VERSION
5461 *--p = thousep[0];
5462# else
5463 p -= thousep_len;
5464 DCHAR_CPY (p, thousep, thousep_len);
5465# endif
5466 insert--;
5467 if (insert == 0)
5468 break;
5469 if (g[1] != 0)
5470 g++;
5471 }
5472 }
5473 for (;;)
5474 {
5475 *--p = *digitp++;
5476 if (p == p_before_intpart)
5477 break;
5478 }
5479 p = p_after_intpart;
5480 ndigits -= intpart_digits;
5481# undef thousep_len
5482
4947 if ((flags & FLAG_ALT) || ndigits > nzeroes) 5483 if ((flags & FLAG_ALT) || ndigits > nzeroes)
4948 { 5484 {
4949 *p++ = decimal_point_char (); 5485 *p++ = decimal_point_char ();
@@ -5000,9 +5536,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5000 else 5536 else
5001 { 5537 {
5002 char expbuf[6 + 1]; 5538 char expbuf[6 + 1];
5003 const char *ep;
5004 sprintf (expbuf, "%+.2d", exponent); 5539 sprintf (expbuf, "%+.2d", exponent);
5005 for (ep = expbuf; (*p = *ep) != '\0'; ep++) 5540 for (const char *ep = expbuf; (*p = *ep) != '\0'; ep++)
5006 p++; 5541 p++;
5007 } 5542 }
5008# endif 5543# endif
@@ -5102,7 +5637,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5102 else 5637 else
5103 { 5638 {
5104 int sign = 0; 5639 int sign = 0;
5105
5106 if (signbit (arg)) /* arg < 0.0 or negative zero */ 5640 if (signbit (arg)) /* arg < 0.0 or negative zero */
5107 { 5641 {
5108 sign = -1; 5642 sign = -1;
@@ -5134,22 +5668,91 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5134 5668
5135 if (dp->conversion == 'f' || dp->conversion == 'F') 5669 if (dp->conversion == 'f' || dp->conversion == 'F')
5136 { 5670 {
5137 char *digits; 5671 char *digits =
5138 size_t ndigits;
5139
5140 digits =
5141 scale10_round_decimal_double (arg, precision); 5672 scale10_round_decimal_double (arg, precision);
5142 if (digits == NULL) 5673 if (digits == NULL)
5143 goto out_of_memory; 5674 goto out_of_memory;
5144 ndigits = strlen (digits); 5675 size_t ndigits = strlen (digits);
5145 5676
5146 if (ndigits > precision) 5677 if (ndigits > precision)
5147 do 5678 {
5148 { 5679 /* Number of digits before the decimal point. */
5149 --ndigits; 5680 size_t intpart_digits = ndigits - precision;
5150 *p++ = digits[ndigits]; 5681
5151 } 5682 const DCHAR_T *thousep = NULL;
5152 while (ndigits > precision); 5683 DCHAR_T thousep_buf[10];
5684# if !WIDE_CHAR_VERSION
5685 size_t thousep_len = 0;
5686# endif
5687 const signed char *grouping;
5688 size_t insert = 0;
5689
5690 if ((flags & FLAG_GROUP) && (intpart_digits > 1))
5691 {
5692 /* Determine the thousands separator and
5693 the grouping rule of the current locale. */
5694# if WIDE_CHAR_VERSION
5695 /* DCHAR_T is wchar_t. */
5696 thousep = thousands_separator_wchar (thousep_buf);
5697# define thousep_len 1
5698# elif defined DCHAR_CONV_FROM_ENCODING
5699 /* DCHAR_T is uintN_t. */
5700 thousep = thousands_separator_DCHAR (thousep_buf);
5701 thousep_len = DCHAR_STRLEN (thousep);
5702# else
5703 /* DCHAR_T is char. */
5704 thousep = thousands_separator_char (thousep_buf);
5705 thousep_len = strlen (thousep);
5706# endif
5707 if (*thousep == 0)
5708 thousep = NULL;
5709 if (thousep != NULL)
5710 {
5711 grouping = grouping_rule ();
5712 insert =
5713 num_thousands_separators (grouping, intpart_digits);
5714 }
5715 }
5716
5717 const char *digitp = digits + precision;
5718 DCHAR_T *p_before_intpart = p;
5719 p += intpart_digits + insert * thousep_len;
5720 DCHAR_T *p_after_intpart = p;
5721 if (insert > 0) /* implies (flag & FLAG_GROUP) && (thousep != NULL) */
5722 {
5723 const signed char *g = grouping;
5724 for (;;)
5725 {
5726 int h = *g;
5727 if (h <= 0)
5728 abort ();
5729 int i = h;
5730 do
5731 *--p = *digitp++;
5732 while (--i > 0);
5733# if WIDE_CHAR_VERSION
5734 *--p = thousep[0];
5735# else
5736 p -= thousep_len;
5737 DCHAR_CPY (p, thousep, thousep_len);
5738# endif
5739 insert--;
5740 if (insert == 0)
5741 break;
5742 if (g[1] != 0)
5743 g++;
5744 }
5745 }
5746 for (;;)
5747 {
5748 *--p = *digitp++;
5749 if (p == p_before_intpart)
5750 break;
5751 }
5752 p = p_after_intpart;
5753 ndigits = precision;
5754# undef thousep_len
5755 }
5153 else 5756 else
5154 *p++ = '0'; 5757 *p++ = '0';
5155 /* Here ndigits <= precision. */ 5758 /* Here ndigits <= precision. */
@@ -5185,12 +5788,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5185 else 5788 else
5186 { 5789 {
5187 /* arg > 0.0. */ 5790 /* arg > 0.0. */
5188 int adjusted; 5791 exponent = floorlog10 (arg);
5792 int adjusted = 0;
5189 char *digits; 5793 char *digits;
5190 size_t ndigits; 5794 size_t ndigits;
5191
5192 exponent = floorlog10 (arg);
5193 adjusted = 0;
5194 for (;;) 5795 for (;;)
5195 { 5796 {
5196 digits = 5797 digits =
@@ -5292,9 +5893,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5292 else 5893 else
5293 { 5894 {
5294 char expbuf[6 + 1]; 5895 char expbuf[6 + 1];
5295 const char *ep;
5296 sprintf (expbuf, decimal_format, exponent); 5896 sprintf (expbuf, decimal_format, exponent);
5297 for (ep = expbuf; (*p = *ep) != '\0'; ep++) 5897 for (const char *ep = expbuf; (*p = *ep) != '\0'; ep++)
5298 p++; 5898 p++;
5299 } 5899 }
5300 } 5900 }
@@ -5331,14 +5931,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5331 else 5931 else
5332 { 5932 {
5333 /* arg > 0.0. */ 5933 /* arg > 0.0. */
5334 int exponent; 5934 int exponent = floorlog10 (arg);
5335 int adjusted; 5935 int adjusted = 0;
5336 char *digits; 5936 char *digits;
5337 size_t ndigits; 5937 size_t ndigits;
5338 size_t nzeroes;
5339
5340 exponent = floorlog10 (arg);
5341 adjusted = 0;
5342 for (;;) 5938 for (;;)
5343 { 5939 {
5344 digits = 5940 digits =
@@ -5394,7 +5990,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5394 5990
5395 /* Determine the number of trailing zeroes 5991 /* Determine the number of trailing zeroes
5396 that have to be dropped. */ 5992 that have to be dropped. */
5397 nzeroes = 0; 5993 size_t nzeroes = 0;
5398 if ((flags & FLAG_ALT) == 0) 5994 if ((flags & FLAG_ALT) == 0)
5399 while (nzeroes < ndigits 5995 while (nzeroes < ndigits
5400 && digits[nzeroes] == '0') 5996 && digits[nzeroes] == '0')
@@ -5410,10 +6006,84 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5410 digits without trailing zeroes. */ 6006 digits without trailing zeroes. */
5411 if (exponent >= 0) 6007 if (exponent >= 0)
5412 { 6008 {
5413 size_t ecount = exponent + 1; 6009 /* Number of digits before the decimal point. */
5414 /* Note: ecount <= precision = ndigits. */ 6010 size_t intpart_digits = exponent + 1;
5415 for (; ecount > 0; ecount--) 6011 /* Note: intpart_digits <= precision = ndigits. */
5416 *p++ = digits[--ndigits]; 6012
6013 const DCHAR_T *thousep = NULL;
6014 DCHAR_T thousep_buf[10];
6015# if !WIDE_CHAR_VERSION
6016 size_t thousep_len = 0;
6017# endif
6018 const signed char *grouping;
6019 size_t insert = 0;
6020
6021 if ((flags & FLAG_GROUP) && (intpart_digits > 1))
6022 {
6023 /* Determine the thousands separator and
6024 the grouping rule of the current locale. */
6025# if WIDE_CHAR_VERSION
6026 /* DCHAR_T is wchar_t. */
6027 thousep = thousands_separator_wchar (thousep_buf);
6028# define thousep_len 1
6029# elif defined DCHAR_CONV_FROM_ENCODING
6030 /* DCHAR_T is uintN_t. */
6031 thousep = thousands_separator_DCHAR (thousep_buf);
6032 thousep_len = DCHAR_STRLEN (thousep);
6033# else
6034 /* DCHAR_T is char. */
6035 thousep = thousands_separator_char (thousep_buf);
6036 thousep_len = strlen (thousep);
6037# endif
6038 if (*thousep == 0)
6039 thousep = NULL;
6040 if (thousep != NULL)
6041 {
6042 grouping = grouping_rule ();
6043 insert =
6044 num_thousands_separators (grouping, intpart_digits);
6045 }
6046 }
6047
6048 const char *digitp = digits + ndigits - intpart_digits;
6049 DCHAR_T *p_before_intpart = p;
6050 p += intpart_digits + insert * thousep_len;
6051 DCHAR_T *p_after_intpart = p;
6052 if (insert > 0) /* implies (flag & FLAG_GROUP) && (thousep != NULL) */
6053 {
6054 const signed char *g = grouping;
6055 for (;;)
6056 {
6057 int h = *g;
6058 if (h <= 0)
6059 abort ();
6060 int i = h;
6061 do
6062 *--p = *digitp++;
6063 while (--i > 0);
6064# if WIDE_CHAR_VERSION
6065 *--p = thousep[0];
6066# else
6067 p -= thousep_len;
6068 DCHAR_CPY (p, thousep, thousep_len);
6069# endif
6070 insert--;
6071 if (insert == 0)
6072 break;
6073 if (g[1] != 0)
6074 g++;
6075 }
6076 }
6077 for (;;)
6078 {
6079 *--p = *digitp++;
6080 if (p == p_before_intpart)
6081 break;
6082 }
6083 p = p_after_intpart;
6084 ndigits -= intpart_digits;
6085# undef thousep_len
6086
5417 if ((flags & FLAG_ALT) || ndigits > nzeroes) 6087 if ((flags & FLAG_ALT) || ndigits > nzeroes)
5418 { 6088 {
5419 *p++ = decimal_point_char (); 6089 *p++ = decimal_point_char ();
@@ -5485,9 +6155,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5485 else 6155 else
5486 { 6156 {
5487 char expbuf[6 + 1]; 6157 char expbuf[6 + 1];
5488 const char *ep;
5489 sprintf (expbuf, decimal_format, exponent); 6158 sprintf (expbuf, decimal_format, exponent);
5490 for (ep = expbuf; (*p = *ep) != '\0'; ep++) 6159 for (const char *ep = expbuf; (*p = *ep) != '\0'; ep++)
5491 p++; 6160 p++;
5492 } 6161 }
5493 } 6162 }
@@ -5557,7 +6226,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5557 6226
5558 /* The generated string now extends from tmp to p, with the 6227 /* The generated string now extends from tmp to p, with the
5559 zero padding insertion point being at pad_ptr. */ 6228 zero padding insertion point being at pad_ptr. */
5560 count = p - tmp; 6229 size_t count = p - tmp;
5561 6230
5562 if (count < width) 6231 if (count < width)
5563 { 6232 {
@@ -5606,7 +6275,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5606 { 6275 {
5607 size_t n = xsum (length, count); 6276 size_t n = xsum (length, count);
5608 6277
5609 ENSURE_ALLOCATION (n); 6278 ENSURE_ALLOCATION_ELSE (n,
6279 { if (tmp != tmpbuf) free (tmp); goto out_of_memory; });
5610 } 6280 }
5611 6281
5612 /* Append the result. */ 6282 /* Append the result. */
@@ -5620,24 +6290,19 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5620 { 6290 {
5621 arg_type type = a.arg[dp->arg_index].type; 6291 arg_type type = a.arg[dp->arg_index].type;
5622 int flags = dp->flags; 6292 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
5624 int has_width;
5625#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
5627 size_t width;
5628#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
5630 int has_precision;
5631 size_t precision;
5632#endif
5633#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION 6293#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
5634 int prec_ourselves; 6294 int prec_ourselves;
5635#else 6295#else
5636# define prec_ourselves 0 6296# define prec_ourselves 0
5637#endif 6297#endif
6298#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
6299 int group_ourselves;
6300#else
6301# define group_ourselves 0
6302#endif
5638#if (WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST 6303#if (WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST
5639# define pad_ourselves 1 6304# 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 6305#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; 6306 int pad_ourselves;
5642#else 6307#else
5643# define pad_ourselves 0 6308# define pad_ourselves 0
@@ -5652,20 +6317,18 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5652 TCHAR_T *tmp; 6317 TCHAR_T *tmp;
5653#endif 6318#endif
5654 6319
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 6320#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; 6321 int has_width = 0;
5657#endif 6322#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 6323#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; 6324 size_t width = 0;
5660 if (dp->width_start != dp->width_end) 6325 if (dp->width_start != dp->width_end)
5661 { 6326 {
5662 if (dp->width_arg_index != ARG_NONE) 6327 if (dp->width_arg_index != ARG_NONE)
5663 { 6328 {
5664 int arg;
5665
5666 if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) 6329 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
5667 abort (); 6330 abort ();
5668 arg = a.arg[dp->width_arg_index].a.a_int; 6331 int arg = a.arg[dp->width_arg_index].a.a_int;
5669 width = arg; 6332 width = arg;
5670 if (arg < 0) 6333 if (arg < 0)
5671 { 6334 {
@@ -5683,24 +6346,25 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5683 width = xsum (xtimes (width, 10), *digitp++ - '0'); 6346 width = xsum (xtimes (width, 10), *digitp++ - '0');
5684 while (digitp != dp->width_end); 6347 while (digitp != dp->width_end);
5685 } 6348 }
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 6349 if (width > (size_t) INT_MAX)
6350 goto overflow;
6351# define WIDTH_IS_CHECKED 1
6352# 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; 6353 has_width = 1;
5688# endif 6354# endif
5689 } 6355 }
5690#endif 6356#endif
5691 6357
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 6358#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; 6359 int has_precision = 0;
5694 precision = 6; 6360 size_t precision = 6;
5695 if (dp->precision_start != dp->precision_end) 6361 if (dp->precision_start != dp->precision_end)
5696 { 6362 {
5697 if (dp->precision_arg_index != ARG_NONE) 6363 if (dp->precision_arg_index != ARG_NONE)
5698 { 6364 {
5699 int arg;
5700
5701 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) 6365 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
5702 abort (); 6366 abort ();
5703 arg = a.arg[dp->precision_arg_index].a.a_int; 6367 int arg = a.arg[dp->precision_arg_index].a.a_int;
5704 /* "A negative precision is taken as if the precision 6368 /* "A negative precision is taken as if the precision
5705 were omitted." */ 6369 were omitted." */
5706 if (arg >= 0) 6370 if (arg >= 0)
@@ -5754,25 +6418,56 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5754 } 6418 }
5755#endif 6419#endif
5756 6420
6421 /* Decide whether to add the thousands separators ourselves. */
6422#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
6423 if (flags & FLAG_GROUP)
6424 {
6425 switch (dp->conversion)
6426 {
6427 case 'd': case 'i': case 'u':
6428# if NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
6429 group_ourselves = 1;
6430# else
6431 group_ourselves = prec_ourselves;
6432# endif
6433 break;
6434 case 'f': case 'F': case 'g': case 'G':
6435# if NEED_PRINTF_FLAG_GROUPING
6436 group_ourselves = 1;
6437# else
6438 group_ourselves = prec_ourselves;
6439# endif
6440 break;
6441 default:
6442 group_ourselves = 0;
6443 break;
6444 }
6445 }
6446 else
6447 group_ourselves = 0;
6448#endif
6449
5757 /* Decide whether to perform the padding ourselves. */ 6450 /* 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) 6451#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) 6452 switch (dp->conversion)
5760 { 6453 {
5761# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO 6454# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO
6455# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
5762 /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need 6456 /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
5763 to perform the padding after this conversion. Functions 6457 to perform the padding after this conversion. Functions
5764 with unistdio extensions perform the padding based on 6458 with unistdio extensions perform the padding based on
5765 character count rather than element count. */ 6459 character count rather than element count. */
5766 case 'c': case 's': 6460 case 'c': case 's':
5767# endif 6461# endif
5768# if NEED_PRINTF_FLAG_ZERO 6462# if NEED_PRINTF_FLAG_ZERO
5769 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': 6463 case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
5770 case 'a': case 'A': 6464 case 'a': case 'A':
5771# endif 6465# endif
5772 pad_ourselves = 1; 6466 pad_ourselves = 1;
5773 break; 6467 break;
6468# endif
5774 default: 6469 default:
5775 pad_ourselves = prec_ourselves; 6470 pad_ourselves = prec_ourselves | group_ourselves;
5776 break; 6471 break;
5777 } 6472 }
5778#endif 6473#endif
@@ -5805,14 +6500,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5805 sprintf. */ 6500 sprintf. */
5806 fbp = buf; 6501 fbp = buf;
5807 *fbp++ = '%'; 6502 *fbp++ = '%';
5808#if NEED_PRINTF_FLAG_GROUPING 6503 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++ = '\''; 6504 *fbp++ = '\'';
5815#endif
5816 if (flags & FLAG_LEFT) 6505 if (flags & FLAG_LEFT)
5817 *fbp++ = '-'; 6506 *fbp++ = '-';
5818 if (flags & FLAG_SHOWSIGN) 6507 if (flags & FLAG_SHOWSIGN)
@@ -5832,6 +6521,41 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5832 if (dp->width_start != dp->width_end) 6521 if (dp->width_start != dp->width_end)
5833 { 6522 {
5834 size_t n = dp->width_end - dp->width_start; 6523 size_t n = dp->width_end - dp->width_start;
6524#if !WIDTH_IS_CHECKED
6525 size_t width;
6526 /* Reject an out-of-range width.
6527 The underlying SNPRINTF already does this on some
6528 platforms (glibc, musl, macOS, FreeBSD, NetBSD,
6529 OpenBSD, Cygwin, Solaris, MSVC). However, on others
6530 (AIX, mingw), it doesn't; thus this vasnprintf
6531 invocation would succeed and produce a wrong result.
6532 So, this is redundant on some platforms, but it's a
6533 quick check anyway. */
6534 if (dp->width_arg_index != ARG_NONE)
6535 {
6536 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
6537 abort ();
6538 int arg = a.arg[dp->width_arg_index].a.a_int;
6539 width = arg;
6540 if (arg < 0)
6541 {
6542 /* "A negative field width is taken as a '-' flag
6543 followed by a positive field width." */
6544 width = -width;
6545 }
6546 }
6547 else
6548 {
6549 const FCHAR_T *digitp = dp->width_start;
6550
6551 width = 0;
6552 do
6553 width = xsum (xtimes (width, 10), *digitp++ - '0');
6554 while (digitp != dp->width_end);
6555 }
6556 if (width > (size_t) INT_MAX)
6557 goto overflow;
6558#endif
5835 /* The width specification is known to consist only 6559 /* The width specification is known to consist only
5836 of standard ASCII characters. */ 6560 of standard ASCII characters. */
5837 if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) 6561 if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
@@ -5870,7 +6594,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5870 } 6594 }
5871 } 6595 }
5872 6596
5873 switch (type) 6597 switch (+type)
5874 { 6598 {
5875 case TYPE_LONGLONGINT: 6599 case TYPE_LONGLONGINT:
5876 case TYPE_ULONGLONGINT: 6600 case TYPE_ULONGLONGINT:
@@ -5984,9 +6708,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
5984 #if HAVE_WINT_T 6708 #if HAVE_WINT_T
5985 case TYPE_WIDE_CHAR: 6709 case TYPE_WIDE_CHAR:
5986 #endif 6710 #endif
5987 #if HAVE_WCHAR_T
5988 case TYPE_WIDE_STRING: 6711 case TYPE_WIDE_STRING:
5989 #endif
5990 *fbp++ = 'l'; 6712 *fbp++ = 'l';
5991 break; 6713 break;
5992 case TYPE_LONGDOUBLE: 6714 case TYPE_LONGDOUBLE:
@@ -6038,7 +6760,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6038 /* The following platforms forbid %n: 6760 /* The following platforms forbid %n:
6039 - On glibc2 systems from 2004-10-18 or newer, the use of 6761 - On glibc2 systems from 2004-10-18 or newer, the use of
6040 %n in format strings in writable memory may crash the 6762 %n in format strings in writable memory may crash the
6041 program (if compiled with _FORTIFY_SOURCE=2). 6763 program (if compiled with _FORTIFY_SOURCE >= 2).
6042 - On macOS 10.13 or newer, the use of %n in format 6764 - On macOS 10.13 or newer, the use of %n in format
6043 strings in writable memory by default crashes the 6765 strings in writable memory by default crashes the
6044 program. 6766 program.
@@ -6071,7 +6793,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6071 on musl libc because we would run into an swprintf() bug. 6793 on musl libc because we would run into an swprintf() bug.
6072 See <https://www.openwall.com/lists/musl/2023/03/19/1>. */ 6794 See <https://www.openwall.com/lists/musl/2023/03/19/1>. */
6073 fbp[1] = '\0'; 6795 fbp[1] = '\0';
6074# else /* AIX <= 5.1, HP-UX, IRIX, OSF/1, Solaris <= 9, BeOS */ 6796# else /* AIX <= 5.1, HP-UX, Solaris <= 9, BeOS */
6075 fbp[1] = '%'; 6797 fbp[1] = '%';
6076 fbp[2] = 'n'; 6798 fbp[2] = 'n';
6077 fbp[3] = '\0'; 6799 fbp[3] = '\0';
@@ -6168,7 +6890,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6168#endif 6890#endif
6169 6891
6170 errno = 0; 6892 errno = 0;
6171 switch (type) 6893 switch (+type)
6172 { 6894 {
6173 case TYPE_SCHAR: 6895 case TYPE_SCHAR:
6174 { 6896 {
@@ -6358,14 +7080,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6358 SNPRINTF_BUF (arg); 7080 SNPRINTF_BUF (arg);
6359 } 7081 }
6360 break; 7082 break;
6361#if HAVE_WCHAR_T
6362 case TYPE_WIDE_STRING: 7083 case TYPE_WIDE_STRING:
6363 { 7084 {
6364 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; 7085 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
6365 SNPRINTF_BUF (arg); 7086 SNPRINTF_BUF (arg);
6366 } 7087 }
6367 break; 7088 break;
6368#endif
6369 case TYPE_POINTER: 7089 case TYPE_POINTER:
6370 { 7090 {
6371 void *arg = a.arg[dp->arg_index].a.a_pointer; 7091 void *arg = a.arg[dp->arg_index].a.a_pointer;
@@ -6539,10 +7259,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6539 || *prec_ptr == ' ')) 7259 || *prec_ptr == ' '))
6540 prefix_count = 1; 7260 prefix_count = 1;
6541 /* Put the additional zeroes after the 0x prefix if 7261 /* Put the additional zeroes after the 0x prefix if
6542 (flags & FLAG_ALT) || (dp->conversion == 'p'). */ 7262 (flags & FLAG_ALT) || (dp->conversion == 'p'), or
7263 after the 0b prefix if (flags & FLAG_ALT). */
6543 else if (count >= 2 7264 else if (count >= 2
6544 && prec_ptr[0] == '0' 7265 && prec_ptr[0] == '0'
6545 && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X')) 7266 && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'
7267 || prec_ptr[1] == 'b'
7268 || prec_ptr[1] == 'B'))
6546 prefix_count = 2; 7269 prefix_count = 2;
6547 7270
6548 move = count - prefix_count; 7271 move = count - prefix_count;
@@ -6591,6 +7314,135 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6591 } 7314 }
6592#endif 7315#endif
6593 7316
7317#if NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION || NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT
7318 if (group_ourselves) /* implies (flags & FLAG_GROUP) */
7319 /* Handle the grouping. */
7320 switch (dp->conversion)
7321 {
7322 /* These are the only conversion to which grouping
7323 applies. */
7324 case 'd': case 'i': case 'u':
7325 case 'f': case 'F': case 'g': case 'G':
7326 {
7327 /* Determine the thousands separator of the current
7328 locale. */
7329 const TCHAR_T *thousep;
7330 TCHAR_T thousep_buf[10];
7331
7332# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
7333 /* TCHAR_T is wchar_t. */
7334 thousep = thousands_separator_wchar (thousep_buf);
7335# else
7336 /* TCHAR_T is char. */
7337 thousep = thousands_separator_char (thousep_buf);
7338# endif
7339
7340 /* Nothing to do in locales where thousep is the empty
7341 string. */
7342 if (*thousep != 0)
7343 {
7344 /* Since FLAG_LOCALIZED is only supported on glibc
7345 systems, here we can assume that all digits are
7346 the ASCII digits '0'..'9'. */
7347 TCHAR_T *number_ptr =
7348# if USE_SNPRINTF
7349 (TCHAR_T *) (result + length);
7350# else
7351 tmp;
7352# endif
7353 TCHAR_T *end_ptr = number_ptr + count;
7354
7355 /* Find where the leading digits start. */
7356 TCHAR_T *digits_ptr = number_ptr;
7357 if (count >= 1
7358 && (*digits_ptr == '-' || *digits_ptr == '+'
7359 || *digits_ptr == ' '))
7360 digits_ptr++;
7361
7362 /* Find where the leading digits end. */
7363 TCHAR_T *digits_end_ptr;
7364 switch (dp->conversion)
7365 {
7366 case 'd': case 'i': case 'u':
7367 digits_end_ptr = end_ptr;
7368 break;
7369 case 'f': case 'F': case 'g': case 'G':
7370 {
7371 TCHAR_T decimal_point = decimal_point_char ();
7372 for (digits_end_ptr = digits_ptr;
7373 digits_end_ptr < end_ptr;
7374 digits_end_ptr++)
7375 if (*digits_end_ptr == decimal_point
7376 || *digits_end_ptr == 'e')
7377 break;
7378 }
7379 break;
7380 }
7381
7382 /* Determine the number of thousands separators
7383 to insert. */
7384 const signed char *grouping = grouping_rule ();
7385 size_t insert =
7386 num_thousands_separators (grouping, digits_end_ptr - digits_ptr);
7387 if (insert > 0)
7388 {
7389# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
7390# define thousep_len 1
7391# else
7392 size_t thousep_len = strlen (thousep);
7393# endif
7394# if USE_SNPRINTF
7395 size_t digits_offset = digits_ptr - number_ptr;
7396 size_t digits_end_offset = digits_end_ptr - number_ptr;
7397 size_t n =
7398 xsum (length,
7399 (count + insert * thousep_len + TCHARS_PER_DCHAR - 1)
7400 / TCHARS_PER_DCHAR);
7401 length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
7402 ENSURE_ALLOCATION (n);
7403 length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
7404 number_ptr = (TCHAR_T *) (result + length);
7405 end_ptr = number_ptr + count;
7406 digits_ptr = number_ptr + digits_offset;
7407 digits_end_ptr = number_ptr + digits_end_offset;
7408# endif
7409
7410 count += insert * thousep_len;
7411
7412 const TCHAR_T *p = end_ptr;
7413 TCHAR_T *q = end_ptr + insert * thousep_len;
7414 while (p > digits_end_ptr)
7415 *--q = *--p;
7416 const signed char *g = grouping;
7417 for (;;)
7418 {
7419 int h = *g;
7420 if (h <= 0)
7421 abort ();
7422 int i = h;
7423 do
7424 *--q = *--p;
7425 while (--i > 0);
7426# if WIDE_CHAR_VERSION && DCHAR_IS_TCHAR
7427 *--q = *thousep;
7428# else
7429 q -= thousep_len;
7430 memcpy (q, thousep, thousep_len);
7431# endif
7432 insert--;
7433 if (insert == 0)
7434 break;
7435 if (g[1] != 0)
7436 g++;
7437 }
7438 /* Here q == p. Done with the insertions. */
7439 }
7440 }
7441 }
7442 break;
7443 }
7444#endif
7445
6594#if !USE_SNPRINTF 7446#if !USE_SNPRINTF
6595 if (count >= tmp_length) 7447 if (count >= tmp_length)
6596 /* tmp_length was incorrectly calculated - fix the 7448 /* tmp_length was incorrectly calculated - fix the
@@ -6601,22 +7453,23 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6601#if !DCHAR_IS_TCHAR 7453#if !DCHAR_IS_TCHAR
6602 /* Convert from TCHAR_T[] to DCHAR_T[]. */ 7454 /* Convert from TCHAR_T[] to DCHAR_T[]. */
6603 if (dp->conversion == 'c' || dp->conversion == 's' 7455 if (dp->conversion == 'c' || dp->conversion == 's'
7456 || (flags & FLAG_GROUP)
6604# if __GLIBC__ >= 2 && !defined __UCLIBC__ 7457# if __GLIBC__ >= 2 && !defined __UCLIBC__
6605 || (flags & FLAG_LOCALIZED) 7458 || (flags & FLAG_LOCALIZED)
6606# endif 7459# endif
6607 ) 7460 )
6608 { 7461 {
6609 /* The result string is not guaranteed to be ASCII. */ 7462 /* The result string is not guaranteed to be ASCII. */
6610 const TCHAR_T *tmpsrc;
6611 DCHAR_T *tmpdst;
6612 size_t tmpdst_len;
6613 /* This code assumes that TCHAR_T is 'char'. */ 7463 /* This code assumes that TCHAR_T is 'char'. */
6614 static_assert (sizeof (TCHAR_T) == 1); 7464 static_assert (sizeof (TCHAR_T) == 1);
7465 const TCHAR_T *tmpsrc;
6615# if USE_SNPRINTF 7466# if USE_SNPRINTF
6616 tmpsrc = (TCHAR_T *) (result + length); 7467 tmpsrc = (TCHAR_T *) (result + length);
6617# else 7468# else
6618 tmpsrc = tmp; 7469 tmpsrc = tmp;
6619# endif 7470# endif
7471 DCHAR_T *tmpdst;
7472 size_t tmpdst_len;
6620# if WIDE_CHAR_VERSION 7473# if WIDE_CHAR_VERSION
6621 /* Convert tmpsrc[0..count-1] to a freshly allocated 7474 /* Convert tmpsrc[0..count-1] to a freshly allocated
6622 wide character array. */ 7475 wide character array. */
@@ -6677,7 +7530,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6677 goto fail_with_errno; 7530 goto fail_with_errno;
6678# endif 7531# endif
6679 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len), 7532 ENSURE_ALLOCATION_ELSE (xsum (length, tmpdst_len),
6680 { free (tmpdst); goto out_of_memory; }); 7533 { free (tmpdst); goto out_of_memory; });
6681 DCHAR_CPY (result + length, tmpdst, tmpdst_len); 7534 DCHAR_CPY (result + length, tmpdst, tmpdst_len);
6682 free (tmpdst); 7535 free (tmpdst);
6683 count = tmpdst_len; 7536 count = tmpdst_len;
@@ -6694,9 +7547,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6694# endif 7547# endif
6695 { 7548 {
6696 const TCHAR_T *tmpsrc; 7549 const TCHAR_T *tmpsrc;
6697 DCHAR_T *tmpdst;
6698 size_t n;
6699
6700# if USE_SNPRINTF 7550# if USE_SNPRINTF
6701 if (result == resultbuf) 7551 if (result == resultbuf)
6702 { 7552 {
@@ -6716,11 +7566,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6716 tmpsrc = tmp; 7566 tmpsrc = tmp;
6717 ENSURE_ALLOCATION (xsum (length, count)); 7567 ENSURE_ALLOCATION (xsum (length, count));
6718# endif 7568# endif
6719 tmpdst = result + length; 7569 DCHAR_T *tmpdst = result + length;
6720 /* Copy backwards, because of overlapping. */ 7570 /* Copy backwards, because of overlapping. */
6721 tmpsrc += count; 7571 tmpsrc += count;
6722 tmpdst += count; 7572 tmpdst += count;
6723 for (n = count; n > 0; n--) 7573 for (size_t n = count; n > 0; n--)
6724 *--tmpdst = *--tmpsrc; 7574 *--tmpdst = *--tmpsrc;
6725 } 7575 }
6726 } 7576 }
@@ -6742,7 +7592,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6742 /* Here count <= allocated - length. */ 7592 /* Here count <= allocated - length. */
6743 7593
6744 /* Perform padding. */ 7594 /* 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 7595#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) 7596 if (pad_ourselves && has_width)
6747 { 7597 {
6748 size_t w; 7598 size_t w;
@@ -6751,6 +7601,23 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6751 against the number of _characters_ of the converted 7601 against the number of _characters_ of the converted
6752 value. */ 7602 value. */
6753 w = DCHAR_MBSNLEN (result + length, count); 7603 w = DCHAR_MBSNLEN (result + length, count);
7604# elif __GLIBC__ >= 2
7605 /* glibc prefers to compare the width against the number
7606 of characters as well, but only for numeric conversion
7607 specifiers. See
7608 <https://sourceware.org/PR28943>
7609 <https://sourceware.org/PR30883>
7610 <https://sourceware.org/PR31542> */
7611 switch (dp->conversion)
7612 {
7613 case 'd': case 'i': case 'u':
7614 case 'f': case 'F': case 'g': case 'G':
7615 w = DCHAR_MBSNLEN (result + length, count);
7616 break;
7617 default:
7618 w = count;
7619 break;
7620 }
6754# else 7621# else
6755 /* The width is compared against the number of _bytes_ 7622 /* The width is compared against the number of _bytes_
6756 of the converted value, says POSIX. */ 7623 of the converted value, says POSIX. */
@@ -6888,8 +7755,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6888 { 7755 {
6889 /* Convert the %f result to upper case for %F. */ 7756 /* Convert the %f result to upper case for %F. */
6890 DCHAR_T *rp = result + length; 7757 DCHAR_T *rp = result + length;
6891 size_t rc; 7758 for (size_t rc = count; rc > 0; rc--, rp++)
6892 for (rc = count; rc > 0; rc--, rp++)
6893 if (*rp >= 'a' && *rp <= 'z') 7759 if (*rp >= 'a' && *rp <= 'z')
6894 *rp = *rp - 'a' + 'A'; 7760 *rp = *rp - 'a' + 'A';
6895 } 7761 }
@@ -6912,9 +7778,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6912 if (result != resultbuf && length + 1 < allocated) 7778 if (result != resultbuf && length + 1 < allocated)
6913 { 7779 {
6914 /* Shrink the allocated memory if possible. */ 7780 /* Shrink the allocated memory if possible. */
6915 DCHAR_T *memory; 7781 DCHAR_T *memory =
6916 7782 (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
6917 memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
6918 if (memory != NULL) 7783 if (memory != NULL)
6919 result = memory; 7784 result = memory;
6920 } 7785 }
@@ -6929,17 +7794,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
6929 not have this limitation. */ 7794 not have this limitation. */
6930 return result; 7795 return result;
6931 7796
6932#if USE_SNPRINTF
6933 overflow: 7797 overflow:
6934 errno = EOVERFLOW; 7798 errno = EOVERFLOW;
6935 goto fail_with_errno; 7799 goto fail_with_errno;
6936#endif
6937 7800
6938 out_of_memory: 7801 out_of_memory:
6939 errno = ENOMEM; 7802 errno = ENOMEM;
6940 goto fail_with_errno; 7803 goto fail_with_errno;
6941 7804
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) 7805#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: 7806 fail_with_EILSEQ:
6944 errno = EILSEQ; 7807 errno = EILSEQ;
6945 goto fail_with_errno; 7808 goto fail_with_errno;