PIPS
vasnprintf.c File Reference
#include <config.h>
#include <alloca.h>
#include "vasnprintf.h"
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <float.h>
#include "printf-parse.h"
#include "xsize.h"
#include "verify.h"
+ Include dependency graph for vasnprintf.c:

Go to the source code of this file.

Macros

#define _GNU_SOURCE   1
 vsprintf with automatic memory allocation. More...
 
#define VASNPRINTF   vasnprintf
 Specification. More...
 
#define FCHAR_T   char
 
#define DCHAR_T   char
 
#define TCHAR_T   char
 
#define DCHAR_IS_TCHAR   1
 
#define DIRECTIVE   char_directive
 
#define DIRECTIVES   char_directives
 
#define PRINTF_PARSE   printf_parse
 
#define DCHAR_CPY   memcpy
 
#define DCHAR_SET   memset
 
#define USE_SNPRINTF   0
 TCHAR_T is char. More...
 
#define SNPRINTF   snprintf
 Unix. More...
 
#define IF_LINT(Code)   /**empty */
 Here we need to call the native snprintf, not rpl_snprintf. More...
 
#define exp   expo
 Avoid some warnings from "gcc -Wshadow". More...
 
#define remainder   rem
 
#define local_strnlen_defined   1
 
#define MAX_ROOM_NEEDED   max_room_needed
 Use a different function name, to make it possible that the 'wchar_t' parametrization and the 'char' parametrization get compiled in the same translation unit. More...
 
#define CLEANUP()
 
#define ENSURE_ALLOCATION(needed)
 
#define prec_ourselves   0
 
#define pad_ourselves   0
 
#define SNPRINTF_BUF(arg)
 

Functions

static size_t local_strnlen (const char *string, size_t maxlen)
 
static size_t MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion, arg_type type, int flags, size_t width, int has_precision, size_t precision, int pad_ourselves)
 Returns the number of TCHAR_T units needed as temporary space for the result of sprintf or SNPRINTF of a single conversion directive. More...
 
DCHAR_TVASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, const FCHAR_T *format, va_list args)
 

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE   1

vsprintf with automatic memory allocation.

Copyright (C) 1999, 2002-2014 Free Software Foundation, Inc.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, see http://www.gnu.org/licenses/.
This file can be parametrized with the following macros: VASNPRINTF The name of the function being defined. FCHAR_T The element type of the format string. DCHAR_T The element type of the destination (result) string. FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters in the format string are ASCII. MUST be set if FCHAR_T and DCHAR_T are not the same type. DIRECTIVE Structure denoting a format directive. Depends on FCHAR_T. DIRECTIVES Structure denoting the set of format directives of a format string. Depends on FCHAR_T. PRINTF_PARSE Function that parses a format string. Depends on FCHAR_T. DCHAR_CPY memcpy like function for DCHAR_T[] arrays. DCHAR_SET memset like function for DCHAR_T[] arrays. DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays. SNPRINTF The system's snprintf (or similar) function. This may be either snprintf or swprintf. TCHAR_T The element type of the argument and result string of the said SNPRINTF function. This may be either char or wchar_t. The code exploits that sizeof (TCHAR_T) | sizeof (DCHAR_T) and alignof (TCHAR_T) <= alignof (DCHAR_T). DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type. DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[]. DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t. DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t. DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t.
Tell glibc's <stdio.h> to provide a prototype for snprintf(). This must come before <config.h> because <config.h> may include <features.h>, and once <features.h> has been included, it's too late.

Definition at line 50 of file vasnprintf.c.

◆ CLEANUP

#define CLEANUP ( )
Value:
if (d.dir != d.direct_alloc_dir) \
free (d.dir); \
if (a.arg != a.direct_alloc_arg) \
free (a.arg);

◆ DCHAR_CPY

#define DCHAR_CPY   memcpy

Definition at line 143 of file vasnprintf.c.

◆ DCHAR_IS_TCHAR

#define DCHAR_IS_TCHAR   1

Definition at line 139 of file vasnprintf.c.

◆ DCHAR_SET

#define DCHAR_SET   memset

Definition at line 144 of file vasnprintf.c.

◆ DCHAR_T

#define DCHAR_T   char

Definition at line 137 of file vasnprintf.c.

◆ DIRECTIVE

#define DIRECTIVE   char_directive

Definition at line 140 of file vasnprintf.c.

◆ DIRECTIVES

#define DIRECTIVES   char_directives

Definition at line 141 of file vasnprintf.c.

◆ ENSURE_ALLOCATION

#define ENSURE_ALLOCATION (   needed)
Value:
if ((needed) > allocated) \
{ \
size_t memory_size; \
DCHAR_T *memory; \
\
allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
if ((needed) > allocated) \
allocated = (needed); \
memory_size = xtimes (allocated, sizeof (DCHAR_T)); \
if (size_overflow_p (memory_size)) \
goto out_of_memory; \
if (result == resultbuf || result == NULL) \
memory = (DCHAR_T *) malloc (memory_size); \
else \
memory = (DCHAR_T *) realloc (result, memory_size); \
if (memory == NULL) \
goto out_of_memory; \
if (result == resultbuf && length > 0) \
DCHAR_CPY (memory, result, length); \
result = memory; \
}
void * malloc(YYSIZE_T)
#define DCHAR_T
Definition: vasnprintf.c:137
#define size_overflow_p(SIZE)
Check for overflow.
Definition: xsize.h:109
#define xtimes(N, ELSIZE)
Multiplication of a count with an element size, with overflow check.
Definition: xsize.h:105

◆ exp

#define exp   expo

Avoid some warnings from "gcc -Wshadow".

This file doesn't use the exp() and remainder() functions.

Definition at line 207 of file vasnprintf.c.

◆ FCHAR_T

#define FCHAR_T   char

Definition at line 136 of file vasnprintf.c.

◆ IF_LINT

#define IF_LINT (   Code)    /**empty */

Here we need to call the native snprintf, not rpl_snprintf.


Here we need to call the native sprintf, not rpl_sprintf.
GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized" warnings in this file. Use -Dlint to suppress them.

Definition at line 201 of file vasnprintf.c.

◆ local_strnlen_defined

#define local_strnlen_defined   1

Definition at line 216 of file vasnprintf.c.

◆ MAX_ROOM_NEEDED

#define MAX_ROOM_NEEDED   max_room_needed

Use a different function name, to make it possible that the 'wchar_t' parametrization and the 'char' parametrization get compiled in the same translation unit.


Definition at line 1528 of file vasnprintf.c.

◆ pad_ourselves

#define pad_ourselves   0

◆ prec_ourselves

#define prec_ourselves   0

◆ PRINTF_PARSE

#define PRINTF_PARSE   printf_parse

Definition at line 142 of file vasnprintf.c.

◆ remainder

#define remainder   rem

Definition at line 209 of file vasnprintf.c.

◆ SNPRINTF

#define SNPRINTF   snprintf

Unix.


Definition at line 188 of file vasnprintf.c.

◆ SNPRINTF_BUF

#define SNPRINTF_BUF (   arg)
Value:
switch (prefix_count) \
{ \
case 0: \
count = sprintf (tmp, buf, arg); \
break; \
case 1: \
count = sprintf (tmp, buf, prefixes[0], arg); \
break; \
case 2: \
count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
arg); \
break; \
default: \
abort (); \
}
static string prefixes[]
Definition: entity.c:1433
static char buf[BSZ]
Definition: split_file.c:157

◆ TCHAR_T

#define TCHAR_T   char

Definition at line 138 of file vasnprintf.c.

◆ USE_SNPRINTF

#define USE_SNPRINTF   0

TCHAR_T is char.


Use snprintf if it exists under the name 'snprintf' or '_snprintf'. But don't use it on BeOS, since BeOS snprintf produces no output if the size argument is >= 0x3000000. Also don't use it on Linux libc5, since there snprintf with size = 1 writes any output without bounds, like sprintf.

Definition at line 174 of file vasnprintf.c.

◆ VASNPRINTF

#define VASNPRINTF   vasnprintf

Specification.


localeconv() snprintf(), sprintf() abort(), malloc(), realloc(), free() memcpy(), strlen() errno CHAR_BIT DBL_MAX_EXP, LDBL_MAX_EXP Checked size_t computations.
Default parameters.

Definition at line 135 of file vasnprintf.c.

Function Documentation

◆ local_strnlen()

static size_t local_strnlen ( const char *  string,
size_t  maxlen 
)
static

Definition at line 218 of file vasnprintf.c.

219 {
220  const char *end = memchr (string, '\0', maxlen);
221  return end ? (size_t) (end - string) : maxlen;
222 }
char end
Definition: gtk_status.c:82
size_t size_t
Definition: properties.c:413

References end.

Referenced by MAX_ROOM_NEEDED().

+ Here is the caller graph for this function:

◆ MAX_ROOM_NEEDED()

static size_t MAX_ROOM_NEEDED ( const arguments ap,
size_t  arg_index,
FCHAR_T  conversion,
arg_type  type,
int  flags,
size_t  width,
int  has_precision,
size_t  precision,
int  pad_ourselves 
)
static

Returns the number of TCHAR_T units needed as temporary space for the result of sprintf or SNPRINTF of a single conversion directive.


binary -> decimal

turn floor into ceil

binary -> decimal

turn floor into ceil

Multiply by 2, as an estimate for FLAG_GROUP.

Add 1, to account for a leading sign.

binary -> octal

turn floor into ceil

binary -> octal

turn floor into ceil

Add 1, to account for a leading sign.

binary -> hexadecimal

turn floor into ceil

binary -> hexadecimal

turn floor into ceil

Add 2, to account for a leading sign or alternate form.

binary -> decimal

estimate for FLAG_GROUP

turn floor into ceil

sign, decimal point etc.

binary -> decimal

estimate for FLAG_GROUP

turn floor into ceil

sign, decimal point etc.

sign, decimal point, exponent etc.

decimal -> hexadecimal

turn floor into ceil

decimal -> hexadecimal

turn floor into ceil

Account for sign, decimal point etc.

ISO C says about s in fprintf: "If the precision is not specified or greater than the size of the array, the array shall contain a null character." So if there is a precision, we must not use strlen.

binary -> hexadecimal

turn floor into ceil

account for leading 0x

Padding considers the number of elements, says POSIX.

account for trailing NUL

Definition at line 1534 of file vasnprintf.c.

1537 {
1538  size_t tmp_length;
1539 
1540  switch (conversion)
1541  {
1542  case 'd': case 'i': case 'u':
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.30103 /* binary -> decimal */
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.30103 /* binary -> decimal */
1556  )
1557  + 1; /* turn floor into ceil */
1558  else
1559  tmp_length =
1560  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
1561  * 0.30103 /* binary -> decimal */
1562  )
1563  + 1; /* turn floor into ceil */
1564  if (tmp_length < precision)
1565  tmp_length = precision;
1566  /* Multiply by 2, as an estimate for FLAG_GROUP. */
1567  tmp_length = xsum (tmp_length, tmp_length);
1568  /* Add 1, to account for a leading sign. */
1569  tmp_length = xsum (tmp_length, 1);
1570  break;
1571 
1572  case 'o':
1573 # if HAVE_LONG_LONG_INT
1574  if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
1575  tmp_length =
1576  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
1577  * 0.333334 /* binary -> octal */
1578  )
1579  + 1; /* turn floor into ceil */
1580  else
1581 # endif
1582  if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
1583  tmp_length =
1584  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
1585  * 0.333334 /* binary -> octal */
1586  )
1587  + 1; /* turn floor into ceil */
1588  else
1589  tmp_length =
1590  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
1591  * 0.333334 /* binary -> octal */
1592  )
1593  + 1; /* turn floor into ceil */
1594  if (tmp_length < precision)
1595  tmp_length = precision;
1596  /* Add 1, to account for a leading sign. */
1597  tmp_length = xsum (tmp_length, 1);
1598  break;
1599 
1600  case 'x': case 'X':
1601 # if HAVE_LONG_LONG_INT
1602  if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
1603  tmp_length =
1604  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
1605  * 0.25 /* binary -> hexadecimal */
1606  )
1607  + 1; /* turn floor into ceil */
1608  else
1609 # endif
1610  if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
1611  tmp_length =
1612  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
1613  * 0.25 /* binary -> hexadecimal */
1614  )
1615  + 1; /* turn floor into ceil */
1616  else
1617  tmp_length =
1618  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
1619  * 0.25 /* binary -> hexadecimal */
1620  )
1621  + 1; /* turn floor into ceil */
1622  if (tmp_length < precision)
1623  tmp_length = precision;
1624  /* Add 2, to account for a leading sign or alternate form. */
1625  tmp_length = xsum (tmp_length, 2);
1626  break;
1627 
1628  case 'f': case 'F':
1629  if (type == TYPE_LONGDOUBLE)
1630  tmp_length =
1631  (unsigned int) (LDBL_MAX_EXP
1632  * 0.30103 /* binary -> decimal */
1633  * 2 /* estimate for FLAG_GROUP */
1634  )
1635  + 1 /* turn floor into ceil */
1636  + 10; /* sign, decimal point etc. */
1637  else
1638  tmp_length =
1639  (unsigned int) (DBL_MAX_EXP
1640  * 0.30103 /* binary -> decimal */
1641  * 2 /* estimate for FLAG_GROUP */
1642  )
1643  + 1 /* turn floor into ceil */
1644  + 10; /* sign, decimal point etc. */
1645  tmp_length = xsum (tmp_length, precision);
1646  break;
1647 
1648  case 'e': case 'E': case 'g': case 'G':
1649  tmp_length =
1650  12; /* sign, decimal point, exponent etc. */
1651  tmp_length = xsum (tmp_length, precision);
1652  break;
1653 
1654  case 'a': case 'A':
1655  if (type == TYPE_LONGDOUBLE)
1656  tmp_length =
1657  (unsigned int) (LDBL_DIG
1658  * 0.831 /* decimal -> hexadecimal */
1659  )
1660  + 1; /* turn floor into ceil */
1661  else
1662  tmp_length =
1663  (unsigned int) (DBL_DIG
1664  * 0.831 /* decimal -> hexadecimal */
1665  )
1666  + 1; /* turn floor into ceil */
1667  if (tmp_length < precision)
1668  tmp_length = precision;
1669  /* Account for sign, decimal point etc. */
1670  tmp_length = xsum (tmp_length, 12);
1671  break;
1672 
1673  case 'c':
1674 # if HAVE_WINT_T && !WIDE_CHAR_VERSION
1675  if (type == TYPE_WIDE_CHAR)
1676  tmp_length = MB_CUR_MAX;
1677  else
1678 # endif
1679  tmp_length = 1;
1680  break;
1681 
1682  case 's':
1683 # if HAVE_WCHAR_T
1684  if (type == TYPE_WIDE_STRING)
1685  {
1686 # if WIDE_CHAR_VERSION
1687  /* ISO C says about %ls in fwprintf:
1688  "If the precision is not specified or is greater than the size
1689  of the array, the array shall contain a null wide character."
1690  So if there is a precision, we must not use wcslen. */
1691  const wchar_t *arg = ap->arg[arg_index].a.a_wide_string;
1692 
1693  if (has_precision)
1694  tmp_length = local_wcsnlen (arg, precision);
1695  else
1696  tmp_length = local_wcslen (arg);
1697 # else
1698  /* ISO C says about %ls in fprintf:
1699  "If a precision is specified, no more than that many bytes are
1700  written (including shift sequences, if any), and the array
1701  shall contain a null wide character if, to equal the multibyte
1702  character sequence length given by the precision, the function
1703  would need to access a wide character one past the end of the
1704  array."
1705  So if there is a precision, we must not use wcslen. */
1706  /* This case has already been handled separately in VASNPRINTF. */
1707  abort ();
1708 # endif
1709  }
1710  else
1711 # endif
1712  {
1713 # if WIDE_CHAR_VERSION
1714  /* ISO C says about %s in fwprintf:
1715  "If the precision is not specified or is greater than the size
1716  of the converted array, the converted array shall contain a
1717  null wide character."
1718  So if there is a precision, we must not use strlen. */
1719  /* This case has already been handled separately in VASNPRINTF. */
1720  abort ();
1721 # else
1722  /* ISO C says about %s in fprintf:
1723  "If the precision is not specified or greater than the size of
1724  the array, the array shall contain a null character."
1725  So if there is a precision, we must not use strlen. */
1726  const char *arg = ap->arg[arg_index].a.a_string;
1727 
1728  if (has_precision)
1729  tmp_length = local_strnlen (arg, precision);
1730  else
1731  tmp_length = strlen (arg);
1732 # endif
1733  }
1734  break;
1735 
1736  case 'p':
1737  tmp_length =
1738  (unsigned int) (sizeof (void *) * CHAR_BIT
1739  * 0.25 /* binary -> hexadecimal */
1740  )
1741  + 1 /* turn floor into ceil */
1742  + 2; /* account for leading 0x */
1743  break;
1744 
1745  default:
1746  abort ();
1747  }
1748 
1749  if (!pad_ourselves)
1750  {
1751 # if ENABLE_UNISTDIO
1752  /* Padding considers the number of characters, therefore the number of
1753  elements after padding may be
1754  > max (tmp_length, width)
1755  but is certainly
1756  <= tmp_length + width. */
1757  tmp_length = xsum (tmp_length, width);
1758 # else
1759  /* Padding considers the number of elements, says POSIX. */
1760  if (tmp_length < width)
1761  tmp_length = width;
1762 # endif
1763  }
1764 
1765  tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
1766 
1767  return tmp_length;
1768 }
void const char const char const int
#define abort()
Definition: misc-local.h:53
@ TYPE_LONGINT
Definition: printf-args.h:58
@ TYPE_LONGDOUBLE
Definition: printf-args.h:65
@ TYPE_ULONGINT
Definition: printf-args.h:59
static void precision(struct rproblem *RR, int i, int nx)
fin validite
Definition: r1.c:383
union argument::@14 a
const char * a_string
Definition: printf-args.h:115
argument * arg
Definition: printf-args.h:144
#define pad_ourselves
static size_t local_strnlen(const char *string, size_t maxlen)
Definition: vasnprintf.c:218
XSIZE_INLINE size_t xsum(size_t size1, size_t size2)
Sum of two sizes, with overflow check.
Definition: xsize.h:63

References argument::a, argument::a_string, abort, arguments::arg, int, local_strnlen(), pad_ourselves, precision(), TYPE_LONGDOUBLE, TYPE_LONGINT, TYPE_ULONGINT, and xsum().

+ Here is the call graph for this function:

◆ VASNPRINTF()

DCHAR_T* VASNPRINTF ( DCHAR_T resultbuf,
size_t lengthp,
const FCHAR_T format,
va_list  args 
)

errno is already set.

Output string accumulator.

Allocate a small buffer that will hold a directive passed to sprintf or snprintf.

Invariants: result is either == resultbuf or == NULL or malloc-allocated. If length > 0, then result != NULL.

Ensures that allocated >= needed. Aborts through a jump to out_of_memory if needed is SIZE_MAX or otherwise too big.

This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we need that the format string contains only ASCII characters if FCHAR_T and DCHAR_T are not the same type.

Execute a single directive.

"A negative field width is taken as a '-' flag followed by a positive field width."

"A negative precision is taken as if the precision were omitted."

Decide whether to handle the precision ourselves.

Decide whether to perform the padding ourselves.

Allocate a temporary buffer of sufficient size for calling sprintf.

Overflow, would lead to out of memory.

Out of memory.

Construct the format string for calling snprintf or sprintf.

The width specification is known to consist only of standard ASCII characters.

The precision specification is known to consist only of standard ASCII characters.

Construct the arguments for calling snprintf or sprintf.

Attempt to handle failure.

SNPRINTF or sprintf failed. Save and use the errno that it has set, if any.

tmp_length was incorrectly calculated - fix the code above!

Make room for the result.

Need at least count elements. But allocate proportionally.

Here count <= allocated - length.

Perform padding.

Here still count <= allocated - length.

Append the sprintf() result.

Add the final NUL.

Shrink the allocated memory if possible.

Note that we can produce a big string of a length > INT_MAX. POSIX says that snprintf() fails with errno = EOVERFLOW in this case, but that's only because snprintf() returns an 'int'. This function does not have this limitation.

Definition at line 1773 of file vasnprintf.c.

1775 {
1776  DIRECTIVES d;
1777  arguments a;
1778 
1779  if (PRINTF_PARSE (format, &d, &a) < 0)
1780  /* errno is already set. */
1781  return NULL;
1782 
1783 #define CLEANUP() \
1784  if (d.dir != d.direct_alloc_dir) \
1785  free (d.dir); \
1786  if (a.arg != a.direct_alloc_arg) \
1787  free (a.arg);
1788 
1789  if (PRINTF_FETCHARGS (args, &a) < 0)
1790  {
1791  CLEANUP ();
1792  errno = EINVAL;
1793  return NULL;
1794  }
1795 
1796  {
1797  size_t buf_neededlength;
1798  TCHAR_T *buf;
1799  TCHAR_T *buf_malloced;
1800  const FCHAR_T *cp;
1801  size_t i;
1802  DIRECTIVE *dp;
1803  /* Output string accumulator. */
1804  DCHAR_T *result;
1805  size_t allocated;
1806  size_t length;
1807 
1808  /* Allocate a small buffer that will hold a directive passed to
1809  sprintf or snprintf. */
1810  buf_neededlength =
1811  xsum4 (7, d.max_width_length, d.max_precision_length, 6);
1812 #if HAVE_ALLOCA
1813  if (buf_neededlength < 4000 / sizeof (TCHAR_T))
1814  {
1815  buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));
1816  buf_malloced = NULL;
1817  }
1818  else
1819 #endif
1820  {
1821  size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));
1822  if (size_overflow_p (buf_memsize))
1823  goto out_of_memory_1;
1824  buf = (TCHAR_T *) malloc (buf_memsize);
1825  if (buf == NULL)
1826  goto out_of_memory_1;
1827  buf_malloced = buf;
1828  }
1829 
1830  if (resultbuf != NULL)
1831  {
1832  result = resultbuf;
1833  allocated = *lengthp;
1834  }
1835  else
1836  {
1837  result = NULL;
1838  allocated = 0;
1839  }
1840  length = 0;
1841  /* Invariants:
1842  result is either == resultbuf or == NULL or malloc-allocated.
1843  If length > 0, then result != NULL. */
1844 
1845  /* Ensures that allocated >= needed. Aborts through a jump to
1846  out_of_memory if needed is SIZE_MAX or otherwise too big. */
1847 #define ENSURE_ALLOCATION(needed) \
1848  if ((needed) > allocated) \
1849  { \
1850  size_t memory_size; \
1851  DCHAR_T *memory; \
1852  \
1853  allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
1854  if ((needed) > allocated) \
1855  allocated = (needed); \
1856  memory_size = xtimes (allocated, sizeof (DCHAR_T)); \
1857  if (size_overflow_p (memory_size)) \
1858  goto out_of_memory; \
1859  if (result == resultbuf || result == NULL) \
1860  memory = (DCHAR_T *) malloc (memory_size); \
1861  else \
1862  memory = (DCHAR_T *) realloc (result, memory_size); \
1863  if (memory == NULL) \
1864  goto out_of_memory; \
1865  if (result == resultbuf && length > 0) \
1866  DCHAR_CPY (memory, result, length); \
1867  result = memory; \
1868  }
1869 
1870  for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
1871  {
1872  if (cp != dp->dir_start)
1873  {
1874  size_t n = dp->dir_start - cp;
1875  size_t augmented_length = xsum (length, n);
1876 
1877  ENSURE_ALLOCATION (augmented_length);
1878  /* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we
1879  need that the format string contains only ASCII characters
1880  if FCHAR_T and DCHAR_T are not the same type. */
1881  if (sizeof (FCHAR_T) == sizeof (DCHAR_T))
1882  {
1883  DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);
1884  length = augmented_length;
1885  }
1886  else
1887  {
1888  do
1889  result[length++] = (unsigned char) *cp++;
1890  while (--n > 0);
1891  }
1892  }
1893  if (i == d.count)
1894  break;
1895 
1896  /* Execute a single directive. */
1897  if (dp->conversion == '%')
1898  {
1899  size_t augmented_length;
1900 
1901  if (!(dp->arg_index == ARG_NONE))
1902  abort ();
1903  augmented_length = xsum (length, 1);
1904  ENSURE_ALLOCATION (augmented_length);
1905  result[length] = '%';
1906  length = augmented_length;
1907  }
1908  else
1909  {
1910  if (!(dp->arg_index != ARG_NONE))
1911  abort ();
1912 
1913  if (dp->conversion == 'n')
1914  {
1915  switch (a.arg[dp->arg_index].type)
1916  {
1918  *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
1919  break;
1921  *a.arg[dp->arg_index].a.a_count_short_pointer = length;
1922  break;
1924  *a.arg[dp->arg_index].a.a_count_int_pointer = length;
1925  break;
1927  *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
1928  break;
1929 #if HAVE_LONG_LONG_INT
1930  case TYPE_COUNT_LONGLONGINT_POINTER:
1931  *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
1932  break;
1933 #endif
1934  default:
1935  abort ();
1936  }
1937  }
1938 #if ENABLE_UNISTDIO
1939  /* The unistdio extensions. */
1940  else if (dp->conversion == 'U')
1941  {
1942  arg_type type = a.arg[dp->arg_index].type;
1943  int flags = dp->flags;
1944  int has_width;
1945  size_t width;
1946  int has_precision;
1947  size_t precision;
1948 
1949  has_width = 0;
1950  width = 0;
1951  if (dp->width_start != dp->width_end)
1952  {
1953  if (dp->width_arg_index != ARG_NONE)
1954  {
1955  int arg;
1956 
1957  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
1958  abort ();
1959  arg = a.arg[dp->width_arg_index].a.a_int;
1960  if (arg < 0)
1961  {
1962  /* "A negative field width is taken as a '-' flag
1963  followed by a positive field width." */
1964  flags |= FLAG_LEFT;
1965  width = (unsigned int) (-arg);
1966  }
1967  else
1968  width = arg;
1969  }
1970  else
1971  {
1972  const FCHAR_T *digitp = dp->width_start;
1973 
1974  do
1975  width = xsum (xtimes (width, 10), *digitp++ - '0');
1976  while (digitp != dp->width_end);
1977  }
1978  has_width = 1;
1979  }
1980 
1981  has_precision = 0;
1982  precision = 0;
1983  if (dp->precision_start != dp->precision_end)
1984  {
1985  if (dp->precision_arg_index != ARG_NONE)
1986  {
1987  int arg;
1988 
1989  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
1990  abort ();
1991  arg = a.arg[dp->precision_arg_index].a.a_int;
1992  /* "A negative precision is taken as if the precision
1993  were omitted." */
1994  if (arg >= 0)
1995  {
1996  precision = arg;
1997  has_precision = 1;
1998  }
1999  }
2000  else
2001  {
2002  const FCHAR_T *digitp = dp->precision_start + 1;
2003 
2004  precision = 0;
2005  while (digitp != dp->precision_end)
2006  precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2007  has_precision = 1;
2008  }
2009  }
2010 
2011  switch (type)
2012  {
2013  case TYPE_U8_STRING:
2014  {
2015  const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;
2016  const uint8_t *arg_end;
2017  size_t characters;
2018 
2019  if (has_precision)
2020  {
2021  /* Use only PRECISION characters, from the left. */
2022  arg_end = arg;
2023  characters = 0;
2024  for (; precision > 0; precision--)
2025  {
2026  int count = u8_strmblen (arg_end);
2027  if (count == 0)
2028  break;
2029  if (count < 0)
2030  {
2031  if (!(result == resultbuf || result == NULL))
2032  free (result);
2033  if (buf_malloced != NULL)
2034  free (buf_malloced);
2035  CLEANUP ();
2036  errno = EILSEQ;
2037  return NULL;
2038  }
2039  arg_end += count;
2040  characters++;
2041  }
2042  }
2043  else if (has_width)
2044  {
2045  /* Use the entire string, and count the number of
2046  characters. */
2047  arg_end = arg;
2048  characters = 0;
2049  for (;;)
2050  {
2051  int count = u8_strmblen (arg_end);
2052  if (count == 0)
2053  break;
2054  if (count < 0)
2055  {
2056  if (!(result == resultbuf || result == NULL))
2057  free (result);
2058  if (buf_malloced != NULL)
2059  free (buf_malloced);
2060  CLEANUP ();
2061  errno = EILSEQ;
2062  return NULL;
2063  }
2064  arg_end += count;
2065  characters++;
2066  }
2067  }
2068  else
2069  {
2070  /* Use the entire string. */
2071  arg_end = arg + u8_strlen (arg);
2072  /* The number of characters doesn't matter. */
2073  characters = 0;
2074  }
2075 
2076  if (has_width && width > characters
2077  && !(dp->flags & FLAG_LEFT))
2078  {
2079  size_t n = width - characters;
2080  ENSURE_ALLOCATION (xsum (length, n));
2081  DCHAR_SET (result + length, ' ', n);
2082  length += n;
2083  }
2084 
2085 # if DCHAR_IS_UINT8_T
2086  {
2087  size_t n = arg_end - arg;
2088  ENSURE_ALLOCATION (xsum (length, n));
2089  DCHAR_CPY (result + length, arg, n);
2090  length += n;
2091  }
2092 # else
2093  { /* Convert. */
2094  DCHAR_T *converted = result + length;
2095  size_t converted_len = allocated - length;
2096 # if DCHAR_IS_TCHAR
2097  /* Convert from UTF-8 to locale encoding. */
2098  converted =
2099  u8_conv_to_encoding (locale_charset (),
2100  iconveh_question_mark,
2101  arg, arg_end - arg, NULL,
2102  converted, &converted_len);
2103 # else
2104  /* Convert from UTF-8 to UTF-16/UTF-32. */
2105  converted =
2106  U8_TO_DCHAR (arg, arg_end - arg,
2107  converted, &converted_len);
2108 # endif
2109  if (converted == NULL)
2110  {
2111  int saved_errno = errno;
2112  if (!(result == resultbuf || result == NULL))
2113  free (result);
2114  if (buf_malloced != NULL)
2115  free (buf_malloced);
2116  CLEANUP ();
2117  errno = saved_errno;
2118  return NULL;
2119  }
2120  if (converted != result + length)
2121  {
2122  ENSURE_ALLOCATION (xsum (length, converted_len));
2123  DCHAR_CPY (result + length, converted, converted_len);
2124  free (converted);
2125  }
2126  length += converted_len;
2127  }
2128 # endif
2129 
2130  if (has_width && width > characters
2131  && (dp->flags & FLAG_LEFT))
2132  {
2133  size_t n = width - characters;
2134  ENSURE_ALLOCATION (xsum (length, n));
2135  DCHAR_SET (result + length, ' ', n);
2136  length += n;
2137  }
2138  }
2139  break;
2140 
2141  case TYPE_U16_STRING:
2142  {
2143  const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string;
2144  const uint16_t *arg_end;
2145  size_t characters;
2146 
2147  if (has_precision)
2148  {
2149  /* Use only PRECISION characters, from the left. */
2150  arg_end = arg;
2151  characters = 0;
2152  for (; precision > 0; precision--)
2153  {
2154  int count = u16_strmblen (arg_end);
2155  if (count == 0)
2156  break;
2157  if (count < 0)
2158  {
2159  if (!(result == resultbuf || result == NULL))
2160  free (result);
2161  if (buf_malloced != NULL)
2162  free (buf_malloced);
2163  CLEANUP ();
2164  errno = EILSEQ;
2165  return NULL;
2166  }
2167  arg_end += count;
2168  characters++;
2169  }
2170  }
2171  else if (has_width)
2172  {
2173  /* Use the entire string, and count the number of
2174  characters. */
2175  arg_end = arg;
2176  characters = 0;
2177  for (;;)
2178  {
2179  int count = u16_strmblen (arg_end);
2180  if (count == 0)
2181  break;
2182  if (count < 0)
2183  {
2184  if (!(result == resultbuf || result == NULL))
2185  free (result);
2186  if (buf_malloced != NULL)
2187  free (buf_malloced);
2188  CLEANUP ();
2189  errno = EILSEQ;
2190  return NULL;
2191  }
2192  arg_end += count;
2193  characters++;
2194  }
2195  }
2196  else
2197  {
2198  /* Use the entire string. */
2199  arg_end = arg + u16_strlen (arg);
2200  /* The number of characters doesn't matter. */
2201  characters = 0;
2202  }
2203 
2204  if (has_width && width > characters
2205  && !(dp->flags & FLAG_LEFT))
2206  {
2207  size_t n = width - characters;
2208  ENSURE_ALLOCATION (xsum (length, n));
2209  DCHAR_SET (result + length, ' ', n);
2210  length += n;
2211  }
2212 
2213 # if DCHAR_IS_UINT16_T
2214  {
2215  size_t n = arg_end - arg;
2216  ENSURE_ALLOCATION (xsum (length, n));
2217  DCHAR_CPY (result + length, arg, n);
2218  length += n;
2219  }
2220 # else
2221  { /* Convert. */
2222  DCHAR_T *converted = result + length;
2223  size_t converted_len = allocated - length;
2224 # if DCHAR_IS_TCHAR
2225  /* Convert from UTF-16 to locale encoding. */
2226  converted =
2227  u16_conv_to_encoding (locale_charset (),
2228  iconveh_question_mark,
2229  arg, arg_end - arg, NULL,
2230  converted, &converted_len);
2231 # else
2232  /* Convert from UTF-16 to UTF-8/UTF-32. */
2233  converted =
2234  U16_TO_DCHAR (arg, arg_end - arg,
2235  converted, &converted_len);
2236 # endif
2237  if (converted == NULL)
2238  {
2239  int saved_errno = errno;
2240  if (!(result == resultbuf || result == NULL))
2241  free (result);
2242  if (buf_malloced != NULL)
2243  free (buf_malloced);
2244  CLEANUP ();
2245  errno = saved_errno;
2246  return NULL;
2247  }
2248  if (converted != result + length)
2249  {
2250  ENSURE_ALLOCATION (xsum (length, converted_len));
2251  DCHAR_CPY (result + length, converted, converted_len);
2252  free (converted);
2253  }
2254  length += converted_len;
2255  }
2256 # endif
2257 
2258  if (has_width && width > characters
2259  && (dp->flags & FLAG_LEFT))
2260  {
2261  size_t n = width - characters;
2262  ENSURE_ALLOCATION (xsum (length, n));
2263  DCHAR_SET (result + length, ' ', n);
2264  length += n;
2265  }
2266  }
2267  break;
2268 
2269  case TYPE_U32_STRING:
2270  {
2271  const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string;
2272  const uint32_t *arg_end;
2273  size_t characters;
2274 
2275  if (has_precision)
2276  {
2277  /* Use only PRECISION characters, from the left. */
2278  arg_end = arg;
2279  characters = 0;
2280  for (; precision > 0; precision--)
2281  {
2282  int count = u32_strmblen (arg_end);
2283  if (count == 0)
2284  break;
2285  if (count < 0)
2286  {
2287  if (!(result == resultbuf || result == NULL))
2288  free (result);
2289  if (buf_malloced != NULL)
2290  free (buf_malloced);
2291  CLEANUP ();
2292  errno = EILSEQ;
2293  return NULL;
2294  }
2295  arg_end += count;
2296  characters++;
2297  }
2298  }
2299  else if (has_width)
2300  {
2301  /* Use the entire string, and count the number of
2302  characters. */
2303  arg_end = arg;
2304  characters = 0;
2305  for (;;)
2306  {
2307  int count = u32_strmblen (arg_end);
2308  if (count == 0)
2309  break;
2310  if (count < 0)
2311  {
2312  if (!(result == resultbuf || result == NULL))
2313  free (result);
2314  if (buf_malloced != NULL)
2315  free (buf_malloced);
2316  CLEANUP ();
2317  errno = EILSEQ;
2318  return NULL;
2319  }
2320  arg_end += count;
2321  characters++;
2322  }
2323  }
2324  else
2325  {
2326  /* Use the entire string. */
2327  arg_end = arg + u32_strlen (arg);
2328  /* The number of characters doesn't matter. */
2329  characters = 0;
2330  }
2331 
2332  if (has_width && width > characters
2333  && !(dp->flags & FLAG_LEFT))
2334  {
2335  size_t n = width - characters;
2336  ENSURE_ALLOCATION (xsum (length, n));
2337  DCHAR_SET (result + length, ' ', n);
2338  length += n;
2339  }
2340 
2341 # if DCHAR_IS_UINT32_T
2342  {
2343  size_t n = arg_end - arg;
2344  ENSURE_ALLOCATION (xsum (length, n));
2345  DCHAR_CPY (result + length, arg, n);
2346  length += n;
2347  }
2348 # else
2349  { /* Convert. */
2350  DCHAR_T *converted = result + length;
2351  size_t converted_len = allocated - length;
2352 # if DCHAR_IS_TCHAR
2353  /* Convert from UTF-32 to locale encoding. */
2354  converted =
2355  u32_conv_to_encoding (locale_charset (),
2356  iconveh_question_mark,
2357  arg, arg_end - arg, NULL,
2358  converted, &converted_len);
2359 # else
2360  /* Convert from UTF-32 to UTF-8/UTF-16. */
2361  converted =
2362  U32_TO_DCHAR (arg, arg_end - arg,
2363  converted, &converted_len);
2364 # endif
2365  if (converted == NULL)
2366  {
2367  int saved_errno = errno;
2368  if (!(result == resultbuf || result == NULL))
2369  free (result);
2370  if (buf_malloced != NULL)
2371  free (buf_malloced);
2372  CLEANUP ();
2373  errno = saved_errno;
2374  return NULL;
2375  }
2376  if (converted != result + length)
2377  {
2378  ENSURE_ALLOCATION (xsum (length, converted_len));
2379  DCHAR_CPY (result + length, converted, converted_len);
2380  free (converted);
2381  }
2382  length += converted_len;
2383  }
2384 # endif
2385 
2386  if (has_width && width > characters
2387  && (dp->flags & FLAG_LEFT))
2388  {
2389  size_t n = width - characters;
2390  ENSURE_ALLOCATION (xsum (length, n));
2391  DCHAR_SET (result + length, ' ', n);
2392  length += n;
2393  }
2394  }
2395  break;
2396 
2397  default:
2398  abort ();
2399  }
2400  }
2401 #endif
2402 #if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
2403  else if (dp->conversion == 's'
2404 # if WIDE_CHAR_VERSION
2405  && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
2406 # else
2407  && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
2408 # endif
2409  )
2410  {
2411  /* The normal handling of the 's' directive below requires
2412  allocating a temporary buffer. The determination of its
2413  length (tmp_length), in the case when a precision is
2414  specified, below requires a conversion between a char[]
2415  string and a wchar_t[] wide string. It could be done, but
2416  we have no guarantee that the implementation of sprintf will
2417  use the exactly same algorithm. Without this guarantee, it
2418  is possible to have buffer overrun bugs. In order to avoid
2419  such bugs, we implement the entire processing of the 's'
2420  directive ourselves. */
2421  int flags = dp->flags;
2422  int has_width;
2423  size_t width;
2424  int has_precision;
2425  size_t precision;
2426 
2427  has_width = 0;
2428  width = 0;
2429  if (dp->width_start != dp->width_end)
2430  {
2431  if (dp->width_arg_index != ARG_NONE)
2432  {
2433  int arg;
2434 
2435  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2436  abort ();
2437  arg = a.arg[dp->width_arg_index].a.a_int;
2438  if (arg < 0)
2439  {
2440  /* "A negative field width is taken as a '-' flag
2441  followed by a positive field width." */
2442  flags |= FLAG_LEFT;
2443  width = (unsigned int) (-arg);
2444  }
2445  else
2446  width = arg;
2447  }
2448  else
2449  {
2450  const FCHAR_T *digitp = dp->width_start;
2451 
2452  do
2453  width = xsum (xtimes (width, 10), *digitp++ - '0');
2454  while (digitp != dp->width_end);
2455  }
2456  has_width = 1;
2457  }
2458 
2459  has_precision = 0;
2460  precision = 6;
2461  if (dp->precision_start != dp->precision_end)
2462  {
2463  if (dp->precision_arg_index != ARG_NONE)
2464  {
2465  int arg;
2466 
2467  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2468  abort ();
2469  arg = a.arg[dp->precision_arg_index].a.a_int;
2470  /* "A negative precision is taken as if the precision
2471  were omitted." */
2472  if (arg >= 0)
2473  {
2474  precision = arg;
2475  has_precision = 1;
2476  }
2477  }
2478  else
2479  {
2480  const FCHAR_T *digitp = dp->precision_start + 1;
2481 
2482  precision = 0;
2483  while (digitp != dp->precision_end)
2484  precision = xsum (xtimes (precision, 10), *digitp++ - '0');
2485  has_precision = 1;
2486  }
2487  }
2488 
2489 # if WIDE_CHAR_VERSION
2490  /* %s in vasnwprintf. See the specification of fwprintf. */
2491  {
2492  const char *arg = a.arg[dp->arg_index].a.a_string;
2493  const char *arg_end;
2494  size_t characters;
2495 
2496  if (has_precision)
2497  {
2498  /* Use only as many bytes as needed to produce PRECISION
2499  wide characters, from the left. */
2500 # if HAVE_MBRTOWC
2501  mbstate_t state;
2502  memset (&state, '\0', sizeof (mbstate_t));
2503 # endif
2504  arg_end = arg;
2505  characters = 0;
2506  for (; precision > 0; precision--)
2507  {
2508  int count;
2509 # if HAVE_MBRTOWC
2510  count = mbrlen (arg_end, MB_CUR_MAX, &state);
2511 # else
2512  count = mblen (arg_end, MB_CUR_MAX);
2513 # endif
2514  if (count == 0)
2515  /* Found the terminating NUL. */
2516  break;
2517  if (count < 0)
2518  {
2519  /* Invalid or incomplete multibyte character. */
2520  if (!(result == resultbuf || result == NULL))
2521  free (result);
2522  if (buf_malloced != NULL)
2523  free (buf_malloced);
2524  CLEANUP ();
2525  errno = EILSEQ;
2526  return NULL;
2527  }
2528  arg_end += count;
2529  characters++;
2530  }
2531  }
2532  else if (has_width)
2533  {
2534  /* Use the entire string, and count the number of wide
2535  characters. */
2536 # if HAVE_MBRTOWC
2537  mbstate_t state;
2538  memset (&state, '\0', sizeof (mbstate_t));
2539 # endif
2540  arg_end = arg;
2541  characters = 0;
2542  for (;;)
2543  {
2544  int count;
2545 # if HAVE_MBRTOWC
2546  count = mbrlen (arg_end, MB_CUR_MAX, &state);
2547 # else
2548  count = mblen (arg_end, MB_CUR_MAX);
2549 # endif
2550  if (count == 0)
2551  /* Found the terminating NUL. */
2552  break;
2553  if (count < 0)
2554  {
2555  /* Invalid or incomplete multibyte character. */
2556  if (!(result == resultbuf || result == NULL))
2557  free (result);
2558  if (buf_malloced != NULL)
2559  free (buf_malloced);
2560  CLEANUP ();
2561  errno = EILSEQ;
2562  return NULL;
2563  }
2564  arg_end += count;
2565  characters++;
2566  }
2567  }
2568  else
2569  {
2570  /* Use the entire string. */
2571  arg_end = arg + strlen (arg);
2572  /* The number of characters doesn't matter. */
2573  characters = 0;
2574  }
2575 
2576  if (has_width && width > characters
2577  && !(dp->flags & FLAG_LEFT))
2578  {
2579  size_t n = width - characters;
2580  ENSURE_ALLOCATION (xsum (length, n));
2581  DCHAR_SET (result + length, ' ', n);
2582  length += n;
2583  }
2584 
2585  if (has_precision || has_width)
2586  {
2587  /* We know the number of wide characters in advance. */
2588  size_t remaining;
2589 # if HAVE_MBRTOWC
2590  mbstate_t state;
2591  memset (&state, '\0', sizeof (mbstate_t));
2592 # endif
2593  ENSURE_ALLOCATION (xsum (length, characters));
2594  for (remaining = characters; remaining > 0; remaining--)
2595  {
2596  wchar_t wc;
2597  int count;
2598 # if HAVE_MBRTOWC
2599  count = mbrtowc (&wc, arg, arg_end - arg, &state);
2600 # else
2601  count = mbtowc (&wc, arg, arg_end - arg);
2602 # endif
2603  if (count <= 0)
2604  /* mbrtowc not consistent with mbrlen, or mbtowc
2605  not consistent with mblen. */
2606  abort ();
2607  result[length++] = wc;
2608  arg += count;
2609  }
2610  if (!(arg == arg_end))
2611  abort ();
2612  }
2613  else
2614  {
2615 # if HAVE_MBRTOWC
2616  mbstate_t state;
2617  memset (&state, '\0', sizeof (mbstate_t));
2618 # endif
2619  while (arg < arg_end)
2620  {
2621  wchar_t wc;
2622  int count;
2623 # if HAVE_MBRTOWC
2624  count = mbrtowc (&wc, arg, arg_end - arg, &state);
2625 # else
2626  count = mbtowc (&wc, arg, arg_end - arg);
2627 # endif
2628  if (count <= 0)
2629  /* mbrtowc not consistent with mbrlen, or mbtowc
2630  not consistent with mblen. */
2631  abort ();
2632  ENSURE_ALLOCATION (xsum (length, 1));
2633  result[length++] = wc;
2634  arg += count;
2635  }
2636  }
2637 
2638  if (has_width && width > characters
2639  && (dp->flags & FLAG_LEFT))
2640  {
2641  size_t n = width - characters;
2642  ENSURE_ALLOCATION (xsum (length, n));
2643  DCHAR_SET (result + length, ' ', n);
2644  length += n;
2645  }
2646  }
2647 # else
2648  /* %ls in vasnprintf. See the specification of fprintf. */
2649  {
2650  const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
2651  const wchar_t *arg_end;
2652  size_t characters;
2653 # if !DCHAR_IS_TCHAR
2654  /* This code assumes that TCHAR_T is 'char'. */
2655  verify (sizeof (TCHAR_T) == 1);
2656  TCHAR_T *tmpsrc;
2657  DCHAR_T *tmpdst;
2658  size_t tmpdst_len;
2659 # endif
2660  size_t w;
2661 
2662  if (has_precision)
2663  {
2664  /* Use only as many wide characters as needed to produce
2665  at most PRECISION bytes, from the left. */
2666 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2667  mbstate_t state;
2668  memset (&state, '\0', sizeof (mbstate_t));
2669 # endif
2670  arg_end = arg;
2671  characters = 0;
2672  while (precision > 0)
2673  {
2674  char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2675  int count;
2676 
2677  if (*arg_end == 0)
2678  /* Found the terminating null wide character. */
2679  break;
2680 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2681  count = wcrtomb (cbuf, *arg_end, &state);
2682 # else
2683  count = wctomb (cbuf, *arg_end);
2684 # endif
2685  if (count < 0)
2686  {
2687  /* Cannot convert. */
2688  if (!(result == resultbuf || result == NULL))
2689  free (result);
2690  if (buf_malloced != NULL)
2691  free (buf_malloced);
2692  CLEANUP ();
2693  errno = EILSEQ;
2694  return NULL;
2695  }
2696  if (precision < count)
2697  break;
2698  arg_end++;
2699  characters += count;
2700  precision -= count;
2701  }
2702  }
2703 # if DCHAR_IS_TCHAR
2704  else if (has_width)
2705 # else
2706  else
2707 # endif
2708  {
2709  /* Use the entire string, and count the number of
2710  bytes. */
2711 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2712  mbstate_t state;
2713  memset (&state, '\0', sizeof (mbstate_t));
2714 # endif
2715  arg_end = arg;
2716  characters = 0;
2717  for (;;)
2718  {
2719  char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2720  int count;
2721 
2722  if (*arg_end == 0)
2723  /* Found the terminating null wide character. */
2724  break;
2725 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2726  count = wcrtomb (cbuf, *arg_end, &state);
2727 # else
2728  count = wctomb (cbuf, *arg_end);
2729 # endif
2730  if (count < 0)
2731  {
2732  /* Cannot convert. */
2733  if (!(result == resultbuf || result == NULL))
2734  free (result);
2735  if (buf_malloced != NULL)
2736  free (buf_malloced);
2737  CLEANUP ();
2738  errno = EILSEQ;
2739  return NULL;
2740  }
2741  arg_end++;
2742  characters += count;
2743  }
2744  }
2745 # if DCHAR_IS_TCHAR
2746  else
2747  {
2748  /* Use the entire string. */
2749  arg_end = arg + local_wcslen (arg);
2750  /* The number of bytes doesn't matter. */
2751  characters = 0;
2752  }
2753 # endif
2754 
2755 # if !DCHAR_IS_TCHAR
2756  /* Convert the string into a piece of temporary memory. */
2757  tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
2758  if (tmpsrc == NULL)
2759  goto out_of_memory;
2760  {
2761  TCHAR_T *tmpptr = tmpsrc;
2762  size_t remaining;
2763 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2764  mbstate_t state;
2765  memset (&state, '\0', sizeof (mbstate_t));
2766 # endif
2767  for (remaining = characters; remaining > 0; )
2768  {
2769  char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2770  int count;
2771 
2772  if (*arg == 0)
2773  abort ();
2774 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2775  count = wcrtomb (cbuf, *arg, &state);
2776 # else
2777  count = wctomb (cbuf, *arg);
2778 # endif
2779  if (count <= 0)
2780  /* Inconsistency. */
2781  abort ();
2782  memcpy (tmpptr, cbuf, count);
2783  tmpptr += count;
2784  arg++;
2785  remaining -= count;
2786  }
2787  if (!(arg == arg_end))
2788  abort ();
2789  }
2790 
2791  /* Convert from TCHAR_T[] to DCHAR_T[]. */
2792  tmpdst =
2793  DCHAR_CONV_FROM_ENCODING (locale_charset (),
2794  iconveh_question_mark,
2795  tmpsrc, characters,
2796  NULL,
2797  NULL, &tmpdst_len);
2798  if (tmpdst == NULL)
2799  {
2800  int saved_errno = errno;
2801  free (tmpsrc);
2802  if (!(result == resultbuf || result == NULL))
2803  free (result);
2804  if (buf_malloced != NULL)
2805  free (buf_malloced);
2806  CLEANUP ();
2807  errno = saved_errno;
2808  return NULL;
2809  }
2810  free (tmpsrc);
2811 # endif
2812 
2813  if (has_width)
2814  {
2815 # if ENABLE_UNISTDIO
2816  /* Outside POSIX, it's preferable to compare the width
2817  against the number of _characters_ of the converted
2818  value. */
2819  w = DCHAR_MBSNLEN (result + length, characters);
2820 # else
2821  /* The width is compared against the number of _bytes_
2822  of the converted value, says POSIX. */
2823  w = characters;
2824 # endif
2825  }
2826  else
2827  /* w doesn't matter. */
2828  w = 0;
2829 
2830  if (has_width && width > w
2831  && !(dp->flags & FLAG_LEFT))
2832  {
2833  size_t n = width - w;
2834  ENSURE_ALLOCATION (xsum (length, n));
2835  DCHAR_SET (result + length, ' ', n);
2836  length += n;
2837  }
2838 
2839 # if DCHAR_IS_TCHAR
2840  if (has_precision || has_width)
2841  {
2842  /* We know the number of bytes in advance. */
2843  size_t remaining;
2844 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2845  mbstate_t state;
2846  memset (&state, '\0', sizeof (mbstate_t));
2847 # endif
2848  ENSURE_ALLOCATION (xsum (length, characters));
2849  for (remaining = characters; remaining > 0; )
2850  {
2851  char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2852  int count;
2853 
2854  if (*arg == 0)
2855  abort ();
2856 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2857  count = wcrtomb (cbuf, *arg, &state);
2858 # else
2859  count = wctomb (cbuf, *arg);
2860 # endif
2861  if (count <= 0)
2862  /* Inconsistency. */
2863  abort ();
2864  memcpy (result + length, cbuf, count);
2865  length += count;
2866  arg++;
2867  remaining -= count;
2868  }
2869  if (!(arg == arg_end))
2870  abort ();
2871  }
2872  else
2873  {
2874 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2875  mbstate_t state;
2876  memset (&state, '\0', sizeof (mbstate_t));
2877 # endif
2878  while (arg < arg_end)
2879  {
2880  char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
2881  int count;
2882 
2883  if (*arg == 0)
2884  abort ();
2885 # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
2886  count = wcrtomb (cbuf, *arg, &state);
2887 # else
2888  count = wctomb (cbuf, *arg);
2889 # endif
2890  if (count <= 0)
2891  {
2892  /* Cannot convert. */
2893  if (!(result == resultbuf || result == NULL))
2894  free (result);
2895  if (buf_malloced != NULL)
2896  free (buf_malloced);
2897  CLEANUP ();
2898  errno = EILSEQ;
2899  return NULL;
2900  }
2901  ENSURE_ALLOCATION (xsum (length, count));
2902  memcpy (result + length, cbuf, count);
2903  length += count;
2904  arg++;
2905  }
2906  }
2907 # else
2908  ENSURE_ALLOCATION (xsum (length, tmpdst_len));
2909  DCHAR_CPY (result + length, tmpdst, tmpdst_len);
2910  free (tmpdst);
2911  length += tmpdst_len;
2912 # endif
2913 
2914  if (has_width && width > w
2915  && (dp->flags & FLAG_LEFT))
2916  {
2917  size_t n = width - w;
2918  ENSURE_ALLOCATION (xsum (length, n));
2919  DCHAR_SET (result + length, ' ', n);
2920  length += n;
2921  }
2922  }
2923 # endif
2924  }
2925 #endif
2926 #if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
2927  else if ((dp->conversion == 'a' || dp->conversion == 'A')
2928 # if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
2929  && (0
2930 # if NEED_PRINTF_DOUBLE
2931  || a.arg[dp->arg_index].type == TYPE_DOUBLE
2932 # endif
2933 # if NEED_PRINTF_LONG_DOUBLE
2934  || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
2935 # endif
2936  )
2937 # endif
2938  )
2939  {
2940  arg_type type = a.arg[dp->arg_index].type;
2941  int flags = dp->flags;
2942  int has_width;
2943  size_t width;
2944  int has_precision;
2945  size_t precision;
2946  size_t tmp_length;
2947  DCHAR_T tmpbuf[700];
2948  DCHAR_T *tmp;
2949  DCHAR_T *pad_ptr;
2950  DCHAR_T *p;
2951 
2952  has_width = 0;
2953  width = 0;
2954  if (dp->width_start != dp->width_end)
2955  {
2956  if (dp->width_arg_index != ARG_NONE)
2957  {
2958  int arg;
2959 
2960  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
2961  abort ();
2962  arg = a.arg[dp->width_arg_index].a.a_int;
2963  if (arg < 0)
2964  {
2965  /* "A negative field width is taken as a '-' flag
2966  followed by a positive field width." */
2967  flags |= FLAG_LEFT;
2968  width = (unsigned int) (-arg);
2969  }
2970  else
2971  width = arg;
2972  }
2973  else
2974  {
2975  const FCHAR_T *digitp = dp->width_start;
2976 
2977  do
2978  width = xsum (xtimes (width, 10), *digitp++ - '0');
2979  while (digitp != dp->width_end);
2980  }
2981  has_width = 1;
2982  }
2983 
2984  has_precision = 0;
2985  precision = 0;
2986  if (dp->precision_start != dp->precision_end)
2987  {
2988  if (dp->precision_arg_index != ARG_NONE)
2989  {
2990  int arg;
2991 
2992  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
2993  abort ();
2994  arg = a.arg[dp->precision_arg_index].a.a_int;
2995  /* "A negative precision is taken as if the precision
2996  were omitted." */
2997  if (arg >= 0)
2998  {
2999  precision = arg;
3000  has_precision = 1;
3001  }
3002  }
3003  else
3004  {
3005  const FCHAR_T *digitp = dp->precision_start + 1;
3006 
3007  precision = 0;
3008  while (digitp != dp->precision_end)
3009  precision = xsum (xtimes (precision, 10), *digitp++ - '0');
3010  has_precision = 1;
3011  }
3012  }
3013 
3014  /* Allocate a temporary buffer of sufficient size. */
3015  if (type == TYPE_LONGDOUBLE)
3016  tmp_length =
3017  (unsigned int) ((LDBL_DIG + 1)
3018  * 0.831 /* decimal -> hexadecimal */
3019  )
3020  + 1; /* turn floor into ceil */
3021  else
3022  tmp_length =
3023  (unsigned int) ((DBL_DIG + 1)
3024  * 0.831 /* decimal -> hexadecimal */
3025  )
3026  + 1; /* turn floor into ceil */
3027  if (tmp_length < precision)
3028  tmp_length = precision;
3029  /* Account for sign, decimal point etc. */
3030  tmp_length = xsum (tmp_length, 12);
3031 
3032  if (tmp_length < width)
3033  tmp_length = width;
3034 
3035  tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
3036 
3037  if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
3038  tmp = tmpbuf;
3039  else
3040  {
3041  size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
3042 
3043  if (size_overflow_p (tmp_memsize))
3044  /* Overflow, would lead to out of memory. */
3045  goto out_of_memory;
3046  tmp = (DCHAR_T *) malloc (tmp_memsize);
3047  if (tmp == NULL)
3048  /* Out of memory. */
3049  goto out_of_memory;
3050  }
3051 
3052  pad_ptr = NULL;
3053  p = tmp;
3054  if (type == TYPE_LONGDOUBLE)
3055  {
3056 # if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
3057  long double arg = a.arg[dp->arg_index].a.a_longdouble;
3058 
3059  if (isnanl (arg))
3060  {
3061  if (dp->conversion == 'A')
3062  {
3063  *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
3064  }
3065  else
3066  {
3067  *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
3068  }
3069  }
3070  else
3071  {
3072  int sign = 0;
3073  DECL_LONG_DOUBLE_ROUNDING
3074 
3075  BEGIN_LONG_DOUBLE_ROUNDING ();
3076 
3077  if (signbit (arg)) /* arg < 0.0L or negative zero */
3078  {
3079  sign = -1;
3080  arg = -arg;
3081  }
3082 
3083  if (sign < 0)
3084  *p++ = '-';
3085  else if (flags & FLAG_SHOWSIGN)
3086  *p++ = '+';
3087  else if (flags & FLAG_SPACE)
3088  *p++ = ' ';
3089 
3090  if (arg > 0.0L && arg + arg == arg)
3091  {
3092  if (dp->conversion == 'A')
3093  {
3094  *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
3095  }
3096  else
3097  {
3098  *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
3099  }
3100  }
3101  else
3102  {
3103  int exponent;
3104  long double mantissa;
3105 
3106  if (arg > 0.0L)
3107  mantissa = printf_frexpl (arg, &exponent);
3108  else
3109  {
3110  exponent = 0;
3111  mantissa = 0.0L;
3112  }
3113 
3114  if (has_precision
3115  && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
3116  {
3117  /* Round the mantissa. */
3118  long double tail = mantissa;
3119  size_t q;
3120 
3121  for (q = precision; ; q--)
3122  {
3123  int digit = (int) tail;
3124  tail -= digit;
3125  if (q == 0)
3126  {
3127  if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
3128  tail = 1 - tail;
3129  else
3130  tail = - tail;
3131  break;
3132  }
3133  tail *= 16.0L;
3134  }
3135  if (tail != 0.0L)
3136  for (q = precision; q > 0; q--)
3137  tail *= 0.0625L;
3138  mantissa += tail;
3139  }
3140 
3141  *p++ = '0';
3142  *p++ = dp->conversion - 'A' + 'X';
3143  pad_ptr = p;
3144  {
3145  int digit;
3146 
3147  digit = (int) mantissa;
3148  mantissa -= digit;
3149  *p++ = '0' + digit;
3150  if ((flags & FLAG_ALT)
3151  || mantissa > 0.0L || precision > 0)
3152  {
3153  *p++ = decimal_point_char ();
3154  /* This loop terminates because we assume
3155  that FLT_RADIX is a power of 2. */
3156  while (mantissa > 0.0L)
3157  {
3158  mantissa *= 16.0L;
3159  digit = (int) mantissa;
3160  mantissa -= digit;
3161  *p++ = digit
3162  + (digit < 10
3163  ? '0'
3164  : dp->conversion - 10);
3165  if (precision > 0)
3166  precision--;
3167  }
3168  while (precision > 0)
3169  {
3170  *p++ = '0';
3171  precision--;
3172  }
3173  }
3174  }
3175  *p++ = dp->conversion - 'A' + 'P';
3176 # if WIDE_CHAR_VERSION
3177  {
3178  static const wchar_t decimal_format[] =
3179  { '%', '+', 'd', '\0' };
3180  SNPRINTF (p, 6 + 1, decimal_format, exponent);
3181  }
3182  while (*p != '\0')
3183  p++;
3184 # else
3185  if (sizeof (DCHAR_T) == 1)
3186  {
3187  sprintf ((char *) p, "%+d", exponent);
3188  while (*p != '\0')
3189  p++;
3190  }
3191  else
3192  {
3193  char expbuf[6 + 1];
3194  const char *ep;
3195  sprintf (expbuf, "%+d", exponent);
3196  for (ep = expbuf; (*p = *ep) != '\0'; ep++)
3197  p++;
3198  }
3199 # endif
3200  }
3201 
3202  END_LONG_DOUBLE_ROUNDING ();
3203  }
3204 # else
3205  abort ();
3206 # endif
3207  }
3208  else
3209  {
3210 # if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
3211  double arg = a.arg[dp->arg_index].a.a_double;
3212 
3213  if (isnand (arg))
3214  {
3215  if (dp->conversion == 'A')
3216  {
3217  *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
3218  }
3219  else
3220  {
3221  *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
3222  }
3223  }
3224  else
3225  {
3226  int sign = 0;
3227 
3228  if (signbit (arg)) /* arg < 0.0 or negative zero */
3229  {
3230  sign = -1;
3231  arg = -arg;
3232  }
3233 
3234  if (sign < 0)
3235  *p++ = '-';
3236  else if (flags & FLAG_SHOWSIGN)
3237  *p++ = '+';
3238  else if (flags & FLAG_SPACE)
3239  *p++ = ' ';
3240 
3241  if (arg > 0.0 && arg + arg == arg)
3242  {
3243  if (dp->conversion == 'A')
3244  {
3245  *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
3246  }
3247  else
3248  {
3249  *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
3250  }
3251  }
3252  else
3253  {
3254  int exponent;
3255  double mantissa;
3256 
3257  if (arg > 0.0)
3258  mantissa = printf_frexp (arg, &exponent);
3259  else
3260  {
3261  exponent = 0;
3262  mantissa = 0.0;
3263  }
3264 
3265  if (has_precision
3266  && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
3267  {
3268  /* Round the mantissa. */
3269  double tail = mantissa;
3270  size_t q;
3271 
3272  for (q = precision; ; q--)
3273  {
3274  int digit = (int) tail;
3275  tail -= digit;
3276  if (q == 0)
3277  {
3278  if (digit & 1 ? tail >= 0.5 : tail > 0.5)
3279  tail = 1 - tail;
3280  else
3281  tail = - tail;
3282  break;
3283  }
3284  tail *= 16.0;
3285  }
3286  if (tail != 0.0)
3287  for (q = precision; q > 0; q--)
3288  tail *= 0.0625;
3289  mantissa += tail;
3290  }
3291 
3292  *p++ = '0';
3293  *p++ = dp->conversion - 'A' + 'X';
3294  pad_ptr = p;
3295  {
3296  int digit;
3297 
3298  digit = (int) mantissa;
3299  mantissa -= digit;
3300  *p++ = '0' + digit;
3301  if ((flags & FLAG_ALT)
3302  || mantissa > 0.0 || precision > 0)
3303  {
3304  *p++ = decimal_point_char ();
3305  /* This loop terminates because we assume
3306  that FLT_RADIX is a power of 2. */
3307  while (mantissa > 0.0)
3308  {
3309  mantissa *= 16.0;
3310  digit = (int) mantissa;
3311  mantissa -= digit;
3312  *p++ = digit
3313  + (digit < 10
3314  ? '0'
3315  : dp->conversion - 10);
3316  if (precision > 0)
3317  precision--;
3318  }
3319  while (precision > 0)
3320  {
3321  *p++ = '0';
3322  precision--;
3323  }
3324  }
3325  }
3326  *p++ = dp->conversion - 'A' + 'P';
3327 # if WIDE_CHAR_VERSION
3328  {
3329  static const wchar_t decimal_format[] =
3330  { '%', '+', 'd', '\0' };
3331  SNPRINTF (p, 6 + 1, decimal_format, exponent);
3332  }
3333  while (*p != '\0')
3334  p++;
3335 # else
3336  if (sizeof (DCHAR_T) == 1)
3337  {
3338  sprintf ((char *) p, "%+d", exponent);
3339  while (*p != '\0')
3340  p++;
3341  }
3342  else
3343  {
3344  char expbuf[6 + 1];
3345  const char *ep;
3346  sprintf (expbuf, "%+d", exponent);
3347  for (ep = expbuf; (*p = *ep) != '\0'; ep++)
3348  p++;
3349  }
3350 # endif
3351  }
3352  }
3353 # else
3354  abort ();
3355 # endif
3356  }
3357  /* The generated string now extends from tmp to p, with the
3358  zero padding insertion point being at pad_ptr. */
3359  if (has_width && p - tmp < width)
3360  {
3361  size_t pad = width - (p - tmp);
3362  DCHAR_T *end = p + pad;
3363 
3364  if (flags & FLAG_LEFT)
3365  {
3366  /* Pad with spaces on the right. */
3367  for (; pad > 0; pad--)
3368  *p++ = ' ';
3369  }
3370  else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
3371  {
3372  /* Pad with zeroes. */
3373  DCHAR_T *q = end;
3374 
3375  while (p > pad_ptr)
3376  *--q = *--p;
3377  for (; pad > 0; pad--)
3378  *p++ = '0';
3379  }
3380  else
3381  {
3382  /* Pad with spaces on the left. */
3383  DCHAR_T *q = end;
3384 
3385  while (p > tmp)
3386  *--q = *--p;
3387  for (; pad > 0; pad--)
3388  *p++ = ' ';
3389  }
3390 
3391  p = end;
3392  }
3393 
3394  {
3395  size_t count = p - tmp;
3396 
3397  if (count >= tmp_length)
3398  /* tmp_length was incorrectly calculated - fix the
3399  code above! */
3400  abort ();
3401 
3402  /* Make room for the result. */
3403  if (count >= allocated - length)
3404  {
3405  size_t n = xsum (length, count);
3406 
3407  ENSURE_ALLOCATION (n);
3408  }
3409 
3410  /* Append the result. */
3411  memcpy (result + length, tmp, count * sizeof (DCHAR_T));
3412  if (tmp != tmpbuf)
3413  free (tmp);
3414  length += count;
3415  }
3416  }
3417 #endif
3418 #if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
3419  else if ((dp->conversion == 'f' || dp->conversion == 'F'
3420  || dp->conversion == 'e' || dp->conversion == 'E'
3421  || dp->conversion == 'g' || dp->conversion == 'G'
3422  || dp->conversion == 'a' || dp->conversion == 'A')
3423  && (0
3424 # if NEED_PRINTF_DOUBLE
3425  || a.arg[dp->arg_index].type == TYPE_DOUBLE
3426 # elif NEED_PRINTF_INFINITE_DOUBLE
3427  || (a.arg[dp->arg_index].type == TYPE_DOUBLE
3428  /* The systems (mingw) which produce wrong output
3429  for Inf, -Inf, and NaN also do so for -0.0.
3430  Therefore we treat this case here as well. */
3431  && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
3432 # endif
3433 # if NEED_PRINTF_LONG_DOUBLE
3434  || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
3435 # elif NEED_PRINTF_INFINITE_LONG_DOUBLE
3436  || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
3437  /* Some systems produce wrong output for Inf,
3438  -Inf, and NaN. Some systems in this category
3439  (IRIX 5.3) also do so for -0.0. Therefore we
3440  treat this case here as well. */
3441  && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
3442 # endif
3443  ))
3444  {
3445 # if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
3446  arg_type type = a.arg[dp->arg_index].type;
3447 # endif
3448  int flags = dp->flags;
3449  int has_width;
3450  size_t width;
3451  int has_precision;
3452  size_t precision;
3453  size_t tmp_length;
3454  DCHAR_T tmpbuf[700];
3455  DCHAR_T *tmp;
3456  DCHAR_T *pad_ptr;
3457  DCHAR_T *p;
3458 
3459  has_width = 0;
3460  width = 0;
3461  if (dp->width_start != dp->width_end)
3462  {
3463  if (dp->width_arg_index != ARG_NONE)
3464  {
3465  int arg;
3466 
3467  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
3468  abort ();
3469  arg = a.arg[dp->width_arg_index].a.a_int;
3470  if (arg < 0)
3471  {
3472  /* "A negative field width is taken as a '-' flag
3473  followed by a positive field width." */
3474  flags |= FLAG_LEFT;
3475  width = (unsigned int) (-arg);
3476  }
3477  else
3478  width = arg;
3479  }
3480  else
3481  {
3482  const FCHAR_T *digitp = dp->width_start;
3483 
3484  do
3485  width = xsum (xtimes (width, 10), *digitp++ - '0');
3486  while (digitp != dp->width_end);
3487  }
3488  has_width = 1;
3489  }
3490 
3491  has_precision = 0;
3492  precision = 0;
3493  if (dp->precision_start != dp->precision_end)
3494  {
3495  if (dp->precision_arg_index != ARG_NONE)
3496  {
3497  int arg;
3498 
3499  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
3500  abort ();
3501  arg = a.arg[dp->precision_arg_index].a.a_int;
3502  /* "A negative precision is taken as if the precision
3503  were omitted." */
3504  if (arg >= 0)
3505  {
3506  precision = arg;
3507  has_precision = 1;
3508  }
3509  }
3510  else
3511  {
3512  const FCHAR_T *digitp = dp->precision_start + 1;
3513 
3514  precision = 0;
3515  while (digitp != dp->precision_end)
3516  precision = xsum (xtimes (precision, 10), *digitp++ - '0');
3517  has_precision = 1;
3518  }
3519  }
3520 
3521  /* POSIX specifies the default precision to be 6 for %f, %F,
3522  %e, %E, but not for %g, %G. Implementations appear to use
3523  the same default precision also for %g, %G. But for %a, %A,
3524  the default precision is 0. */
3525  if (!has_precision)
3526  if (!(dp->conversion == 'a' || dp->conversion == 'A'))
3527  precision = 6;
3528 
3529  /* Allocate a temporary buffer of sufficient size. */
3530 # if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
3531  tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
3532 # elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
3533  tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
3534 # elif NEED_PRINTF_LONG_DOUBLE
3535  tmp_length = LDBL_DIG + 1;
3536 # elif NEED_PRINTF_DOUBLE
3537  tmp_length = DBL_DIG + 1;
3538 # else
3539  tmp_length = 0;
3540 # endif
3541  if (tmp_length < precision)
3542  tmp_length = precision;
3543 # if NEED_PRINTF_LONG_DOUBLE
3544 # if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
3545  if (type == TYPE_LONGDOUBLE)
3546 # endif
3547  if (dp->conversion == 'f' || dp->conversion == 'F')
3548  {
3549  long double arg = a.arg[dp->arg_index].a.a_longdouble;
3550  if (!(isnanl (arg) || arg + arg == arg))
3551  {
3552  /* arg is finite and nonzero. */
3553  int exponent = floorlog10l (arg < 0 ? -arg : arg);
3554  if (exponent >= 0 && tmp_length < exponent + precision)
3555  tmp_length = exponent + precision;
3556  }
3557  }
3558 # endif
3559 # if NEED_PRINTF_DOUBLE
3560 # if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
3561  if (type == TYPE_DOUBLE)
3562 # endif
3563  if (dp->conversion == 'f' || dp->conversion == 'F')
3564  {
3565  double arg = a.arg[dp->arg_index].a.a_double;
3566  if (!(isnand (arg) || arg + arg == arg))
3567  {
3568  /* arg is finite and nonzero. */
3569  int exponent = floorlog10 (arg < 0 ? -arg : arg);
3570  if (exponent >= 0 && tmp_length < exponent + precision)
3571  tmp_length = exponent + precision;
3572  }
3573  }
3574 # endif
3575  /* Account for sign, decimal point etc. */
3576  tmp_length = xsum (tmp_length, 12);
3577 
3578  if (tmp_length < width)
3579  tmp_length = width;
3580 
3581  tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
3582 
3583  if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
3584  tmp = tmpbuf;
3585  else
3586  {
3587  size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
3588 
3589  if (size_overflow_p (tmp_memsize))
3590  /* Overflow, would lead to out of memory. */
3591  goto out_of_memory;
3592  tmp = (DCHAR_T *) malloc (tmp_memsize);
3593  if (tmp == NULL)
3594  /* Out of memory. */
3595  goto out_of_memory;
3596  }
3597 
3598  pad_ptr = NULL;
3599  p = tmp;
3600 
3601 # if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
3602 # if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
3603  if (type == TYPE_LONGDOUBLE)
3604 # endif
3605  {
3606  long double arg = a.arg[dp->arg_index].a.a_longdouble;
3607 
3608  if (isnanl (arg))
3609  {
3610  if (dp->conversion >= 'A' && dp->conversion <= 'Z')
3611  {
3612  *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
3613  }
3614  else
3615  {
3616  *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
3617  }
3618  }
3619  else
3620  {
3621  int sign = 0;
3622  DECL_LONG_DOUBLE_ROUNDING
3623 
3624  BEGIN_LONG_DOUBLE_ROUNDING ();
3625 
3626  if (signbit (arg)) /* arg < 0.0L or negative zero */
3627  {
3628  sign = -1;
3629  arg = -arg;
3630  }
3631 
3632  if (sign < 0)
3633  *p++ = '-';
3634  else if (flags & FLAG_SHOWSIGN)
3635  *p++ = '+';
3636  else if (flags & FLAG_SPACE)
3637  *p++ = ' ';
3638 
3639  if (arg > 0.0L && arg + arg == arg)
3640  {
3641  if (dp->conversion >= 'A' && dp->conversion <= 'Z')
3642  {
3643  *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
3644  }
3645  else
3646  {
3647  *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
3648  }
3649  }
3650  else
3651  {
3652 # if NEED_PRINTF_LONG_DOUBLE
3653  pad_ptr = p;
3654 
3655  if (dp->conversion == 'f' || dp->conversion == 'F')
3656  {
3657  char *digits;
3658  size_t ndigits;
3659 
3660  digits =
3661  scale10_round_decimal_long_double (arg, precision);
3662  if (digits == NULL)
3663  {
3664  END_LONG_DOUBLE_ROUNDING ();
3665  goto out_of_memory;
3666  }
3667  ndigits = strlen (digits);
3668 
3669  if (ndigits > precision)
3670  do
3671  {
3672  --ndigits;
3673  *p++ = digits[ndigits];
3674  }
3675  while (ndigits > precision);
3676  else
3677  *p++ = '0';
3678  /* Here ndigits <= precision. */
3679  if ((flags & FLAG_ALT) || precision > 0)
3680  {
3681  *p++ = decimal_point_char ();
3682  for (; precision > ndigits; precision--)
3683  *p++ = '0';
3684  while (ndigits > 0)
3685  {
3686  --ndigits;
3687  *p++ = digits[ndigits];
3688  }
3689  }
3690 
3691  free (digits);
3692  }
3693  else if (dp->conversion == 'e' || dp->conversion == 'E')
3694  {
3695  int exponent;
3696 
3697  if (arg == 0.0L)
3698  {
3699  exponent = 0;
3700  *p++ = '0';
3701  if ((flags & FLAG_ALT) || precision > 0)
3702  {
3703  *p++ = decimal_point_char ();
3704  for (; precision > 0; precision--)
3705  *p++ = '0';
3706  }
3707  }
3708  else
3709  {
3710  /* arg > 0.0L. */
3711  int adjusted;
3712  char *digits;
3713  size_t ndigits;
3714 
3715  exponent = floorlog10l (arg);
3716  adjusted = 0;
3717  for (;;)
3718  {
3719  digits =
3720  scale10_round_decimal_long_double (arg,
3721  (int)precision - exponent);
3722  if (digits == NULL)
3723  {
3724  END_LONG_DOUBLE_ROUNDING ();
3725  goto out_of_memory;
3726  }
3727  ndigits = strlen (digits);
3728 
3729  if (ndigits == precision + 1)
3730  break;
3731  if (ndigits < precision
3732  || ndigits > precision + 2)
3733  /* The exponent was not guessed
3734  precisely enough. */
3735  abort ();
3736  if (adjusted)
3737  /* None of two values of exponent is
3738  the right one. Prevent an endless
3739  loop. */
3740  abort ();
3741  free (digits);
3742  if (ndigits == precision)
3743  exponent -= 1;
3744  else
3745  exponent += 1;
3746  adjusted = 1;
3747  }
3748  /* Here ndigits = precision+1. */
3749  if (is_borderline (digits, precision))
3750  {
3751  /* Maybe the exponent guess was too high
3752  and a smaller exponent can be reached
3753  by turning a 10...0 into 9...9x. */
3754  char *digits2 =
3755  scale10_round_decimal_long_double (arg,
3756  (int)precision - exponent + 1);
3757  if (digits2 == NULL)
3758  {
3759  free (digits);
3760  END_LONG_DOUBLE_ROUNDING ();
3761  goto out_of_memory;
3762  }
3763  if (strlen (digits2) == precision + 1)
3764  {
3765  free (digits);
3766  digits = digits2;
3767  exponent -= 1;
3768  }
3769  else
3770  free (digits2);
3771  }
3772  /* Here ndigits = precision+1. */
3773 
3774  *p++ = digits[--ndigits];
3775  if ((flags & FLAG_ALT) || precision > 0)
3776  {
3777  *p++ = decimal_point_char ();
3778  while (ndigits > 0)
3779  {
3780  --ndigits;
3781  *p++ = digits[ndigits];
3782  }
3783  }
3784 
3785  free (digits);
3786  }
3787 
3788  *p++ = dp->conversion; /* 'e' or 'E' */
3789 # if WIDE_CHAR_VERSION
3790  {
3791  static const wchar_t decimal_format[] =
3792  { '%', '+', '.', '2', 'd', '\0' };
3793  SNPRINTF (p, 6 + 1, decimal_format, exponent);
3794  }
3795  while (*p != '\0')
3796  p++;
3797 # else
3798  if (sizeof (DCHAR_T) == 1)
3799  {
3800  sprintf ((char *) p, "%+.2d", exponent);
3801  while (*p != '\0')
3802  p++;
3803  }
3804  else
3805  {
3806  char expbuf[6 + 1];
3807  const char *ep;
3808  sprintf (expbuf, "%+.2d", exponent);
3809  for (ep = expbuf; (*p = *ep) != '\0'; ep++)
3810  p++;
3811  }
3812 # endif
3813  }
3814  else if (dp->conversion == 'g' || dp->conversion == 'G')
3815  {
3816  if (precision == 0)
3817  precision = 1;
3818  /* precision >= 1. */
3819 
3820  if (arg == 0.0L)
3821  /* The exponent is 0, >= -4, < precision.
3822  Use fixed-point notation. */
3823  {
3824  size_t ndigits = precision;
3825  /* Number of trailing zeroes that have to be
3826  dropped. */
3827  size_t nzeroes =
3828  (flags & FLAG_ALT ? 0 : precision - 1);
3829 
3830  --ndigits;
3831  *p++ = '0';
3832  if ((flags & FLAG_ALT) || ndigits > nzeroes)
3833  {
3834  *p++ = decimal_point_char ();
3835  while (ndigits > nzeroes)
3836  {
3837  --ndigits;
3838  *p++ = '0';
3839  }
3840  }
3841  }
3842  else
3843  {
3844  /* arg > 0.0L. */
3845  int exponent;
3846  int adjusted;
3847  char *digits;
3848  size_t ndigits;
3849  size_t nzeroes;
3850 
3851  exponent = floorlog10l (arg);
3852  adjusted = 0;
3853  for (;;)
3854  {
3855  digits =
3856  scale10_round_decimal_long_double (arg,
3857  (int)(precision - 1) - exponent);
3858  if (digits == NULL)
3859  {
3860  END_LONG_DOUBLE_ROUNDING ();
3861  goto out_of_memory;
3862  }
3863  ndigits = strlen (digits);
3864 
3865  if (ndigits == precision)
3866  break;
3867  if (ndigits < precision - 1
3868  || ndigits > precision + 1)
3869  /* The exponent was not guessed
3870  precisely enough. */
3871  abort ();
3872  if (adjusted)
3873  /* None of two values of exponent is
3874  the right one. Prevent an endless
3875  loop. */
3876  abort ();
3877  free (digits);
3878  if (ndigits < precision)
3879  exponent -= 1;
3880  else
3881  exponent += 1;
3882  adjusted = 1;
3883  }
3884  /* Here ndigits = precision. */
3885  if (is_borderline (digits, precision - 1))
3886  {
3887  /* Maybe the exponent guess was too high
3888  and a smaller exponent can be reached
3889  by turning a 10...0 into 9...9x. */
3890  char *digits2 =
3891  scale10_round_decimal_long_double (arg,
3892  (int)(precision - 1) - exponent + 1);
3893  if (digits2 == NULL)
3894  {
3895  free (digits);
3896  END_LONG_DOUBLE_ROUNDING ();
3897  goto out_of_memory;
3898  }
3899  if (strlen (digits2) == precision)
3900  {
3901  free (digits);
3902  digits = digits2;
3903  exponent -= 1;
3904  }
3905  else
3906  free (digits2);
3907  }
3908  /* Here ndigits = precision. */
3909 
3910  /* Determine the number of trailing zeroes
3911  that have to be dropped. */
3912  nzeroes = 0;
3913  if ((flags & FLAG_ALT) == 0)
3914  while (nzeroes < ndigits
3915  && digits[nzeroes] == '0')
3916  nzeroes++;
3917 
3918  /* The exponent is now determined. */
3919  if (exponent >= -4
3920  && exponent < (long)precision)
3921  {
3922  /* Fixed-point notation:
3923  max(exponent,0)+1 digits, then the
3924  decimal point, then the remaining
3925  digits without trailing zeroes. */
3926  if (exponent >= 0)
3927  {
3928  size_t count = exponent + 1;
3929  /* Note: count <= precision = ndigits. */
3930  for (; count > 0; count--)
3931  *p++ = digits[--ndigits];
3932  if ((flags & FLAG_ALT) || ndigits > nzeroes)
3933  {
3934  *p++ = decimal_point_char ();
3935  while (ndigits > nzeroes)
3936  {
3937  --ndigits;
3938  *p++ = digits[ndigits];
3939  }
3940  }
3941  }
3942  else
3943  {
3944  size_t count = -exponent - 1;
3945  *p++ = '0';
3946  *p++ = decimal_point_char ();
3947  for (; count > 0; count--)
3948  *p++ = '0';
3949  while (ndigits > nzeroes)
3950  {
3951  --ndigits;
3952  *p++ = digits[ndigits];
3953  }
3954  }
3955  }
3956  else
3957  {
3958  /* Exponential notation. */
3959  *p++ = digits[--ndigits];
3960  if ((flags & FLAG_ALT) || ndigits > nzeroes)
3961  {
3962  *p++ = decimal_point_char ();
3963  while (ndigits > nzeroes)
3964  {
3965  --ndigits;
3966  *p++ = digits[ndigits];
3967  }
3968  }
3969  *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
3970 # if WIDE_CHAR_VERSION
3971  {
3972  static const wchar_t decimal_format[] =
3973  { '%', '+', '.', '2', 'd', '\0' };
3974  SNPRINTF (p, 6 + 1, decimal_format, exponent);
3975  }
3976  while (*p != '\0')
3977  p++;
3978 # else
3979  if (sizeof (DCHAR_T) == 1)
3980  {
3981  sprintf ((char *) p, "%+.2d", exponent);
3982  while (*p != '\0')
3983  p++;
3984  }
3985  else
3986  {
3987  char expbuf[6 + 1];
3988  const char *ep;
3989  sprintf (expbuf, "%+.2d", exponent);
3990  for (ep = expbuf; (*p = *ep) != '\0'; ep++)
3991  p++;
3992  }
3993 # endif
3994  }
3995 
3996  free (digits);
3997  }
3998  }
3999  else
4000  abort ();
4001 # else
4002  /* arg is finite. */
4003  if (!(arg == 0.0L))
4004  abort ();
4005 
4006  pad_ptr = p;
4007 
4008  if (dp->conversion == 'f' || dp->conversion == 'F')
4009  {
4010  *p++ = '0';
4011  if ((flags & FLAG_ALT) || precision > 0)
4012  {
4013  *p++ = decimal_point_char ();
4014  for (; precision > 0; precision--)
4015  *p++ = '0';
4016  }
4017  }
4018  else if (dp->conversion == 'e' || dp->conversion == 'E')
4019  {
4020  *p++ = '0';
4021  if ((flags & FLAG_ALT) || precision > 0)
4022  {
4023  *p++ = decimal_point_char ();
4024  for (; precision > 0; precision--)
4025  *p++ = '0';
4026  }
4027  *p++ = dp->conversion; /* 'e' or 'E' */
4028  *p++ = '+';
4029  *p++ = '0';
4030  *p++ = '0';
4031  }
4032  else if (dp->conversion == 'g' || dp->conversion == 'G')
4033  {
4034  *p++ = '0';
4035  if (flags & FLAG_ALT)
4036  {
4037  size_t ndigits =
4038  (precision > 0 ? precision - 1 : 0);
4039  *p++ = decimal_point_char ();
4040  for (; ndigits > 0; --ndigits)
4041  *p++ = '0';
4042  }
4043  }
4044  else if (dp->conversion == 'a' || dp->conversion == 'A')
4045  {
4046  *p++ = '0';
4047  *p++ = dp->conversion - 'A' + 'X';
4048  pad_ptr = p;
4049  *p++ = '0';
4050  if ((flags & FLAG_ALT) || precision > 0)
4051  {
4052  *p++ = decimal_point_char ();
4053  for (; precision > 0; precision--)
4054  *p++ = '0';
4055  }
4056  *p++ = dp->conversion - 'A' + 'P';
4057  *p++ = '+';
4058  *p++ = '0';
4059  }
4060  else
4061  abort ();
4062 # endif
4063  }
4064 
4065  END_LONG_DOUBLE_ROUNDING ();
4066  }
4067  }
4068 # if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
4069  else
4070 # endif
4071 # endif
4072 # if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
4073  {
4074  double arg = a.arg[dp->arg_index].a.a_double;
4075 
4076  if (isnand (arg))
4077  {
4078  if (dp->conversion >= 'A' && dp->conversion <= 'Z')
4079  {
4080  *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
4081  }
4082  else
4083  {
4084  *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
4085  }
4086  }
4087  else
4088  {
4089  int sign = 0;
4090 
4091  if (signbit (arg)) /* arg < 0.0 or negative zero */
4092  {
4093  sign = -1;
4094  arg = -arg;
4095  }
4096 
4097  if (sign < 0)
4098  *p++ = '-';
4099  else if (flags & FLAG_SHOWSIGN)
4100  *p++ = '+';
4101  else if (flags & FLAG_SPACE)
4102  *p++ = ' ';
4103 
4104  if (arg > 0.0 && arg + arg == arg)
4105  {
4106  if (dp->conversion >= 'A' && dp->conversion <= 'Z')
4107  {
4108  *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
4109  }
4110  else
4111  {
4112  *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
4113  }
4114  }
4115  else
4116  {
4117 # if NEED_PRINTF_DOUBLE
4118  pad_ptr = p;
4119 
4120  if (dp->conversion == 'f' || dp->conversion == 'F')
4121  {
4122  char *digits;
4123  size_t ndigits;
4124 
4125  digits =
4126  scale10_round_decimal_double (arg, precision);
4127  if (digits == NULL)
4128  goto out_of_memory;
4129  ndigits = strlen (digits);
4130 
4131  if (ndigits > precision)
4132  do
4133  {
4134  --ndigits;
4135  *p++ = digits[ndigits];
4136  }
4137  while (ndigits > precision);
4138  else
4139  *p++ = '0';
4140  /* Here ndigits <= precision. */
4141  if ((flags & FLAG_ALT) || precision > 0)
4142  {
4143  *p++ = decimal_point_char ();
4144  for (; precision > ndigits; precision--)
4145  *p++ = '0';
4146  while (ndigits > 0)
4147  {
4148  --ndigits;
4149  *p++ = digits[ndigits];
4150  }
4151  }
4152 
4153  free (digits);
4154  }
4155  else if (dp->conversion == 'e' || dp->conversion == 'E')
4156  {
4157  int exponent;
4158 
4159  if (arg == 0.0)
4160  {
4161  exponent = 0;
4162  *p++ = '0';
4163  if ((flags & FLAG_ALT) || precision > 0)
4164  {
4165  *p++ = decimal_point_char ();
4166  for (; precision > 0; precision--)
4167  *p++ = '0';
4168  }
4169  }
4170  else
4171  {
4172  /* arg > 0.0. */
4173  int adjusted;
4174  char *digits;
4175  size_t ndigits;
4176 
4177  exponent = floorlog10 (arg);
4178  adjusted = 0;
4179  for (;;)
4180  {
4181  digits =
4182  scale10_round_decimal_double (arg,
4183  (int)precision - exponent);
4184  if (digits == NULL)
4185  goto out_of_memory;
4186  ndigits = strlen (digits);
4187 
4188  if (ndigits == precision + 1)
4189  break;
4190  if (ndigits < precision
4191  || ndigits > precision + 2)
4192  /* The exponent was not guessed
4193  precisely enough. */
4194  abort ();
4195  if (adjusted)
4196  /* None of two values of exponent is
4197  the right one. Prevent an endless
4198  loop. */
4199  abort ();
4200  free (digits);
4201  if (ndigits == precision)
4202  exponent -= 1;
4203  else
4204  exponent += 1;
4205  adjusted = 1;
4206  }
4207  /* Here ndigits = precision+1. */
4208  if (is_borderline (digits, precision))
4209  {
4210  /* Maybe the exponent guess was too high
4211  and a smaller exponent can be reached
4212  by turning a 10...0 into 9...9x. */
4213  char *digits2 =
4214  scale10_round_decimal_double (arg,
4215  (int)precision - exponent + 1);
4216  if (digits2 == NULL)
4217  {
4218  free (digits);
4219  goto out_of_memory;
4220  }
4221  if (strlen (digits2) == precision + 1)
4222  {
4223  free (digits);
4224  digits = digits2;
4225  exponent -= 1;
4226  }
4227  else
4228  free (digits2);
4229  }
4230  /* Here ndigits = precision+1. */
4231 
4232  *p++ = digits[--ndigits];
4233  if ((flags & FLAG_ALT) || precision > 0)
4234  {
4235  *p++ = decimal_point_char ();
4236  while (ndigits > 0)
4237  {
4238  --ndigits;
4239  *p++ = digits[ndigits];
4240  }
4241  }
4242 
4243  free (digits);
4244  }
4245 
4246  *p++ = dp->conversion; /* 'e' or 'E' */
4247 # if WIDE_CHAR_VERSION
4248  {
4249  static const wchar_t decimal_format[] =
4250  /* Produce the same number of exponent digits
4251  as the native printf implementation. */
4252 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4253  { '%', '+', '.', '3', 'd', '\0' };
4254 # else
4255  { '%', '+', '.', '2', 'd', '\0' };
4256 # endif
4257  SNPRINTF (p, 6 + 1, decimal_format, exponent);
4258  }
4259  while (*p != '\0')
4260  p++;
4261 # else
4262  {
4263  static const char decimal_format[] =
4264  /* Produce the same number of exponent digits
4265  as the native printf implementation. */
4266 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4267  "%+.3d";
4268 # else
4269  "%+.2d";
4270 # endif
4271  if (sizeof (DCHAR_T) == 1)
4272  {
4273  sprintf ((char *) p, decimal_format, exponent);
4274  while (*p != '\0')
4275  p++;
4276  }
4277  else
4278  {
4279  char expbuf[6 + 1];
4280  const char *ep;
4281  sprintf (expbuf, decimal_format, exponent);
4282  for (ep = expbuf; (*p = *ep) != '\0'; ep++)
4283  p++;
4284  }
4285  }
4286 # endif
4287  }
4288  else if (dp->conversion == 'g' || dp->conversion == 'G')
4289  {
4290  if (precision == 0)
4291  precision = 1;
4292  /* precision >= 1. */
4293 
4294  if (arg == 0.0)
4295  /* The exponent is 0, >= -4, < precision.
4296  Use fixed-point notation. */
4297  {
4298  size_t ndigits = precision;
4299  /* Number of trailing zeroes that have to be
4300  dropped. */
4301  size_t nzeroes =
4302  (flags & FLAG_ALT ? 0 : precision - 1);
4303 
4304  --ndigits;
4305  *p++ = '0';
4306  if ((flags & FLAG_ALT) || ndigits > nzeroes)
4307  {
4308  *p++ = decimal_point_char ();
4309  while (ndigits > nzeroes)
4310  {
4311  --ndigits;
4312  *p++ = '0';
4313  }
4314  }
4315  }
4316  else
4317  {
4318  /* arg > 0.0. */
4319  int exponent;
4320  int adjusted;
4321  char *digits;
4322  size_t ndigits;
4323  size_t nzeroes;
4324 
4325  exponent = floorlog10 (arg);
4326  adjusted = 0;
4327  for (;;)
4328  {
4329  digits =
4330  scale10_round_decimal_double (arg,
4331  (int)(precision - 1) - exponent);
4332  if (digits == NULL)
4333  goto out_of_memory;
4334  ndigits = strlen (digits);
4335 
4336  if (ndigits == precision)
4337  break;
4338  if (ndigits < precision - 1
4339  || ndigits > precision + 1)
4340  /* The exponent was not guessed
4341  precisely enough. */
4342  abort ();
4343  if (adjusted)
4344  /* None of two values of exponent is
4345  the right one. Prevent an endless
4346  loop. */
4347  abort ();
4348  free (digits);
4349  if (ndigits < precision)
4350  exponent -= 1;
4351  else
4352  exponent += 1;
4353  adjusted = 1;
4354  }
4355  /* Here ndigits = precision. */
4356  if (is_borderline (digits, precision - 1))
4357  {
4358  /* Maybe the exponent guess was too high
4359  and a smaller exponent can be reached
4360  by turning a 10...0 into 9...9x. */
4361  char *digits2 =
4362  scale10_round_decimal_double (arg,
4363  (int)(precision - 1) - exponent + 1);
4364  if (digits2 == NULL)
4365  {
4366  free (digits);
4367  goto out_of_memory;
4368  }
4369  if (strlen (digits2) == precision)
4370  {
4371  free (digits);
4372  digits = digits2;
4373  exponent -= 1;
4374  }
4375  else
4376  free (digits2);
4377  }
4378  /* Here ndigits = precision. */
4379 
4380  /* Determine the number of trailing zeroes
4381  that have to be dropped. */
4382  nzeroes = 0;
4383  if ((flags & FLAG_ALT) == 0)
4384  while (nzeroes < ndigits
4385  && digits[nzeroes] == '0')
4386  nzeroes++;
4387 
4388  /* The exponent is now determined. */
4389  if (exponent >= -4
4390  && exponent < (long)precision)
4391  {
4392  /* Fixed-point notation:
4393  max(exponent,0)+1 digits, then the
4394  decimal point, then the remaining
4395  digits without trailing zeroes. */
4396  if (exponent >= 0)
4397  {
4398  size_t count = exponent + 1;
4399  /* Note: count <= precision = ndigits. */
4400  for (; count > 0; count--)
4401  *p++ = digits[--ndigits];
4402  if ((flags & FLAG_ALT) || ndigits > nzeroes)
4403  {
4404  *p++ = decimal_point_char ();
4405  while (ndigits > nzeroes)
4406  {
4407  --ndigits;
4408  *p++ = digits[ndigits];
4409  }
4410  }
4411  }
4412  else
4413  {
4414  size_t count = -exponent - 1;
4415  *p++ = '0';
4416  *p++ = decimal_point_char ();
4417  for (; count > 0; count--)
4418  *p++ = '0';
4419  while (ndigits > nzeroes)
4420  {
4421  --ndigits;
4422  *p++ = digits[ndigits];
4423  }
4424  }
4425  }
4426  else
4427  {
4428  /* Exponential notation. */
4429  *p++ = digits[--ndigits];
4430  if ((flags & FLAG_ALT) || ndigits > nzeroes)
4431  {
4432  *p++ = decimal_point_char ();
4433  while (ndigits > nzeroes)
4434  {
4435  --ndigits;
4436  *p++ = digits[ndigits];
4437  }
4438  }
4439  *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
4440 # if WIDE_CHAR_VERSION
4441  {
4442  static const wchar_t decimal_format[] =
4443  /* Produce the same number of exponent digits
4444  as the native printf implementation. */
4445 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4446  { '%', '+', '.', '3', 'd', '\0' };
4447 # else
4448  { '%', '+', '.', '2', 'd', '\0' };
4449 # endif
4450  SNPRINTF (p, 6 + 1, decimal_format, exponent);
4451  }
4452  while (*p != '\0')
4453  p++;
4454 # else
4455  {
4456  static const char decimal_format[] =
4457  /* Produce the same number of exponent digits
4458  as the native printf implementation. */
4459 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4460  "%+.3d";
4461 # else
4462  "%+.2d";
4463 # endif
4464  if (sizeof (DCHAR_T) == 1)
4465  {
4466  sprintf ((char *) p, decimal_format, exponent);
4467  while (*p != '\0')
4468  p++;
4469  }
4470  else
4471  {
4472  char expbuf[6 + 1];
4473  const char *ep;
4474  sprintf (expbuf, decimal_format, exponent);
4475  for (ep = expbuf; (*p = *ep) != '\0'; ep++)
4476  p++;
4477  }
4478  }
4479 # endif
4480  }
4481 
4482  free (digits);
4483  }
4484  }
4485  else
4486  abort ();
4487 # else
4488  /* arg is finite. */
4489  if (!(arg == 0.0))
4490  abort ();
4491 
4492  pad_ptr = p;
4493 
4494  if (dp->conversion == 'f' || dp->conversion == 'F')
4495  {
4496  *p++ = '0';
4497  if ((flags & FLAG_ALT) || precision > 0)
4498  {
4499  *p++ = decimal_point_char ();
4500  for (; precision > 0; precision--)
4501  *p++ = '0';
4502  }
4503  }
4504  else if (dp->conversion == 'e' || dp->conversion == 'E')
4505  {
4506  *p++ = '0';
4507  if ((flags & FLAG_ALT) || precision > 0)
4508  {
4509  *p++ = decimal_point_char ();
4510  for (; precision > 0; precision--)
4511  *p++ = '0';
4512  }
4513  *p++ = dp->conversion; /* 'e' or 'E' */
4514  *p++ = '+';
4515  /* Produce the same number of exponent digits as
4516  the native printf implementation. */
4517 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4518  *p++ = '0';
4519 # endif
4520  *p++ = '0';
4521  *p++ = '0';
4522  }
4523  else if (dp->conversion == 'g' || dp->conversion == 'G')
4524  {
4525  *p++ = '0';
4526  if (flags & FLAG_ALT)
4527  {
4528  size_t ndigits =
4529  (precision > 0 ? precision - 1 : 0);
4530  *p++ = decimal_point_char ();
4531  for (; ndigits > 0; --ndigits)
4532  *p++ = '0';
4533  }
4534  }
4535  else
4536  abort ();
4537 # endif
4538  }
4539  }
4540  }
4541 # endif
4542 
4543  /* The generated string now extends from tmp to p, with the
4544  zero padding insertion point being at pad_ptr. */
4545  if (has_width && p - tmp < width)
4546  {
4547  size_t pad = width - (p - tmp);
4548  DCHAR_T *end = p + pad;
4549 
4550  if (flags & FLAG_LEFT)
4551  {
4552  /* Pad with spaces on the right. */
4553  for (; pad > 0; pad--)
4554  *p++ = ' ';
4555  }
4556  else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
4557  {
4558  /* Pad with zeroes. */
4559  DCHAR_T *q = end;
4560 
4561  while (p > pad_ptr)
4562  *--q = *--p;
4563  for (; pad > 0; pad--)
4564  *p++ = '0';
4565  }
4566  else
4567  {
4568  /* Pad with spaces on the left. */
4569  DCHAR_T *q = end;
4570 
4571  while (p > tmp)
4572  *--q = *--p;
4573  for (; pad > 0; pad--)
4574  *p++ = ' ';
4575  }
4576 
4577  p = end;
4578  }
4579 
4580  {
4581  size_t count = p - tmp;
4582 
4583  if (count >= tmp_length)
4584  /* tmp_length was incorrectly calculated - fix the
4585  code above! */
4586  abort ();
4587 
4588  /* Make room for the result. */
4589  if (count >= allocated - length)
4590  {
4591  size_t n = xsum (length, count);
4592 
4593  ENSURE_ALLOCATION (n);
4594  }
4595 
4596  /* Append the result. */
4597  memcpy (result + length, tmp, count * sizeof (DCHAR_T));
4598  if (tmp != tmpbuf)
4599  free (tmp);
4600  length += count;
4601  }
4602  }
4603 #endif
4604  else
4605  {
4606  arg_type type = a.arg[dp->arg_index].type;
4607  int flags = dp->flags;
4608 #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4609  int has_width;
4610  size_t width;
4611 #endif
4612 #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
4613  int has_precision;
4614  size_t precision;
4615 #endif
4616 #if NEED_PRINTF_UNBOUNDED_PRECISION
4617  int prec_ourselves;
4618 #else
4619 # define prec_ourselves 0
4620 #endif
4621 #if NEED_PRINTF_FLAG_LEFTADJUST
4622 # define pad_ourselves 1
4623 #elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4624  int pad_ourselves;
4625 #else
4626 # define pad_ourselves 0
4627 #endif
4628  TCHAR_T *fbp;
4629  unsigned int prefix_count;
4630  int prefixes[2] IF_LINT (= { 0 });
4631  int orig_errno;
4632 #if !USE_SNPRINTF
4633  size_t tmp_length;
4634  TCHAR_T tmpbuf[700];
4635  TCHAR_T *tmp;
4636 #endif
4637 
4638 #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
4639  has_width = 0;
4640  width = 0;
4641  if (dp->width_start != dp->width_end)
4642  {
4643  if (dp->width_arg_index != ARG_NONE)
4644  {
4645  int arg;
4646 
4647  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
4648  abort ();
4649  arg = a.arg[dp->width_arg_index].a.a_int;
4650  if (arg < 0)
4651  {
4652  /* "A negative field width is taken as a '-' flag
4653  followed by a positive field width." */
4654  flags |= FLAG_LEFT;
4655  width = (unsigned int) (-arg);
4656  }
4657  else
4658  width = arg;
4659  }
4660  else
4661  {
4662  const FCHAR_T *digitp = dp->width_start;
4663 
4664  do
4665  width = xsum (xtimes (width, 10), *digitp++ - '0');
4666  while (digitp != dp->width_end);
4667  }
4668  has_width = 1;
4669  }
4670 #endif
4671 
4672 #if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
4673  has_precision = 0;
4674  precision = 6;
4675  if (dp->precision_start != dp->precision_end)
4676  {
4677  if (dp->precision_arg_index != ARG_NONE)
4678  {
4679  int arg;
4680 
4681  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
4682  abort ();
4683  arg = a.arg[dp->precision_arg_index].a.a_int;
4684  /* "A negative precision is taken as if the precision
4685  were omitted." */
4686  if (arg >= 0)
4687  {
4688  precision = arg;
4689  has_precision = 1;
4690  }
4691  }
4692  else
4693  {
4694  const FCHAR_T *digitp = dp->precision_start + 1;
4695 
4696  precision = 0;
4697  while (digitp != dp->precision_end)
4698  precision = xsum (xtimes (precision, 10), *digitp++ - '0');
4699  has_precision = 1;
4700  }
4701  }
4702 #endif
4703 
4704  /* Decide whether to handle the precision ourselves. */
4705 #if NEED_PRINTF_UNBOUNDED_PRECISION
4706  switch (dp->conversion)
4707  {
4708  case 'd': case 'i': case 'u':
4709  case 'o':
4710  case 'x': case 'X': case 'p':
4711  prec_ourselves = has_precision && (precision > 0);
4712  break;
4713  default:
4714  prec_ourselves = 0;
4715  break;
4716  }
4717 #endif
4718 
4719  /* Decide whether to perform the padding ourselves. */
4720 #if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
4721  switch (dp->conversion)
4722  {
4723 # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
4724  /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
4725  to perform the padding after this conversion. Functions
4726  with unistdio extensions perform the padding based on
4727  character count rather than element count. */
4728  case 'c': case 's':
4729 # endif
4730 # if NEED_PRINTF_FLAG_ZERO
4731  case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
4732  case 'a': case 'A':
4733 # endif
4734  pad_ourselves = 1;
4735  break;
4736  default:
4738  break;
4739  }
4740 #endif
4741 
4742 #if !USE_SNPRINTF
4743  /* Allocate a temporary buffer of sufficient size for calling
4744  sprintf. */
4745  tmp_length =
4746  MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type,
4747  flags, width, has_precision, precision,
4748  pad_ourselves);
4749 
4750  if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T))
4751  tmp = tmpbuf;
4752  else
4753  {
4754  size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T));
4755 
4756  if (size_overflow_p (tmp_memsize))
4757  /* Overflow, would lead to out of memory. */
4758  goto out_of_memory;
4759  tmp = (TCHAR_T *) malloc (tmp_memsize);
4760  if (tmp == NULL)
4761  /* Out of memory. */
4762  goto out_of_memory;
4763  }
4764 #endif
4765 
4766  /* Construct the format string for calling snprintf or
4767  sprintf. */
4768  fbp = buf;
4769  *fbp++ = '%';
4770 #if NEED_PRINTF_FLAG_GROUPING
4771  /* The underlying implementation doesn't support the ' flag.
4772  Produce no grouping characters in this case; this is
4773  acceptable because the grouping is locale dependent. */
4774 #else
4775  if (flags & FLAG_GROUP)
4776  *fbp++ = '\'';
4777 #endif
4778  if (flags & FLAG_LEFT)
4779  *fbp++ = '-';
4780  if (flags & FLAG_SHOWSIGN)
4781  *fbp++ = '+';
4782  if (flags & FLAG_SPACE)
4783  *fbp++ = ' ';
4784  if (flags & FLAG_ALT)
4785  *fbp++ = '#';
4786 #if __GLIBC__ >= 2 && !defined __UCLIBC__
4787  if (flags & FLAG_LOCALIZED)
4788  *fbp++ = 'I';
4789 #endif
4790  if (!pad_ourselves)
4791  {
4792  if (flags & FLAG_ZERO)
4793  *fbp++ = '0';
4794  if (dp->width_start != dp->width_end)
4795  {
4796  size_t n = dp->width_end - dp->width_start;
4797  /* The width specification is known to consist only
4798  of standard ASCII characters. */
4799  if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
4800  {
4801  memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T));
4802  fbp += n;
4803  }
4804  else
4805  {
4806  const FCHAR_T *mp = dp->width_start;
4807  do
4808  *fbp++ = (unsigned char) *mp++;
4809  while (--n > 0);
4810  }
4811  }
4812  }
4813  if (!prec_ourselves)
4814  {
4815  if (dp->precision_start != dp->precision_end)
4816  {
4817  size_t n = dp->precision_end - dp->precision_start;
4818  /* The precision specification is known to consist only
4819  of standard ASCII characters. */
4820  if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
4821  {
4822  memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T));
4823  fbp += n;
4824  }
4825  else
4826  {
4827  const FCHAR_T *mp = dp->precision_start;
4828  do
4829  *fbp++ = (unsigned char) *mp++;
4830  while (--n > 0);
4831  }
4832  }
4833  }
4834 
4835  switch (type)
4836  {
4837 #if HAVE_LONG_LONG_INT
4838  case TYPE_LONGLONGINT:
4839  case TYPE_ULONGLONGINT:
4840 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
4841  *fbp++ = 'I';
4842  *fbp++ = '6';
4843  *fbp++ = '4';
4844  break;
4845 # else
4846  *fbp++ = 'l';
4847  /*FALLTHROUGH*/
4848 # endif
4849 #endif
4850  case TYPE_LONGINT:
4851  case TYPE_ULONGINT:
4852 #if HAVE_WINT_T
4853  case TYPE_WIDE_CHAR:
4854 #endif
4855 #if HAVE_WCHAR_T
4856  case TYPE_WIDE_STRING:
4857 #endif
4858  *fbp++ = 'l';
4859  break;
4860  case TYPE_LONGDOUBLE:
4861  *fbp++ = 'L';
4862  break;
4863  default:
4864  break;
4865  }
4866 #if NEED_PRINTF_DIRECTIVE_F
4867  if (dp->conversion == 'F')
4868  *fbp = 'f';
4869  else
4870 #endif
4871  *fbp = dp->conversion;
4872 #if USE_SNPRINTF
4873 # if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
4874  fbp[1] = '%';
4875  fbp[2] = 'n';
4876  fbp[3] = '\0';
4877 # else
4878  /* On glibc2 systems from glibc >= 2.3 - probably also older
4879  ones - we know that snprintf's return value conforms to
4880  ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and
4881  gl_SNPRINTF_TRUNCATION_C99 pass.
4882  Therefore we can avoid using %n in this situation.
4883  On glibc2 systems from 2004-10-18 or newer, the use of %n
4884  in format strings in writable memory may crash the program
4885  (if compiled with _FORTIFY_SOURCE=2), so we should avoid it
4886  in this situation. */
4887  /* On native Windows systems (such as mingw), we can avoid using
4888  %n because:
4889  - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
4890  snprintf does not write more than the specified number
4891  of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
4892  '4', '5', '6' into buf, not '4', '5', '\0'.)
4893  - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
4894  allows us to recognize the case of an insufficient
4895  buffer size: it returns -1 in this case.
4896  On native Windows systems (such as mingw) where the OS is
4897  Windows Vista, the use of %n in format strings by default
4898  crashes the program. See
4899  <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
4900  <http://msdn2.microsoft.com/en-us/library/ms175782(VS.80).aspx>
4901  So we should avoid %n in this situation. */
4902  fbp[1] = '\0';
4903 # endif
4904 #else
4905  fbp[1] = '\0';
4906 #endif
4907 
4908  /* Construct the arguments for calling snprintf or sprintf. */
4909  prefix_count = 0;
4910  if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
4911  {
4912  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
4913  abort ();
4914  prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
4915  }
4916  if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
4917  {
4918  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
4919  abort ();
4920  prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
4921  }
4922 
4923 #if USE_SNPRINTF
4924  /* The SNPRINTF result is appended after result[0..length].
4925  The latter is an array of DCHAR_T; SNPRINTF appends an
4926  array of TCHAR_T to it. This is possible because
4927  sizeof (TCHAR_T) divides sizeof (DCHAR_T) and
4928  alignof (TCHAR_T) <= alignof (DCHAR_T). */
4929 # define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T))
4930  /* Ensure that maxlen below will be >= 2. Needed on BeOS,
4931  where an snprintf() with maxlen==1 acts like sprintf(). */
4932  ENSURE_ALLOCATION (xsum (length,
4933  (2 + TCHARS_PER_DCHAR - 1)
4934  / TCHARS_PER_DCHAR));
4935  /* Prepare checking whether snprintf returns the count
4936  via %n. */
4937  *(TCHAR_T *) (result + length) = '\0';
4938 #endif
4939 
4940  orig_errno = errno;
4941 
4942  for (;;)
4943  {
4944  int count = -1;
4945 
4946 #if USE_SNPRINTF
4947  int retcount = 0;
4948  size_t maxlen = allocated - length;
4949  /* SNPRINTF can fail if its second argument is
4950  > INT_MAX. */
4951  if (maxlen > INT_MAX / TCHARS_PER_DCHAR)
4952  maxlen = INT_MAX / TCHARS_PER_DCHAR;
4953  maxlen = maxlen * TCHARS_PER_DCHAR;
4954 # define SNPRINTF_BUF(arg) \
4955  switch (prefix_count) \
4956  { \
4957  case 0: \
4958  retcount = SNPRINTF ((TCHAR_T *) (result + length), \
4959  maxlen, buf, \
4960  arg, &count); \
4961  break; \
4962  case 1: \
4963  retcount = SNPRINTF ((TCHAR_T *) (result + length), \
4964  maxlen, buf, \
4965  prefixes[0], arg, &count); \
4966  break; \
4967  case 2: \
4968  retcount = SNPRINTF ((TCHAR_T *) (result + length), \
4969  maxlen, buf, \
4970  prefixes[0], prefixes[1], arg, \
4971  &count); \
4972  break; \
4973  default: \
4974  abort (); \
4975  }
4976 #else
4977 # define SNPRINTF_BUF(arg) \
4978  switch (prefix_count) \
4979  { \
4980  case 0: \
4981  count = sprintf (tmp, buf, arg); \
4982  break; \
4983  case 1: \
4984  count = sprintf (tmp, buf, prefixes[0], arg); \
4985  break; \
4986  case 2: \
4987  count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
4988  arg); \
4989  break; \
4990  default: \
4991  abort (); \
4992  }
4993 #endif
4994 
4995  errno = 0;
4996  switch (type)
4997  {
4998  case TYPE_SCHAR:
4999  {
5000  int arg = a.arg[dp->arg_index].a.a_schar;
5001  SNPRINTF_BUF (arg);
5002  }
5003  break;
5004  case TYPE_UCHAR:
5005  {
5006  unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
5007  SNPRINTF_BUF (arg);
5008  }
5009  break;
5010  case TYPE_SHORT:
5011  {
5012  int arg = a.arg[dp->arg_index].a.a_short;
5013  SNPRINTF_BUF (arg);
5014  }
5015  break;
5016  case TYPE_USHORT:
5017  {
5018  unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
5019  SNPRINTF_BUF (arg);
5020  }
5021  break;
5022  case TYPE_INT:
5023  {
5024  int arg = a.arg[dp->arg_index].a.a_int;
5025  SNPRINTF_BUF (arg);
5026  }
5027  break;
5028  case TYPE_UINT:
5029  {
5030  unsigned int arg = a.arg[dp->arg_index].a.a_uint;
5031  SNPRINTF_BUF (arg);
5032  }
5033  break;
5034  case TYPE_LONGINT:
5035  {
5036  long int arg = a.arg[dp->arg_index].a.a_longint;
5037  SNPRINTF_BUF (arg);
5038  }
5039  break;
5040  case TYPE_ULONGINT:
5041  {
5042  unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
5043  SNPRINTF_BUF (arg);
5044  }
5045  break;
5046 #if HAVE_LONG_LONG_INT
5047  case TYPE_LONGLONGINT:
5048  {
5049  long long int arg = a.arg[dp->arg_index].a.a_longlongint;
5050  SNPRINTF_BUF (arg);
5051  }
5052  break;
5053  case TYPE_ULONGLONGINT:
5054  {
5055  unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
5056  SNPRINTF_BUF (arg);
5057  }
5058  break;
5059 #endif
5060  case TYPE_DOUBLE:
5061  {
5062  double arg = a.arg[dp->arg_index].a.a_double;
5063  SNPRINTF_BUF (arg);
5064  }
5065  break;
5066  case TYPE_LONGDOUBLE:
5067  {
5068  long double arg = a.arg[dp->arg_index].a.a_longdouble;
5069  SNPRINTF_BUF (arg);
5070  }
5071  break;
5072  case TYPE_CHAR:
5073  {
5074  int arg = a.arg[dp->arg_index].a.a_char;
5075  SNPRINTF_BUF (arg);
5076  }
5077  break;
5078 #if HAVE_WINT_T
5079  case TYPE_WIDE_CHAR:
5080  {
5081  wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
5082  SNPRINTF_BUF (arg);
5083  }
5084  break;
5085 #endif
5086  case TYPE_STRING:
5087  {
5088  const char *arg = a.arg[dp->arg_index].a.a_string;
5089  SNPRINTF_BUF (arg);
5090  }
5091  break;
5092 #if HAVE_WCHAR_T
5093  case TYPE_WIDE_STRING:
5094  {
5095  const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
5096  SNPRINTF_BUF (arg);
5097  }
5098  break;
5099 #endif
5100  case TYPE_POINTER:
5101  {
5102  void *arg = a.arg[dp->arg_index].a.a_pointer;
5103  SNPRINTF_BUF (arg);
5104  }
5105  break;
5106  default:
5107  abort ();
5108  }
5109 
5110 #if USE_SNPRINTF
5111  /* Portability: Not all implementations of snprintf()
5112  are ISO C 99 compliant. Determine the number of
5113  bytes that snprintf() has produced or would have
5114  produced. */
5115  if (count >= 0)
5116  {
5117  /* Verify that snprintf() has NUL-terminated its
5118  result. */
5119  if (count < maxlen
5120  && ((TCHAR_T *) (result + length)) [count] != '\0')
5121  abort ();
5122  /* Portability hack. */
5123  if (retcount > count)
5124  count = retcount;
5125  }
5126  else
5127  {
5128  /* snprintf() doesn't understand the '%n'
5129  directive. */
5130  if (fbp[1] != '\0')
5131  {
5132  /* Don't use the '%n' directive; instead, look
5133  at the snprintf() return value. */
5134  fbp[1] = '\0';
5135  continue;
5136  }
5137  else
5138  {
5139  /* Look at the snprintf() return value. */
5140  if (retcount < 0)
5141  {
5142 # if !HAVE_SNPRINTF_RETVAL_C99
5143  /* HP-UX 10.20 snprintf() is doubly deficient:
5144  It doesn't understand the '%n' directive,
5145  *and* it returns -1 (rather than the length
5146  that would have been required) when the
5147  buffer is too small.
5148  But a failure at this point can also come
5149  from other reasons than a too small buffer,
5150  such as an invalid wide string argument to
5151  the %ls directive, or possibly an invalid
5152  floating-point argument. */
5153  size_t tmp_length =
5154  MAX_ROOM_NEEDED (&a, dp->arg_index,
5155  dp->conversion, type, flags,
5156  has_width ? width : 0,
5157  has_precision,
5159 
5160  if (maxlen < tmp_length)
5161  {
5162  /* Make more room. But try to do through
5163  this reallocation only once. */
5164  size_t bigger_need =
5165  xsum (length,
5166  xsum (tmp_length,
5167  TCHARS_PER_DCHAR - 1)
5168  / TCHARS_PER_DCHAR);
5169  /* And always grow proportionally.
5170  (There may be several arguments, each
5171  needing a little more room than the
5172  previous one.) */
5173  size_t bigger_need2 =
5174  xsum (xtimes (allocated, 2), 12);
5175  if (bigger_need < bigger_need2)
5176  bigger_need = bigger_need2;
5177  ENSURE_ALLOCATION (bigger_need);
5178  continue;
5179  }
5180 # endif
5181  }
5182  else
5183  count = retcount;
5184  }
5185  }
5186 #endif
5187 
5188  /* Attempt to handle failure. */
5189  if (count < 0)
5190  {
5191  /* SNPRINTF or sprintf failed. Save and use the errno
5192  that it has set, if any. */
5193  int saved_errno = errno;
5194 
5195  if (!(result == resultbuf || result == NULL))
5196  free (result);
5197  if (buf_malloced != NULL)
5198  free (buf_malloced);
5199  CLEANUP ();
5200  errno =
5201  (saved_errno != 0
5202  ? saved_errno
5203  : (dp->conversion == 'c' || dp->conversion == 's'
5204  ? EILSEQ
5205  : EINVAL));
5206  return NULL;
5207  }
5208 
5209 #if USE_SNPRINTF
5210  /* Handle overflow of the allocated buffer.
5211  If such an overflow occurs, a C99 compliant snprintf()
5212  returns a count >= maxlen. However, a non-compliant
5213  snprintf() function returns only count = maxlen - 1. To
5214  cover both cases, test whether count >= maxlen - 1. */
5215  if ((unsigned int) count + 1 >= maxlen)
5216  {
5217  /* If maxlen already has attained its allowed maximum,
5218  allocating more memory will not increase maxlen.
5219  Instead of looping, bail out. */
5220  if (maxlen == INT_MAX / TCHARS_PER_DCHAR)
5221  goto overflow;
5222  else
5223  {
5224  /* Need at least (count + 1) * sizeof (TCHAR_T)
5225  bytes. (The +1 is for the trailing NUL.)
5226  But ask for (count + 2) * sizeof (TCHAR_T)
5227  bytes, so that in the next round, we likely get
5228  maxlen > (unsigned int) count + 1
5229  and so we don't get here again.
5230  And allocate proportionally, to avoid looping
5231  eternally if snprintf() reports a too small
5232  count. */
5233  size_t n =
5234  xmax (xsum (length,
5235  ((unsigned int) count + 2
5236  + TCHARS_PER_DCHAR - 1)
5237  / TCHARS_PER_DCHAR),
5238  xtimes (allocated, 2));
5239 
5240  ENSURE_ALLOCATION (n);
5241  continue;
5242  }
5243  }
5244 #endif
5245 
5246 #if NEED_PRINTF_UNBOUNDED_PRECISION
5247  if (prec_ourselves)
5248  {
5249  /* Handle the precision. */
5250  TCHAR_T *prec_ptr =
5251 # if USE_SNPRINTF
5252  (TCHAR_T *) (result + length);
5253 # else
5254  tmp;
5255 # endif
5256  size_t prefix_count;
5257  size_t move;
5258 
5259  prefix_count = 0;
5260  /* Put the additional zeroes after the sign. */
5261  if (count >= 1
5262  && (*prec_ptr == '-' || *prec_ptr == '+'
5263  || *prec_ptr == ' '))
5264  prefix_count = 1;
5265  /* Put the additional zeroes after the 0x prefix if
5266  (flags & FLAG_ALT) || (dp->conversion == 'p'). */
5267  else if (count >= 2
5268  && prec_ptr[0] == '0'
5269  && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'))
5270  prefix_count = 2;
5271 
5272  move = count - prefix_count;
5273  if (precision > move)
5274  {
5275  /* Insert zeroes. */
5276  size_t insert = precision - move;
5277  TCHAR_T *prec_end;
5278 
5279 # if USE_SNPRINTF
5280  size_t n =
5281  xsum (length,
5282  (count + insert + TCHARS_PER_DCHAR - 1)
5283  / TCHARS_PER_DCHAR);
5284  length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
5285  ENSURE_ALLOCATION (n);
5286  length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
5287  prec_ptr = (TCHAR_T *) (result + length);
5288 # endif
5289 
5290  prec_end = prec_ptr + count;
5291  prec_ptr += prefix_count;
5292 
5293  while (prec_end > prec_ptr)
5294  {
5295  prec_end--;
5296  prec_end[insert] = prec_end[0];
5297  }
5298 
5299  prec_end += insert;
5300  do
5301  *--prec_end = '0';
5302  while (prec_end > prec_ptr);
5303 
5304  count += insert;
5305  }
5306  }
5307 #endif
5308 
5309 #if !USE_SNPRINTF
5310  if (count >= tmp_length)
5311  /* tmp_length was incorrectly calculated - fix the
5312  code above! */
5313  abort ();
5314 #endif
5315 
5316 #if !DCHAR_IS_TCHAR
5317  /* Convert from TCHAR_T[] to DCHAR_T[]. */
5318  if (dp->conversion == 'c' || dp->conversion == 's')
5319  {
5320  /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
5321  TYPE_WIDE_STRING.
5322  The result string is not certainly ASCII. */
5323  const TCHAR_T *tmpsrc;
5324  DCHAR_T *tmpdst;
5325  size_t tmpdst_len;
5326  /* This code assumes that TCHAR_T is 'char'. */
5327  verify (sizeof (TCHAR_T) == 1);
5328 # if USE_SNPRINTF
5329  tmpsrc = (TCHAR_T *) (result + length);
5330 # else
5331  tmpsrc = tmp;
5332 # endif
5333  tmpdst =
5334  DCHAR_CONV_FROM_ENCODING (locale_charset (),
5335  iconveh_question_mark,
5336  tmpsrc, count,
5337  NULL,
5338  NULL, &tmpdst_len);
5339  if (tmpdst == NULL)
5340  {
5341  int saved_errno = errno;
5342  if (!(result == resultbuf || result == NULL))
5343  free (result);
5344  if (buf_malloced != NULL)
5345  free (buf_malloced);
5346  CLEANUP ();
5347  errno = saved_errno;
5348  return NULL;
5349  }
5350  ENSURE_ALLOCATION (xsum (length, tmpdst_len));
5351  DCHAR_CPY (result + length, tmpdst, tmpdst_len);
5352  free (tmpdst);
5353  count = tmpdst_len;
5354  }
5355  else
5356  {
5357  /* The result string is ASCII.
5358  Simple 1:1 conversion. */
5359 # if USE_SNPRINTF
5360  /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a
5361  no-op conversion, in-place on the array starting
5362  at (result + length). */
5363  if (sizeof (DCHAR_T) != sizeof (TCHAR_T))
5364 # endif
5365  {
5366  const TCHAR_T *tmpsrc;
5367  DCHAR_T *tmpdst;
5368  size_t n;
5369 
5370 # if USE_SNPRINTF
5371  if (result == resultbuf)
5372  {
5373  tmpsrc = (TCHAR_T *) (result + length);
5374  /* ENSURE_ALLOCATION will not move tmpsrc
5375  (because it's part of resultbuf). */
5376  ENSURE_ALLOCATION (xsum (length, count));
5377  }
5378  else
5379  {
5380  /* ENSURE_ALLOCATION will move the array
5381  (because it uses realloc(). */
5382  ENSURE_ALLOCATION (xsum (length, count));
5383  tmpsrc = (TCHAR_T *) (result + length);
5384  }
5385 # else
5386  tmpsrc = tmp;
5387  ENSURE_ALLOCATION (xsum (length, count));
5388 # endif
5389  tmpdst = result + length;
5390  /* Copy backwards, because of overlapping. */
5391  tmpsrc += count;
5392  tmpdst += count;
5393  for (n = count; n > 0; n--)
5394  *--tmpdst = (unsigned char) *--tmpsrc;
5395  }
5396  }
5397 #endif
5398 
5399 #if DCHAR_IS_TCHAR && !USE_SNPRINTF
5400  /* Make room for the result. */
5401  if (count > allocated - length)
5402  {
5403  /* Need at least count elements. But allocate
5404  proportionally. */
5405  size_t n =
5406  xmax (xsum (length, count), xtimes (allocated, 2));
5407 
5408  ENSURE_ALLOCATION (n);
5409  }
5410 #endif
5411 
5412  /* Here count <= allocated - length. */
5413 
5414  /* Perform padding. */
5415 #if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
5416  if (pad_ourselves && has_width)
5417  {
5418  size_t w;
5419 # if ENABLE_UNISTDIO
5420  /* Outside POSIX, it's preferable to compare the width
5421  against the number of _characters_ of the converted
5422  value. */
5423  w = DCHAR_MBSNLEN (result + length, count);
5424 # else
5425  /* The width is compared against the number of _bytes_
5426  of the converted value, says POSIX. */
5427  w = count;
5428 # endif
5429  if (w < width)
5430  {
5431  size_t pad = width - w;
5432 
5433  /* Make room for the result. */
5434  if (xsum (count, pad) > allocated - length)
5435  {
5436  /* Need at least count + pad elements. But
5437  allocate proportionally. */
5438  size_t n =
5439  xmax (xsum3 (length, count, pad),
5440  xtimes (allocated, 2));
5441 
5442 # if USE_SNPRINTF
5443  length += count;
5444  ENSURE_ALLOCATION (n);
5445  length -= count;
5446 # else
5447  ENSURE_ALLOCATION (n);
5448 # endif
5449  }
5450  /* Here count + pad <= allocated - length. */
5451 
5452  {
5453 # if !DCHAR_IS_TCHAR || USE_SNPRINTF
5454  DCHAR_T * const rp = result + length;
5455 # else
5456  DCHAR_T * const rp = tmp;
5457 # endif
5458  DCHAR_T *p = rp + count;
5459  DCHAR_T *end = p + pad;
5460  DCHAR_T *pad_ptr;
5461 # if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
5462  if (dp->conversion == 'c'
5463  || dp->conversion == 's')
5464  /* No zero-padding for string directives. */
5465  pad_ptr = NULL;
5466  else
5467 # endif
5468  {
5469  pad_ptr = (*rp == '-' ? rp + 1 : rp);
5470  /* No zero-padding of "inf" and "nan". */
5471  if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
5472  || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
5473  pad_ptr = NULL;
5474  }
5475  /* The generated string now extends from rp to p,
5476  with the zero padding insertion point being at
5477  pad_ptr. */
5478 
5479  count = count + pad; /* = end - rp */
5480 
5481  if (flags & FLAG_LEFT)
5482  {
5483  /* Pad with spaces on the right. */
5484  for (; pad > 0; pad--)
5485  *p++ = ' ';
5486  }
5487  else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
5488  {
5489  /* Pad with zeroes. */
5490  DCHAR_T *q = end;
5491 
5492  while (p > pad_ptr)
5493  *--q = *--p;
5494  for (; pad > 0; pad--)
5495  *p++ = '0';
5496  }
5497  else
5498  {
5499  /* Pad with spaces on the left. */
5500  DCHAR_T *q = end;
5501 
5502  while (p > rp)
5503  *--q = *--p;
5504  for (; pad > 0; pad--)
5505  *p++ = ' ';
5506  }
5507  }
5508  }
5509  }
5510 #endif
5511 
5512  /* Here still count <= allocated - length. */
5513 
5514 #if !DCHAR_IS_TCHAR || USE_SNPRINTF
5515  /* The snprintf() result did fit. */
5516 #else
5517  /* Append the sprintf() result. */
5518  memcpy (result + length, tmp, count * sizeof (DCHAR_T));
5519 #endif
5520 #if !USE_SNPRINTF
5521  if (tmp != tmpbuf)
5522  free (tmp);
5523 #endif
5524 
5525 #if NEED_PRINTF_DIRECTIVE_F
5526  if (dp->conversion == 'F')
5527  {
5528  /* Convert the %f result to upper case for %F. */
5529  DCHAR_T *rp = result + length;
5530  size_t rc;
5531  for (rc = count; rc > 0; rc--, rp++)
5532  if (*rp >= 'a' && *rp <= 'z')
5533  *rp = *rp - 'a' + 'A';
5534  }
5535 #endif
5536 
5537  length += count;
5538  break;
5539  }
5540  errno = orig_errno;
5541 #undef pad_ourselves
5542 #undef prec_ourselves
5543  }
5544  }
5545  }
5546 
5547  /* Add the final NUL. */
5548  ENSURE_ALLOCATION (xsum (length, 1));
5549  result[length] = '\0';
5550 
5551  if (result != resultbuf && length + 1 < allocated)
5552  {
5553  /* Shrink the allocated memory if possible. */
5554  DCHAR_T *memory;
5555 
5556  memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
5557  if (memory != NULL)
5558  result = memory;
5559  }
5560 
5561  if (buf_malloced != NULL)
5562  free (buf_malloced);
5563  CLEANUP ();
5564  *lengthp = length;
5565  /* Note that we can produce a big string of a length > INT_MAX. POSIX
5566  says that snprintf() fails with errno = EOVERFLOW in this case, but
5567  that's only because snprintf() returns an 'int'. This function does
5568  not have this limitation. */
5569  return result;
5570 
5571 #if USE_SNPRINTF
5572  overflow:
5573  if (!(result == resultbuf || result == NULL))
5574  free (result);
5575  if (buf_malloced != NULL)
5576  free (buf_malloced);
5577  CLEANUP ();
5578  errno = EOVERFLOW;
5579  return NULL;
5580 #endif
5581 
5582  out_of_memory:
5583  if (!(result == resultbuf || result == NULL))
5584  free (result);
5585  if (buf_malloced != NULL)
5586  free (buf_malloced);
5587  out_of_memory_1:
5588  CLEANUP ();
5589  errno = ENOMEM;
5590  return NULL;
5591  }
5592 }
static int count
Definition: SDG.c:519
void * alloca(size_t)
Memory allocation on the stack.
static int wc
FI: Provisional management of warnings.
#define EOVERFLOW
Definition: errno.in.h:208
#define EILSEQ
Definition: errno.in.h:274
void free(void *)
void * memset(void *str, int c, size_t len)
memset.c – set an area of memory to a given value Copyright (C) 1991, 2003, 2009-2011 Free Software F...
Definition: memset.c:23
arg_type
Get size_t.
Definition: printf-args.h:50
@ TYPE_DOUBLE
Definition: printf-args.h:64
@ TYPE_SHORT
Definition: printf-args.h:54
@ TYPE_CHAR
Definition: printf-args.h:66
@ TYPE_USHORT
Definition: printf-args.h:55
@ TYPE_INT
Definition: printf-args.h:56
@ TYPE_COUNT_SCHAR_POINTER
Definition: printf-args.h:75
@ TYPE_POINTER
Definition: printf-args.h:74
@ TYPE_SCHAR
Definition: printf-args.h:52
@ TYPE_COUNT_SHORT_POINTER
Definition: printf-args.h:76
@ TYPE_COUNT_LONGINT_POINTER
Definition: printf-args.h:78
@ TYPE_COUNT_INT_POINTER
Definition: printf-args.h:77
@ TYPE_UINT
Definition: printf-args.h:57
@ TYPE_STRING
Definition: printf-args.h:70
@ TYPE_UCHAR
Definition: printf-args.h:53
#define PRINTF_FETCHARGS
Decomposed printf argument list.
Definition: printf-args.h:28
#define FLAG_GROUP
Parse printf format string.
Definition: printf-parse.h:33
#define FLAG_LEFT
Definition: printf-parse.h:34
#define ARG_NONE
arg_index value indicating that no argument is consumed.
Definition: printf-parse.h:44
#define FLAG_SHOWSIGN
Definition: printf-parse.h:35
#define FLAG_ZERO
Definition: printf-parse.h:38
#define FLAG_ALT
Definition: printf-parse.h:37
#define FLAG_SPACE
Definition: printf-parse.h:36
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87
#define uint32_t
Definition: stdint.in.h:156
#define uint16_t
Definition: stdint.in.h:149
#define uint8_t
Definition: stdint.in.h:142
int a_char
Definition: printf-args.h:111
signed char * a_count_schar_pointer
Definition: printf-args.h:120
unsigned int a_uint
Definition: printf-args.h:101
long int * a_count_longint_pointer
Definition: printf-args.h:123
arg_type type
Definition: printf-args.h:93
signed char a_schar
Definition: printf-args.h:96
unsigned long int a_ulongint
Definition: printf-args.h:103
long double a_longdouble
Definition: printf-args.h:110
short a_short
Definition: printf-args.h:98
double a_double
Definition: printf-args.h:109
unsigned short a_ushort
Definition: printf-args.h:99
unsigned char a_uchar
Definition: printf-args.h:97
long int a_longint
Definition: printf-args.h:102
void * a_pointer
Definition: printf-args.h:119
short * a_count_short_pointer
Definition: printf-args.h:121
int * a_count_int_pointer
Definition: printf-args.h:122
static bool overflow
#define ENSURE_ALLOCATION(needed)
#define SNPRINTF_BUF(arg)
#define MAX_ROOM_NEEDED
Use a different function name, to make it possible that the 'wchar_t' parametrization and the 'char' ...
Definition: vasnprintf.c:1528
#define DIRECTIVES
Definition: vasnprintf.c:141
#define CLEANUP()
#define TCHAR_T
Definition: vasnprintf.c:138
#define DIRECTIVE
Definition: vasnprintf.c:140
#define DCHAR_SET
Definition: vasnprintf.c:144
#define SNPRINTF
Unix.
Definition: vasnprintf.c:188
#define IF_LINT(Code)
Here we need to call the native snprintf, not rpl_snprintf.
Definition: vasnprintf.c:201
#define PRINTF_PARSE
Definition: vasnprintf.c:142
#define DCHAR_CPY
Definition: vasnprintf.c:143
#define FCHAR_T
Definition: vasnprintf.c:136
#define prec_ourselves
#define verify(R)
Verify requirement R at compile-time, as a declaration without a trailing ';'.
Definition: verify.h:251
#define wint_t
The definitions of _GL_FUNCDECL_RPL etc.
Definition: wchar.in.h:103
#define mbstate_t
Definition: wchar.in.h:133
XSIZE_INLINE size_t xsum4(size_t size1, size_t size2, size_t size3, size_t size4)
Sum of four sizes, with overflow check.
Definition: xsize.h:84
XSIZE_INLINE size_t xmax(size_t size1, size_t size2)
Maximum of two sizes, with overflow check.
Definition: xsize.h:94
XSIZE_INLINE size_t xsum3(size_t size1, size_t size2, size_t size3)
Sum of three sizes, with overflow check.
Definition: xsize.h:74

References argument::a, argument::a_char, argument::a_count_int_pointer, argument::a_count_longint_pointer, argument::a_count_schar_pointer, argument::a_count_short_pointer, argument::a_double, argument::a_int, argument::a_longdouble, argument::a_longint, argument::a_pointer, argument::a_schar, argument::a_short, argument::a_string, argument::a_uchar, argument::a_uint, argument::a_ulongint, argument::a_ushort, abort, alloca(), arguments::arg, ARG_NONE, buf, CLEANUP, count, cp, DCHAR_CPY, DCHAR_SET, DCHAR_T, DIRECTIVE, DIRECTIVES, EILSEQ, end, ENSURE_ALLOCATION, EOVERFLOW, FCHAR_T, FLAG_ALT, FLAG_GROUP, FLAG_LEFT, FLAG_SHOWSIGN, FLAG_SPACE, FLAG_ZERO, free(), IF_LINT, int, malloc(), MAX_ROOM_NEEDED, mbstate_t, memset(), overflow, pad_ourselves, prec_ourselves, precision(), prefixes, PRINTF_FETCHARGS, PRINTF_PARSE, size_overflow_p, SNPRINTF, SNPRINTF_BUF, TCHAR_T, argument::type, TYPE_CHAR, TYPE_COUNT_INT_POINTER, TYPE_COUNT_LONGINT_POINTER, TYPE_COUNT_SCHAR_POINTER, TYPE_COUNT_SHORT_POINTER, TYPE_DOUBLE, TYPE_INT, TYPE_LONGDOUBLE, TYPE_LONGINT, TYPE_POINTER, TYPE_SCHAR, TYPE_SHORT, TYPE_STRING, TYPE_UCHAR, TYPE_UINT, TYPE_ULONGINT, TYPE_USHORT, uint16_t, uint32_t, uint8_t, verify, wc, wint_t, xmax(), xsum(), xsum3(), xsum4(), and xtimes.

+ Here is the call graph for this function: