diff options
Diffstat (limited to 'gl/vasnprintf.c')
| -rw-r--r-- | gl/vasnprintf.c | 601 |
1 files changed, 340 insertions, 261 deletions
diff --git a/gl/vasnprintf.c b/gl/vasnprintf.c index 99d921e9..e618901b 100644 --- a/gl/vasnprintf.c +++ b/gl/vasnprintf.c | |||
| @@ -148,8 +148,14 @@ | |||
| 148 | # define USE_SNPRINTF 1 | 148 | # define USE_SNPRINTF 1 |
| 149 | # if HAVE_DECL__SNWPRINTF | 149 | # if HAVE_DECL__SNWPRINTF |
| 150 | /* On Windows, the function swprintf() has a different signature than | 150 | /* On Windows, the function swprintf() has a different signature than |
| 151 | on Unix; we use the _snwprintf() function instead. */ | 151 | on Unix; we use the function _snwprintf() or - on mingw - snwprintf() |
| 152 | # define SNPRINTF _snwprintf | 152 | instead. The mingw function snwprintf() has fewer bugs than the |
| 153 | MSVCRT function _snwprintf(), so prefer that. */ | ||
| 154 | # if defined __MINGW32__ | ||
| 155 | # define SNPRINTF snwprintf | ||
| 156 | # else | ||
| 157 | # define SNPRINTF _snwprintf | ||
| 158 | # endif | ||
| 153 | # else | 159 | # else |
| 154 | /* Unix. */ | 160 | /* Unix. */ |
| 155 | # define SNPRINTF swprintf | 161 | # define SNPRINTF swprintf |
| @@ -167,8 +173,15 @@ | |||
| 167 | # define USE_SNPRINTF 0 | 173 | # define USE_SNPRINTF 0 |
| 168 | # endif | 174 | # endif |
| 169 | # if HAVE_DECL__SNPRINTF | 175 | # if HAVE_DECL__SNPRINTF |
| 170 | /* Windows. */ | 176 | /* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT |
| 171 | # define SNPRINTF _snprintf | 177 | function _snprintf(), so prefer that. */ |
| 178 | # if defined __MINGW32__ | ||
| 179 | # define SNPRINTF snprintf | ||
| 180 | /* Here we need to call the native snprintf, not rpl_snprintf. */ | ||
| 181 | # undef snprintf | ||
| 182 | # else | ||
| 183 | # define SNPRINTF _snprintf | ||
| 184 | # endif | ||
| 172 | # else | 185 | # else |
| 173 | /* Unix. */ | 186 | /* Unix. */ |
| 174 | # define SNPRINTF snprintf | 187 | # define SNPRINTF snprintf |
| @@ -194,7 +207,7 @@ | |||
| 194 | #undef remainder | 207 | #undef remainder |
| 195 | #define remainder rem | 208 | #define remainder rem |
| 196 | 209 | ||
| 197 | #if !USE_SNPRINTF && !WIDE_CHAR_VERSION | 210 | #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION |
| 198 | # if (HAVE_STRNLEN && !defined _AIX) | 211 | # if (HAVE_STRNLEN && !defined _AIX) |
| 199 | # define local_strnlen strnlen | 212 | # define local_strnlen strnlen |
| 200 | # else | 213 | # else |
| @@ -210,7 +223,7 @@ local_strnlen (const char *string, size_t maxlen) | |||
| 210 | # endif | 223 | # endif |
| 211 | #endif | 224 | #endif |
| 212 | 225 | ||
| 213 | #if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T && (WIDE_CHAR_VERSION || DCHAR_IS_TCHAR) | 226 | #if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T |
| 214 | # if HAVE_WCSLEN | 227 | # if HAVE_WCSLEN |
| 215 | # define local_wcslen wcslen | 228 | # define local_wcslen wcslen |
| 216 | # else | 229 | # else |
| @@ -233,7 +246,7 @@ local_wcslen (const wchar_t *s) | |||
| 233 | # endif | 246 | # endif |
| 234 | #endif | 247 | #endif |
| 235 | 248 | ||
| 236 | #if !USE_SNPRINTF && HAVE_WCHAR_T && WIDE_CHAR_VERSION | 249 | #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION |
| 237 | # if HAVE_WCSNLEN | 250 | # if HAVE_WCSNLEN |
| 238 | # define local_wcsnlen wcsnlen | 251 | # define local_wcsnlen wcsnlen |
| 239 | # else | 252 | # else |
| @@ -1474,6 +1487,258 @@ is_borderline (const char *digits, size_t precision) | |||
| 1474 | 1487 | ||
| 1475 | #endif | 1488 | #endif |
| 1476 | 1489 | ||
| 1490 | #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 | ||
| 1491 | |||
| 1492 | /* Use a different function name, to make it possible that the 'wchar_t' | ||
| 1493 | parametrization and the 'char' parametrization get compiled in the same | ||
| 1494 | translation unit. */ | ||
| 1495 | # if WIDE_CHAR_VERSION | ||
| 1496 | # define MAX_ROOM_NEEDED wmax_room_needed | ||
| 1497 | # else | ||
| 1498 | # define MAX_ROOM_NEEDED max_room_needed | ||
| 1499 | # endif | ||
| 1500 | |||
| 1501 | /* Returns the number of TCHAR_T units needed as temporary space for the result | ||
| 1502 | of sprintf or SNPRINTF of a single conversion directive. */ | ||
| 1503 | static inline size_t | ||
| 1504 | MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion, | ||
| 1505 | arg_type type, int flags, size_t width, int has_precision, | ||
| 1506 | size_t precision, int pad_ourselves) | ||
| 1507 | { | ||
| 1508 | size_t tmp_length; | ||
| 1509 | |||
| 1510 | switch (conversion) | ||
| 1511 | { | ||
| 1512 | case 'd': case 'i': case 'u': | ||
| 1513 | # if HAVE_LONG_LONG_INT | ||
| 1514 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | ||
| 1515 | tmp_length = | ||
| 1516 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT | ||
| 1517 | * 0.30103 /* binary -> decimal */ | ||
| 1518 | ) | ||
| 1519 | + 1; /* turn floor into ceil */ | ||
| 1520 | else | ||
| 1521 | # endif | ||
| 1522 | if (type == TYPE_LONGINT || type == TYPE_ULONGINT) | ||
| 1523 | tmp_length = | ||
| 1524 | (unsigned int) (sizeof (unsigned long) * CHAR_BIT | ||
| 1525 | * 0.30103 /* binary -> decimal */ | ||
| 1526 | ) | ||
| 1527 | + 1; /* turn floor into ceil */ | ||
| 1528 | else | ||
| 1529 | tmp_length = | ||
| 1530 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT | ||
| 1531 | * 0.30103 /* binary -> decimal */ | ||
| 1532 | ) | ||
| 1533 | + 1; /* turn floor into ceil */ | ||
| 1534 | if (tmp_length < precision) | ||
| 1535 | tmp_length = precision; | ||
| 1536 | /* Multiply by 2, as an estimate for FLAG_GROUP. */ | ||
| 1537 | tmp_length = xsum (tmp_length, tmp_length); | ||
| 1538 | /* Add 1, to account for a leading sign. */ | ||
| 1539 | tmp_length = xsum (tmp_length, 1); | ||
| 1540 | break; | ||
| 1541 | |||
| 1542 | case 'o': | ||
| 1543 | # if HAVE_LONG_LONG_INT | ||
| 1544 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | ||
| 1545 | tmp_length = | ||
| 1546 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT | ||
| 1547 | * 0.333334 /* binary -> octal */ | ||
| 1548 | ) | ||
| 1549 | + 1; /* turn floor into ceil */ | ||
| 1550 | else | ||
| 1551 | # endif | ||
| 1552 | if (type == TYPE_LONGINT || type == TYPE_ULONGINT) | ||
| 1553 | tmp_length = | ||
| 1554 | (unsigned int) (sizeof (unsigned long) * CHAR_BIT | ||
| 1555 | * 0.333334 /* binary -> octal */ | ||
| 1556 | ) | ||
| 1557 | + 1; /* turn floor into ceil */ | ||
| 1558 | else | ||
| 1559 | tmp_length = | ||
| 1560 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT | ||
| 1561 | * 0.333334 /* binary -> octal */ | ||
| 1562 | ) | ||
| 1563 | + 1; /* turn floor into ceil */ | ||
| 1564 | if (tmp_length < precision) | ||
| 1565 | tmp_length = precision; | ||
| 1566 | /* Add 1, to account for a leading sign. */ | ||
| 1567 | tmp_length = xsum (tmp_length, 1); | ||
| 1568 | break; | ||
| 1569 | |||
| 1570 | case 'x': case 'X': | ||
| 1571 | # if HAVE_LONG_LONG_INT | ||
| 1572 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | ||
| 1573 | tmp_length = | ||
| 1574 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT | ||
| 1575 | * 0.25 /* binary -> hexadecimal */ | ||
| 1576 | ) | ||
| 1577 | + 1; /* turn floor into ceil */ | ||
| 1578 | else | ||
| 1579 | # endif | ||
| 1580 | if (type == TYPE_LONGINT || type == TYPE_ULONGINT) | ||
| 1581 | tmp_length = | ||
| 1582 | (unsigned int) (sizeof (unsigned long) * CHAR_BIT | ||
| 1583 | * 0.25 /* binary -> hexadecimal */ | ||
| 1584 | ) | ||
| 1585 | + 1; /* turn floor into ceil */ | ||
| 1586 | else | ||
| 1587 | tmp_length = | ||
| 1588 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT | ||
| 1589 | * 0.25 /* binary -> hexadecimal */ | ||
| 1590 | ) | ||
| 1591 | + 1; /* turn floor into ceil */ | ||
| 1592 | if (tmp_length < precision) | ||
| 1593 | tmp_length = precision; | ||
| 1594 | /* Add 2, to account for a leading sign or alternate form. */ | ||
| 1595 | tmp_length = xsum (tmp_length, 2); | ||
| 1596 | break; | ||
| 1597 | |||
| 1598 | case 'f': case 'F': | ||
| 1599 | if (type == TYPE_LONGDOUBLE) | ||
| 1600 | tmp_length = | ||
| 1601 | (unsigned int) (LDBL_MAX_EXP | ||
| 1602 | * 0.30103 /* binary -> decimal */ | ||
| 1603 | * 2 /* estimate for FLAG_GROUP */ | ||
| 1604 | ) | ||
| 1605 | + 1 /* turn floor into ceil */ | ||
| 1606 | + 10; /* sign, decimal point etc. */ | ||
| 1607 | else | ||
| 1608 | tmp_length = | ||
| 1609 | (unsigned int) (DBL_MAX_EXP | ||
| 1610 | * 0.30103 /* binary -> decimal */ | ||
| 1611 | * 2 /* estimate for FLAG_GROUP */ | ||
| 1612 | ) | ||
| 1613 | + 1 /* turn floor into ceil */ | ||
| 1614 | + 10; /* sign, decimal point etc. */ | ||
| 1615 | tmp_length = xsum (tmp_length, precision); | ||
| 1616 | break; | ||
| 1617 | |||
| 1618 | case 'e': case 'E': case 'g': case 'G': | ||
| 1619 | tmp_length = | ||
| 1620 | 12; /* sign, decimal point, exponent etc. */ | ||
| 1621 | tmp_length = xsum (tmp_length, precision); | ||
| 1622 | break; | ||
| 1623 | |||
| 1624 | case 'a': case 'A': | ||
| 1625 | if (type == TYPE_LONGDOUBLE) | ||
| 1626 | tmp_length = | ||
| 1627 | (unsigned int) (LDBL_DIG | ||
| 1628 | * 0.831 /* decimal -> hexadecimal */ | ||
| 1629 | ) | ||
| 1630 | + 1; /* turn floor into ceil */ | ||
| 1631 | else | ||
| 1632 | tmp_length = | ||
| 1633 | (unsigned int) (DBL_DIG | ||
| 1634 | * 0.831 /* decimal -> hexadecimal */ | ||
| 1635 | ) | ||
| 1636 | + 1; /* turn floor into ceil */ | ||
| 1637 | if (tmp_length < precision) | ||
| 1638 | tmp_length = precision; | ||
| 1639 | /* Account for sign, decimal point etc. */ | ||
| 1640 | tmp_length = xsum (tmp_length, 12); | ||
| 1641 | break; | ||
| 1642 | |||
| 1643 | case 'c': | ||
| 1644 | # if HAVE_WINT_T && !WIDE_CHAR_VERSION | ||
| 1645 | if (type == TYPE_WIDE_CHAR) | ||
| 1646 | tmp_length = MB_CUR_MAX; | ||
| 1647 | else | ||
| 1648 | # endif | ||
| 1649 | tmp_length = 1; | ||
| 1650 | break; | ||
| 1651 | |||
| 1652 | case 's': | ||
| 1653 | # if HAVE_WCHAR_T | ||
| 1654 | if (type == TYPE_WIDE_STRING) | ||
| 1655 | { | ||
| 1656 | # if WIDE_CHAR_VERSION | ||
| 1657 | /* ISO C says about %ls in fwprintf: | ||
| 1658 | "If the precision is not specified or is greater than the size | ||
| 1659 | of the array, the array shall contain a null wide character." | ||
| 1660 | So if there is a precision, we must not use wcslen. */ | ||
| 1661 | const wchar_t *arg = ap->arg[arg_index].a.a_wide_string; | ||
| 1662 | |||
| 1663 | if (has_precision) | ||
| 1664 | tmp_length = local_wcsnlen (arg, precision); | ||
| 1665 | else | ||
| 1666 | tmp_length = local_wcslen (arg); | ||
| 1667 | # else | ||
| 1668 | /* ISO C says about %ls in fprintf: | ||
| 1669 | "If a precision is specified, no more than that many bytes are | ||
| 1670 | written (including shift sequences, if any), and the array | ||
| 1671 | shall contain a null wide character if, to equal the multibyte | ||
| 1672 | character sequence length given by the precision, the function | ||
| 1673 | would need to access a wide character one past the end of the | ||
| 1674 | array." | ||
| 1675 | So if there is a precision, we must not use wcslen. */ | ||
| 1676 | /* This case has already been handled separately in VASNPRINTF. */ | ||
| 1677 | abort (); | ||
| 1678 | # endif | ||
| 1679 | } | ||
| 1680 | else | ||
| 1681 | # endif | ||
| 1682 | { | ||
| 1683 | # if WIDE_CHAR_VERSION | ||
| 1684 | /* ISO C says about %s in fwprintf: | ||
| 1685 | "If the precision is not specified or is greater than the size | ||
| 1686 | of the converted array, the converted array shall contain a | ||
| 1687 | null wide character." | ||
| 1688 | So if there is a precision, we must not use strlen. */ | ||
| 1689 | /* This case has already been handled separately in VASNPRINTF. */ | ||
| 1690 | abort (); | ||
| 1691 | # else | ||
| 1692 | /* ISO C says about %s in fprintf: | ||
| 1693 | "If the precision is not specified or greater than the size of | ||
| 1694 | the array, the array shall contain a null character." | ||
| 1695 | So if there is a precision, we must not use strlen. */ | ||
| 1696 | const char *arg = ap->arg[arg_index].a.a_string; | ||
| 1697 | |||
| 1698 | if (has_precision) | ||
| 1699 | tmp_length = local_strnlen (arg, precision); | ||
| 1700 | else | ||
| 1701 | tmp_length = strlen (arg); | ||
| 1702 | # endif | ||
| 1703 | } | ||
| 1704 | break; | ||
| 1705 | |||
| 1706 | case 'p': | ||
| 1707 | tmp_length = | ||
| 1708 | (unsigned int) (sizeof (void *) * CHAR_BIT | ||
| 1709 | * 0.25 /* binary -> hexadecimal */ | ||
| 1710 | ) | ||
| 1711 | + 1 /* turn floor into ceil */ | ||
| 1712 | + 2; /* account for leading 0x */ | ||
| 1713 | break; | ||
| 1714 | |||
| 1715 | default: | ||
| 1716 | abort (); | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | if (!pad_ourselves) | ||
| 1720 | { | ||
| 1721 | # if ENABLE_UNISTDIO | ||
| 1722 | /* Padding considers the number of characters, therefore the number of | ||
| 1723 | elements after padding may be | ||
| 1724 | > max (tmp_length, width) | ||
| 1725 | but is certainly | ||
| 1726 | <= tmp_length + width. */ | ||
| 1727 | tmp_length = xsum (tmp_length, width); | ||
| 1728 | # else | ||
| 1729 | /* Padding considers the number of elements, says POSIX. */ | ||
| 1730 | if (tmp_length < width) | ||
| 1731 | tmp_length = width; | ||
| 1732 | # endif | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ | ||
| 1736 | |||
| 1737 | return tmp_length; | ||
| 1738 | } | ||
| 1739 | |||
| 1740 | #endif | ||
| 1741 | |||
| 1477 | DCHAR_T * | 1742 | DCHAR_T * |
| 1478 | VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | 1743 | VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, |
| 1479 | const FCHAR_T *format, va_list args) | 1744 | const FCHAR_T *format, va_list args) |
| @@ -2103,7 +2368,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 2103 | } | 2368 | } |
| 2104 | } | 2369 | } |
| 2105 | #endif | 2370 | #endif |
| 2106 | #if (!USE_SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T | 2371 | #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T |
| 2107 | else if (dp->conversion == 's' | 2372 | else if (dp->conversion == 's' |
| 2108 | # if WIDE_CHAR_VERSION | 2373 | # if WIDE_CHAR_VERSION |
| 2109 | && a.arg[dp->arg_index].type != TYPE_WIDE_STRING | 2374 | && a.arg[dp->arg_index].type != TYPE_WIDE_STRING |
| @@ -2592,8 +2857,16 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 2592 | count = wctomb (cbuf, *arg); | 2857 | count = wctomb (cbuf, *arg); |
| 2593 | # endif | 2858 | # endif |
| 2594 | if (count <= 0) | 2859 | if (count <= 0) |
| 2595 | /* Inconsistency. */ | 2860 | { |
| 2596 | abort (); | 2861 | /* Cannot convert. */ |
| 2862 | if (!(result == resultbuf || result == NULL)) | ||
| 2863 | free (result); | ||
| 2864 | if (buf_malloced != NULL) | ||
| 2865 | free (buf_malloced); | ||
| 2866 | CLEANUP (); | ||
| 2867 | errno = EILSEQ; | ||
| 2868 | return NULL; | ||
| 2869 | } | ||
| 2597 | ENSURE_ALLOCATION (xsum (length, count)); | 2870 | ENSURE_ALLOCATION (xsum (length, count)); |
| 2598 | memcpy (result + length, cbuf, count); | 2871 | memcpy (result + length, cbuf, count); |
| 2599 | length += count; | 2872 | length += count; |
| @@ -2616,8 +2889,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 2616 | length += n; | 2889 | length += n; |
| 2617 | } | 2890 | } |
| 2618 | } | 2891 | } |
| 2619 | } | ||
| 2620 | # endif | 2892 | # endif |
| 2893 | } | ||
| 2621 | #endif | 2894 | #endif |
| 2622 | #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL | 2895 | #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL |
| 2623 | else if ((dp->conversion == 'a' || dp->conversion == 'A') | 2896 | else if ((dp->conversion == 'a' || dp->conversion == 'A') |
| @@ -4301,11 +4574,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 4301 | { | 4574 | { |
| 4302 | arg_type type = a.arg[dp->arg_index].type; | 4575 | arg_type type = a.arg[dp->arg_index].type; |
| 4303 | int flags = dp->flags; | 4576 | int flags = dp->flags; |
| 4304 | #if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION | 4577 | #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION |
| 4305 | int has_width; | 4578 | int has_width; |
| 4306 | size_t width; | 4579 | size_t width; |
| 4307 | #endif | 4580 | #endif |
| 4308 | #if !USE_SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION | 4581 | #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION |
| 4309 | int has_precision; | 4582 | int has_precision; |
| 4310 | size_t precision; | 4583 | size_t precision; |
| 4311 | #endif | 4584 | #endif |
| @@ -4330,7 +4603,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 4330 | TCHAR_T *tmp; | 4603 | TCHAR_T *tmp; |
| 4331 | #endif | 4604 | #endif |
| 4332 | 4605 | ||
| 4333 | #if !USE_SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION | 4606 | #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION |
| 4334 | has_width = 0; | 4607 | has_width = 0; |
| 4335 | width = 0; | 4608 | width = 0; |
| 4336 | if (dp->width_start != dp->width_end) | 4609 | if (dp->width_start != dp->width_end) |
| @@ -4364,7 +4637,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 4364 | } | 4637 | } |
| 4365 | #endif | 4638 | #endif |
| 4366 | 4639 | ||
| 4367 | #if !USE_SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION | 4640 | #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION |
| 4368 | has_precision = 0; | 4641 | has_precision = 0; |
| 4369 | precision = 6; | 4642 | precision = 6; |
| 4370 | if (dp->precision_start != dp->precision_end) | 4643 | if (dp->precision_start != dp->precision_end) |
| @@ -4437,246 +4710,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 4437 | #if !USE_SNPRINTF | 4710 | #if !USE_SNPRINTF |
| 4438 | /* Allocate a temporary buffer of sufficient size for calling | 4711 | /* Allocate a temporary buffer of sufficient size for calling |
| 4439 | sprintf. */ | 4712 | sprintf. */ |
| 4440 | { | 4713 | tmp_length = |
| 4441 | switch (dp->conversion) | 4714 | MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type, |
| 4442 | { | 4715 | flags, width, has_precision, precision, |
| 4443 | 4716 | pad_ourselves); | |
| 4444 | case 'd': case 'i': case 'u': | ||
| 4445 | # if HAVE_LONG_LONG_INT | ||
| 4446 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | ||
| 4447 | tmp_length = | ||
| 4448 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT | ||
| 4449 | * 0.30103 /* binary -> decimal */ | ||
| 4450 | ) | ||
| 4451 | + 1; /* turn floor into ceil */ | ||
| 4452 | else | ||
| 4453 | # endif | ||
| 4454 | if (type == TYPE_LONGINT || type == TYPE_ULONGINT) | ||
| 4455 | tmp_length = | ||
| 4456 | (unsigned int) (sizeof (unsigned long) * CHAR_BIT | ||
| 4457 | * 0.30103 /* binary -> decimal */ | ||
| 4458 | ) | ||
| 4459 | + 1; /* turn floor into ceil */ | ||
| 4460 | else | ||
| 4461 | tmp_length = | ||
| 4462 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT | ||
| 4463 | * 0.30103 /* binary -> decimal */ | ||
| 4464 | ) | ||
| 4465 | + 1; /* turn floor into ceil */ | ||
| 4466 | if (tmp_length < precision) | ||
| 4467 | tmp_length = precision; | ||
| 4468 | /* Multiply by 2, as an estimate for FLAG_GROUP. */ | ||
| 4469 | tmp_length = xsum (tmp_length, tmp_length); | ||
| 4470 | /* Add 1, to account for a leading sign. */ | ||
| 4471 | tmp_length = xsum (tmp_length, 1); | ||
| 4472 | break; | ||
| 4473 | |||
| 4474 | case 'o': | ||
| 4475 | # if HAVE_LONG_LONG_INT | ||
| 4476 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | ||
| 4477 | tmp_length = | ||
| 4478 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT | ||
| 4479 | * 0.333334 /* binary -> octal */ | ||
| 4480 | ) | ||
| 4481 | + 1; /* turn floor into ceil */ | ||
| 4482 | else | ||
| 4483 | # endif | ||
| 4484 | if (type == TYPE_LONGINT || type == TYPE_ULONGINT) | ||
| 4485 | tmp_length = | ||
| 4486 | (unsigned int) (sizeof (unsigned long) * CHAR_BIT | ||
| 4487 | * 0.333334 /* binary -> octal */ | ||
| 4488 | ) | ||
| 4489 | + 1; /* turn floor into ceil */ | ||
| 4490 | else | ||
| 4491 | tmp_length = | ||
| 4492 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT | ||
| 4493 | * 0.333334 /* binary -> octal */ | ||
| 4494 | ) | ||
| 4495 | + 1; /* turn floor into ceil */ | ||
| 4496 | if (tmp_length < precision) | ||
| 4497 | tmp_length = precision; | ||
| 4498 | /* Add 1, to account for a leading sign. */ | ||
| 4499 | tmp_length = xsum (tmp_length, 1); | ||
| 4500 | break; | ||
| 4501 | |||
| 4502 | case 'x': case 'X': | ||
| 4503 | # if HAVE_LONG_LONG_INT | ||
| 4504 | if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) | ||
| 4505 | tmp_length = | ||
| 4506 | (unsigned int) (sizeof (unsigned long long) * CHAR_BIT | ||
| 4507 | * 0.25 /* binary -> hexadecimal */ | ||
| 4508 | ) | ||
| 4509 | + 1; /* turn floor into ceil */ | ||
| 4510 | else | ||
| 4511 | # endif | ||
| 4512 | if (type == TYPE_LONGINT || type == TYPE_ULONGINT) | ||
| 4513 | tmp_length = | ||
| 4514 | (unsigned int) (sizeof (unsigned long) * CHAR_BIT | ||
| 4515 | * 0.25 /* binary -> hexadecimal */ | ||
| 4516 | ) | ||
| 4517 | + 1; /* turn floor into ceil */ | ||
| 4518 | else | ||
| 4519 | tmp_length = | ||
| 4520 | (unsigned int) (sizeof (unsigned int) * CHAR_BIT | ||
| 4521 | * 0.25 /* binary -> hexadecimal */ | ||
| 4522 | ) | ||
| 4523 | + 1; /* turn floor into ceil */ | ||
| 4524 | if (tmp_length < precision) | ||
| 4525 | tmp_length = precision; | ||
| 4526 | /* Add 2, to account for a leading sign or alternate form. */ | ||
| 4527 | tmp_length = xsum (tmp_length, 2); | ||
| 4528 | break; | ||
| 4529 | |||
| 4530 | case 'f': case 'F': | ||
| 4531 | if (type == TYPE_LONGDOUBLE) | ||
| 4532 | tmp_length = | ||
| 4533 | (unsigned int) (LDBL_MAX_EXP | ||
| 4534 | * 0.30103 /* binary -> decimal */ | ||
| 4535 | * 2 /* estimate for FLAG_GROUP */ | ||
| 4536 | ) | ||
| 4537 | + 1 /* turn floor into ceil */ | ||
| 4538 | + 10; /* sign, decimal point etc. */ | ||
| 4539 | else | ||
| 4540 | tmp_length = | ||
| 4541 | (unsigned int) (DBL_MAX_EXP | ||
| 4542 | * 0.30103 /* binary -> decimal */ | ||
| 4543 | * 2 /* estimate for FLAG_GROUP */ | ||
| 4544 | ) | ||
| 4545 | + 1 /* turn floor into ceil */ | ||
| 4546 | + 10; /* sign, decimal point etc. */ | ||
| 4547 | tmp_length = xsum (tmp_length, precision); | ||
| 4548 | break; | ||
| 4549 | |||
| 4550 | case 'e': case 'E': case 'g': case 'G': | ||
| 4551 | tmp_length = | ||
| 4552 | 12; /* sign, decimal point, exponent etc. */ | ||
| 4553 | tmp_length = xsum (tmp_length, precision); | ||
| 4554 | break; | ||
| 4555 | |||
| 4556 | case 'a': case 'A': | ||
| 4557 | if (type == TYPE_LONGDOUBLE) | ||
| 4558 | tmp_length = | ||
| 4559 | (unsigned int) (LDBL_DIG | ||
| 4560 | * 0.831 /* decimal -> hexadecimal */ | ||
| 4561 | ) | ||
| 4562 | + 1; /* turn floor into ceil */ | ||
| 4563 | else | ||
| 4564 | tmp_length = | ||
| 4565 | (unsigned int) (DBL_DIG | ||
| 4566 | * 0.831 /* decimal -> hexadecimal */ | ||
| 4567 | ) | ||
| 4568 | + 1; /* turn floor into ceil */ | ||
| 4569 | if (tmp_length < precision) | ||
| 4570 | tmp_length = precision; | ||
| 4571 | /* Account for sign, decimal point etc. */ | ||
| 4572 | tmp_length = xsum (tmp_length, 12); | ||
| 4573 | break; | ||
| 4574 | |||
| 4575 | case 'c': | ||
| 4576 | # if HAVE_WINT_T && !WIDE_CHAR_VERSION | ||
| 4577 | if (type == TYPE_WIDE_CHAR) | ||
| 4578 | tmp_length = MB_CUR_MAX; | ||
| 4579 | else | ||
| 4580 | # endif | ||
| 4581 | tmp_length = 1; | ||
| 4582 | break; | ||
| 4583 | |||
| 4584 | case 's': | ||
| 4585 | # if HAVE_WCHAR_T | ||
| 4586 | if (type == TYPE_WIDE_STRING) | ||
| 4587 | { | ||
| 4588 | # if WIDE_CHAR_VERSION | ||
| 4589 | /* ISO C says about %ls in fwprintf: | ||
| 4590 | "If the precision is not specified or is greater | ||
| 4591 | than the size of the array, the array shall | ||
| 4592 | contain a null wide character." | ||
| 4593 | So if there is a precision, we must not use | ||
| 4594 | wcslen. */ | ||
| 4595 | const wchar_t *arg = | ||
| 4596 | a.arg[dp->arg_index].a.a_wide_string; | ||
| 4597 | |||
| 4598 | if (has_precision) | ||
| 4599 | tmp_length = local_wcsnlen (arg, precision); | ||
| 4600 | else | ||
| 4601 | tmp_length = local_wcslen (arg); | ||
| 4602 | # else | ||
| 4603 | /* ISO C says about %ls in fprintf: | ||
| 4604 | "If a precision is specified, no more than that | ||
| 4605 | many bytes are written (including shift | ||
| 4606 | sequences, if any), and the array shall contain | ||
| 4607 | a null wide character if, to equal the | ||
| 4608 | multibyte character sequence length given by | ||
| 4609 | the precision, the function would need to | ||
| 4610 | access a wide character one past the end of the | ||
| 4611 | array." | ||
| 4612 | So if there is a precision, we must not use | ||
| 4613 | wcslen. */ | ||
| 4614 | /* This case has already been handled above. */ | ||
| 4615 | abort (); | ||
| 4616 | # endif | ||
| 4617 | } | ||
| 4618 | else | ||
| 4619 | # endif | ||
| 4620 | { | ||
| 4621 | # if WIDE_CHAR_VERSION | ||
| 4622 | /* ISO C says about %s in fwprintf: | ||
| 4623 | "If the precision is not specified or is greater | ||
| 4624 | than the size of the converted array, the | ||
| 4625 | converted array shall contain a null wide | ||
| 4626 | character." | ||
| 4627 | So if there is a precision, we must not use | ||
| 4628 | strlen. */ | ||
| 4629 | /* This case has already been handled above. */ | ||
| 4630 | abort (); | ||
| 4631 | # else | ||
| 4632 | /* ISO C says about %s in fprintf: | ||
| 4633 | "If the precision is not specified or greater | ||
| 4634 | than the size of the array, the array shall | ||
| 4635 | contain a null character." | ||
| 4636 | So if there is a precision, we must not use | ||
| 4637 | strlen. */ | ||
| 4638 | const char *arg = a.arg[dp->arg_index].a.a_string; | ||
| 4639 | |||
| 4640 | if (has_precision) | ||
| 4641 | tmp_length = local_strnlen (arg, precision); | ||
| 4642 | else | ||
| 4643 | tmp_length = strlen (arg); | ||
| 4644 | # endif | ||
| 4645 | } | ||
| 4646 | break; | ||
| 4647 | |||
| 4648 | case 'p': | ||
| 4649 | tmp_length = | ||
| 4650 | (unsigned int) (sizeof (void *) * CHAR_BIT | ||
| 4651 | * 0.25 /* binary -> hexadecimal */ | ||
| 4652 | ) | ||
| 4653 | + 1 /* turn floor into ceil */ | ||
| 4654 | + 2; /* account for leading 0x */ | ||
| 4655 | break; | ||
| 4656 | |||
| 4657 | default: | ||
| 4658 | abort (); | ||
| 4659 | } | ||
| 4660 | |||
| 4661 | if (!pad_ourselves) | ||
| 4662 | { | ||
| 4663 | # if ENABLE_UNISTDIO | ||
| 4664 | /* Padding considers the number of characters, therefore | ||
| 4665 | the number of elements after padding may be | ||
| 4666 | > max (tmp_length, width) | ||
| 4667 | but is certainly | ||
| 4668 | <= tmp_length + width. */ | ||
| 4669 | tmp_length = xsum (tmp_length, width); | ||
| 4670 | # else | ||
| 4671 | /* Padding considers the number of elements, | ||
| 4672 | says POSIX. */ | ||
| 4673 | if (tmp_length < width) | ||
| 4674 | tmp_length = width; | ||
| 4675 | # endif | ||
| 4676 | } | ||
| 4677 | |||
| 4678 | tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ | ||
| 4679 | } | ||
| 4680 | 4717 | ||
| 4681 | if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T)) | 4718 | if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T)) |
| 4682 | tmp = tmpbuf; | 4719 | tmp = tmpbuf; |
| @@ -4916,6 +4953,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 4916 | } | 4953 | } |
| 4917 | #endif | 4954 | #endif |
| 4918 | 4955 | ||
| 4956 | errno = 0; | ||
| 4919 | switch (type) | 4957 | switch (type) |
| 4920 | { | 4958 | { |
| 4921 | case TYPE_SCHAR: | 4959 | case TYPE_SCHAR: |
| @@ -5062,15 +5100,44 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 5062 | /* Look at the snprintf() return value. */ | 5100 | /* Look at the snprintf() return value. */ |
| 5063 | if (retcount < 0) | 5101 | if (retcount < 0) |
| 5064 | { | 5102 | { |
| 5103 | # if !HAVE_SNPRINTF_RETVAL_C99 | ||
| 5065 | /* HP-UX 10.20 snprintf() is doubly deficient: | 5104 | /* HP-UX 10.20 snprintf() is doubly deficient: |
| 5066 | It doesn't understand the '%n' directive, | 5105 | It doesn't understand the '%n' directive, |
| 5067 | *and* it returns -1 (rather than the length | 5106 | *and* it returns -1 (rather than the length |
| 5068 | that would have been required) when the | 5107 | that would have been required) when the |
| 5069 | buffer is too small. */ | 5108 | buffer is too small. |
| 5070 | size_t bigger_need = | 5109 | But a failure at this point can also come |
| 5071 | xsum (xtimes (allocated, 2), 12); | 5110 | from other reasons than a too small buffer, |
| 5072 | ENSURE_ALLOCATION (bigger_need); | 5111 | such as an invalid wide string argument to |
| 5073 | continue; | 5112 | the %ls directive, or possibly an invalid |
| 5113 | floating-point argument. */ | ||
| 5114 | size_t tmp_length = | ||
| 5115 | MAX_ROOM_NEEDED (&a, dp->arg_index, | ||
| 5116 | dp->conversion, type, flags, | ||
| 5117 | width, has_precision, | ||
| 5118 | precision, pad_ourselves); | ||
| 5119 | |||
| 5120 | if (maxlen < tmp_length) | ||
| 5121 | { | ||
| 5122 | /* Make more room. But try to do through | ||
| 5123 | this reallocation only once. */ | ||
| 5124 | size_t bigger_need = | ||
| 5125 | xsum (length, | ||
| 5126 | xsum (tmp_length, | ||
| 5127 | TCHARS_PER_DCHAR - 1) | ||
| 5128 | / TCHARS_PER_DCHAR); | ||
| 5129 | /* And always grow proportionally. | ||
| 5130 | (There may be several arguments, each | ||
| 5131 | needing a little more room than the | ||
| 5132 | previous one.) */ | ||
| 5133 | size_t bigger_need2 = | ||
| 5134 | xsum (xtimes (allocated, 2), 12); | ||
| 5135 | if (bigger_need < bigger_need2) | ||
| 5136 | bigger_need = bigger_need2; | ||
| 5137 | ENSURE_ALLOCATION (bigger_need); | ||
| 5138 | continue; | ||
| 5139 | } | ||
| 5140 | # endif | ||
| 5074 | } | 5141 | } |
| 5075 | else | 5142 | else |
| 5076 | count = retcount; | 5143 | count = retcount; |
| @@ -5081,12 +5148,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 5081 | /* Attempt to handle failure. */ | 5148 | /* Attempt to handle failure. */ |
| 5082 | if (count < 0) | 5149 | if (count < 0) |
| 5083 | { | 5150 | { |
| 5151 | /* SNPRINTF or sprintf failed. Save and use the errno | ||
| 5152 | that it has set, if any. */ | ||
| 5153 | int saved_errno = errno; | ||
| 5154 | |||
| 5084 | if (!(result == resultbuf || result == NULL)) | 5155 | if (!(result == resultbuf || result == NULL)) |
| 5085 | free (result); | 5156 | free (result); |
| 5086 | if (buf_malloced != NULL) | 5157 | if (buf_malloced != NULL) |
| 5087 | free (buf_malloced); | 5158 | free (buf_malloced); |
| 5088 | CLEANUP (); | 5159 | CLEANUP (); |
| 5089 | errno = EINVAL; | 5160 | errno = |
| 5161 | (saved_errno != 0 | ||
| 5162 | ? saved_errno | ||
| 5163 | : (dp->conversion == 'c' || dp->conversion == 's' | ||
| 5164 | ? EILSEQ | ||
| 5165 | : EINVAL)); | ||
| 5090 | return NULL; | 5166 | return NULL; |
| 5091 | } | 5167 | } |
| 5092 | 5168 | ||
| @@ -5422,6 +5498,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 5422 | length += count; | 5498 | length += count; |
| 5423 | break; | 5499 | break; |
| 5424 | } | 5500 | } |
| 5501 | #undef pad_ourselves | ||
| 5502 | #undef prec_ourselves | ||
| 5425 | } | 5503 | } |
| 5426 | } | 5504 | } |
| 5427 | } | 5505 | } |
| @@ -5473,6 +5551,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, | |||
| 5473 | } | 5551 | } |
| 5474 | } | 5552 | } |
| 5475 | 5553 | ||
| 5554 | #undef MAX_ROOM_NEEDED | ||
| 5476 | #undef TCHARS_PER_DCHAR | 5555 | #undef TCHARS_PER_DCHAR |
| 5477 | #undef SNPRINTF | 5556 | #undef SNPRINTF |
| 5478 | #undef USE_SNPRINTF | 5557 | #undef USE_SNPRINTF |
