diff options
Diffstat (limited to 'gl/vasnprintf.c')
| -rw-r--r-- | gl/vasnprintf.c | 2019 |
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 |
| 294 | static size_t | 321 | static size_t |
| 295 | wctomb_fallback (char *s, wchar_t wc) | 322 | wctomb_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 | ||
| 422 | static const char * | ||
| 423 | thousands_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 | ||
| 456 | static const DCHAR_T * | ||
| 457 | thousands_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 | ||
| 495 | static const wchar_t * | ||
| 496 | thousands_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 | */ | ||
| 579 | static const signed char * | ||
| 580 | grouping_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). */ | ||
| 596 | static size_t | ||
| 597 | num_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 | |||
| 654 | static | ||
| 655 | long 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. */ |
| 433 | static void * | 708 | static void * |
| 434 | multiply (mpn_t src1, mpn_t src2, mpn_t *dest) | 709 | multiply (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. */ |
| 505 | static void * | 779 | static void * |
| 506 | divide (mpn_t a, mpn_t b, mpn_t *q) | 780 | divide (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) | |||
| 1004 | static void * | 1266 | static void * |
| 1005 | decode_long_double (long double x, int *ep, mpn_t *mp) | 1267 | decode_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) | |||
| 1092 | static void * | 1351 | static void * |
| 1093 | decode_double (double x, int *ep, mpn_t *mp) | 1352 | decode_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) | |||
| 1176 | static char * | 1432 | static char * |
| 1177 | scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n) | 1433 | scale10_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) | |||
| 1436 | static int | 1673 | static int |
| 1437 | floorlog10l (long double x) | 1674 | floorlog10l (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) | |||
| 1527 | static int | 1760 | static int |
| 1528 | floorlog10 (double x) | 1761 | floorlog10 (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; |
