Home | History | Annotate | Line # | Download | only in lib
vasnprintf.c revision 1.1
      1  1.1  christos /* vsprintf with automatic memory allocation.
      2  1.1  christos    Copyright (C) 1999, 2002-2005 Free Software Foundation, Inc.
      3  1.1  christos 
      4  1.1  christos    This program is free software; you can redistribute it and/or modify
      5  1.1  christos    it under the terms of the GNU General Public License as published by
      6  1.1  christos    the Free Software Foundation; either version 2, or (at your option)
      7  1.1  christos    any later version.
      8  1.1  christos 
      9  1.1  christos    This program is distributed in the hope that it will be useful,
     10  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  1.1  christos    GNU General Public License for more details.
     13  1.1  christos 
     14  1.1  christos    You should have received a copy of the GNU General Public License along
     15  1.1  christos    with this program; if not, write to the Free Software Foundation,
     16  1.1  christos    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
     17  1.1  christos 
     18  1.1  christos /* Tell glibc's <stdio.h> to provide a prototype for snprintf().
     19  1.1  christos    This must come before <config.h> because <config.h> may include
     20  1.1  christos    <features.h>, and once <features.h> has been included, it's too late.  */
     21  1.1  christos #ifndef _GNU_SOURCE
     22  1.1  christos # define _GNU_SOURCE    1
     23  1.1  christos #endif
     24  1.1  christos 
     25  1.1  christos #ifdef HAVE_CONFIG_H
     26  1.1  christos # include <config.h>
     27  1.1  christos #endif
     28  1.1  christos #ifndef IN_LIBINTL
     29  1.1  christos # include <alloca.h>
     30  1.1  christos #endif
     31  1.1  christos 
     32  1.1  christos /* Specification.  */
     33  1.1  christos #if WIDE_CHAR_VERSION
     34  1.1  christos # include "vasnwprintf.h"
     35  1.1  christos #else
     36  1.1  christos # include "vasnprintf.h"
     37  1.1  christos #endif
     38  1.1  christos 
     39  1.1  christos #include <stdio.h>	/* snprintf(), sprintf() */
     40  1.1  christos #include <stdlib.h>	/* abort(), malloc(), realloc(), free() */
     41  1.1  christos #include <string.h>	/* memcpy(), strlen() */
     42  1.1  christos #include <errno.h>	/* errno */
     43  1.1  christos #include <limits.h>	/* CHAR_BIT, INT_MAX */
     44  1.1  christos #include <float.h>	/* DBL_MAX_EXP, LDBL_MAX_EXP */
     45  1.1  christos #if WIDE_CHAR_VERSION
     46  1.1  christos # include "wprintf-parse.h"
     47  1.1  christos #else
     48  1.1  christos # include "printf-parse.h"
     49  1.1  christos #endif
     50  1.1  christos 
     51  1.1  christos /* Checked size_t computations.  */
     52  1.1  christos #include "xsize.h"
     53  1.1  christos 
     54  1.1  christos /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
     55  1.1  christos #ifndef EOVERFLOW
     56  1.1  christos # define EOVERFLOW E2BIG
     57  1.1  christos #endif
     58  1.1  christos 
     59  1.1  christos #ifdef HAVE_WCHAR_T
     60  1.1  christos # ifdef HAVE_WCSLEN
     61  1.1  christos #  define local_wcslen wcslen
     62  1.1  christos # else
     63  1.1  christos    /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
     64  1.1  christos       a dependency towards this library, here is a local substitute.
     65  1.1  christos       Define this substitute only once, even if this file is included
     66  1.1  christos       twice in the same compilation unit.  */
     67  1.1  christos #  ifndef local_wcslen_defined
     68  1.1  christos #   define local_wcslen_defined 1
     69  1.1  christos static size_t
     70  1.1  christos local_wcslen (const wchar_t *s)
     71  1.1  christos {
     72  1.1  christos   const wchar_t *ptr;
     73  1.1  christos 
     74  1.1  christos   for (ptr = s; *ptr != (wchar_t) 0; ptr++)
     75  1.1  christos     ;
     76  1.1  christos   return ptr - s;
     77  1.1  christos }
     78  1.1  christos #  endif
     79  1.1  christos # endif
     80  1.1  christos #endif
     81  1.1  christos 
     82  1.1  christos #if WIDE_CHAR_VERSION
     83  1.1  christos # define VASNPRINTF vasnwprintf
     84  1.1  christos # define CHAR_T wchar_t
     85  1.1  christos # define DIRECTIVE wchar_t_directive
     86  1.1  christos # define DIRECTIVES wchar_t_directives
     87  1.1  christos # define PRINTF_PARSE wprintf_parse
     88  1.1  christos # define USE_SNPRINTF 1
     89  1.1  christos # if HAVE_DECL__SNWPRINTF
     90  1.1  christos    /* On Windows, the function swprintf() has a different signature than
     91  1.1  christos       on Unix; we use the _snwprintf() function instead.  */
     92  1.1  christos #  define SNPRINTF _snwprintf
     93  1.1  christos # else
     94  1.1  christos    /* Unix.  */
     95  1.1  christos #  define SNPRINTF swprintf
     96  1.1  christos # endif
     97  1.1  christos #else
     98  1.1  christos # define VASNPRINTF vasnprintf
     99  1.1  christos # define CHAR_T char
    100  1.1  christos # define DIRECTIVE char_directive
    101  1.1  christos # define DIRECTIVES char_directives
    102  1.1  christos # define PRINTF_PARSE printf_parse
    103  1.1  christos # define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
    104  1.1  christos # if HAVE_DECL__SNPRINTF
    105  1.1  christos    /* Windows.  */
    106  1.1  christos #  define SNPRINTF _snprintf
    107  1.1  christos # else
    108  1.1  christos    /* Unix.  */
    109  1.1  christos #  define SNPRINTF snprintf
    110  1.1  christos # endif
    111  1.1  christos #endif
    112  1.1  christos 
    113  1.1  christos CHAR_T *
    114  1.1  christos VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
    115  1.1  christos {
    116  1.1  christos   DIRECTIVES d;
    117  1.1  christos   arguments a;
    118  1.1  christos 
    119  1.1  christos   if (PRINTF_PARSE (format, &d, &a) < 0)
    120  1.1  christos     {
    121  1.1  christos       errno = EINVAL;
    122  1.1  christos       return NULL;
    123  1.1  christos     }
    124  1.1  christos 
    125  1.1  christos #define CLEANUP() \
    126  1.1  christos   free (d.dir);								\
    127  1.1  christos   if (a.arg)								\
    128  1.1  christos     free (a.arg);
    129  1.1  christos 
    130  1.1  christos   if (printf_fetchargs (args, &a) < 0)
    131  1.1  christos     {
    132  1.1  christos       CLEANUP ();
    133  1.1  christos       errno = EINVAL;
    134  1.1  christos       return NULL;
    135  1.1  christos     }
    136  1.1  christos 
    137  1.1  christos   {
    138  1.1  christos     size_t buf_neededlength;
    139  1.1  christos     CHAR_T *buf;
    140  1.1  christos     CHAR_T *buf_malloced;
    141  1.1  christos     const CHAR_T *cp;
    142  1.1  christos     size_t i;
    143  1.1  christos     DIRECTIVE *dp;
    144  1.1  christos     /* Output string accumulator.  */
    145  1.1  christos     CHAR_T *result;
    146  1.1  christos     size_t allocated;
    147  1.1  christos     size_t length;
    148  1.1  christos 
    149  1.1  christos     /* Allocate a small buffer that will hold a directive passed to
    150  1.1  christos        sprintf or snprintf.  */
    151  1.1  christos     buf_neededlength =
    152  1.1  christos       xsum4 (7, d.max_width_length, d.max_precision_length, 6);
    153  1.1  christos #if HAVE_ALLOCA
    154  1.1  christos     if (buf_neededlength < 4000 / sizeof (CHAR_T))
    155  1.1  christos       {
    156  1.1  christos 	buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
    157  1.1  christos 	buf_malloced = NULL;
    158  1.1  christos       }
    159  1.1  christos     else
    160  1.1  christos #endif
    161  1.1  christos       {
    162  1.1  christos 	size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
    163  1.1  christos 	if (size_overflow_p (buf_memsize))
    164  1.1  christos 	  goto out_of_memory_1;
    165  1.1  christos 	buf = (CHAR_T *) malloc (buf_memsize);
    166  1.1  christos 	if (buf == NULL)
    167  1.1  christos 	  goto out_of_memory_1;
    168  1.1  christos 	buf_malloced = buf;
    169  1.1  christos       }
    170  1.1  christos 
    171  1.1  christos     if (resultbuf != NULL)
    172  1.1  christos       {
    173  1.1  christos 	result = resultbuf;
    174  1.1  christos 	allocated = *lengthp;
    175  1.1  christos       }
    176  1.1  christos     else
    177  1.1  christos       {
    178  1.1  christos 	result = NULL;
    179  1.1  christos 	allocated = 0;
    180  1.1  christos       }
    181  1.1  christos     length = 0;
    182  1.1  christos     /* Invariants:
    183  1.1  christos        result is either == resultbuf or == NULL or malloc-allocated.
    184  1.1  christos        If length > 0, then result != NULL.  */
    185  1.1  christos 
    186  1.1  christos     /* Ensures that allocated >= needed.  Aborts through a jump to
    187  1.1  christos        out_of_memory if needed is SIZE_MAX or otherwise too big.  */
    188  1.1  christos #define ENSURE_ALLOCATION(needed) \
    189  1.1  christos     if ((needed) > allocated)						     \
    190  1.1  christos       {									     \
    191  1.1  christos 	size_t memory_size;						     \
    192  1.1  christos 	CHAR_T *memory;							     \
    193  1.1  christos 									     \
    194  1.1  christos 	allocated = (allocated > 0 ? xtimes (allocated, 2) : 12);	     \
    195  1.1  christos 	if ((needed) > allocated)					     \
    196  1.1  christos 	  allocated = (needed);						     \
    197  1.1  christos 	memory_size = xtimes (allocated, sizeof (CHAR_T));		     \
    198  1.1  christos 	if (size_overflow_p (memory_size))				     \
    199  1.1  christos 	  goto out_of_memory;						     \
    200  1.1  christos 	if (result == resultbuf || result == NULL)			     \
    201  1.1  christos 	  memory = (CHAR_T *) malloc (memory_size);			     \
    202  1.1  christos 	else								     \
    203  1.1  christos 	  memory = (CHAR_T *) realloc (result, memory_size);		     \
    204  1.1  christos 	if (memory == NULL)						     \
    205  1.1  christos 	  goto out_of_memory;						     \
    206  1.1  christos 	if (result == resultbuf && length > 0)				     \
    207  1.1  christos 	  memcpy (memory, result, length * sizeof (CHAR_T));		     \
    208  1.1  christos 	result = memory;						     \
    209  1.1  christos       }
    210  1.1  christos 
    211  1.1  christos     for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
    212  1.1  christos       {
    213  1.1  christos 	if (cp != dp->dir_start)
    214  1.1  christos 	  {
    215  1.1  christos 	    size_t n = dp->dir_start - cp;
    216  1.1  christos 	    size_t augmented_length = xsum (length, n);
    217  1.1  christos 
    218  1.1  christos 	    ENSURE_ALLOCATION (augmented_length);
    219  1.1  christos 	    memcpy (result + length, cp, n * sizeof (CHAR_T));
    220  1.1  christos 	    length = augmented_length;
    221  1.1  christos 	  }
    222  1.1  christos 	if (i == d.count)
    223  1.1  christos 	  break;
    224  1.1  christos 
    225  1.1  christos 	/* Execute a single directive.  */
    226  1.1  christos 	if (dp->conversion == '%')
    227  1.1  christos 	  {
    228  1.1  christos 	    size_t augmented_length;
    229  1.1  christos 
    230  1.1  christos 	    if (!(dp->arg_index == ARG_NONE))
    231  1.1  christos 	      abort ();
    232  1.1  christos 	    augmented_length = xsum (length, 1);
    233  1.1  christos 	    ENSURE_ALLOCATION (augmented_length);
    234  1.1  christos 	    result[length] = '%';
    235  1.1  christos 	    length = augmented_length;
    236  1.1  christos 	  }
    237  1.1  christos 	else
    238  1.1  christos 	  {
    239  1.1  christos 	    if (!(dp->arg_index != ARG_NONE))
    240  1.1  christos 	      abort ();
    241  1.1  christos 
    242  1.1  christos 	    if (dp->conversion == 'n')
    243  1.1  christos 	      {
    244  1.1  christos 		switch (a.arg[dp->arg_index].type)
    245  1.1  christos 		  {
    246  1.1  christos 		  case TYPE_COUNT_SCHAR_POINTER:
    247  1.1  christos 		    *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
    248  1.1  christos 		    break;
    249  1.1  christos 		  case TYPE_COUNT_SHORT_POINTER:
    250  1.1  christos 		    *a.arg[dp->arg_index].a.a_count_short_pointer = length;
    251  1.1  christos 		    break;
    252  1.1  christos 		  case TYPE_COUNT_INT_POINTER:
    253  1.1  christos 		    *a.arg[dp->arg_index].a.a_count_int_pointer = length;
    254  1.1  christos 		    break;
    255  1.1  christos 		  case TYPE_COUNT_LONGINT_POINTER:
    256  1.1  christos 		    *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
    257  1.1  christos 		    break;
    258  1.1  christos #ifdef HAVE_LONG_LONG
    259  1.1  christos 		  case TYPE_COUNT_LONGLONGINT_POINTER:
    260  1.1  christos 		    *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
    261  1.1  christos 		    break;
    262  1.1  christos #endif
    263  1.1  christos 		  default:
    264  1.1  christos 		    abort ();
    265  1.1  christos 		  }
    266  1.1  christos 	      }
    267  1.1  christos 	    else
    268  1.1  christos 	      {
    269  1.1  christos 		arg_type type = a.arg[dp->arg_index].type;
    270  1.1  christos 		CHAR_T *p;
    271  1.1  christos 		unsigned int prefix_count;
    272  1.1  christos 		int prefixes[2];
    273  1.1  christos #if !USE_SNPRINTF
    274  1.1  christos 		size_t tmp_length;
    275  1.1  christos 		CHAR_T tmpbuf[700];
    276  1.1  christos 		CHAR_T *tmp;
    277  1.1  christos 
    278  1.1  christos 		/* Allocate a temporary buffer of sufficient size for calling
    279  1.1  christos 		   sprintf.  */
    280  1.1  christos 		{
    281  1.1  christos 		  size_t width;
    282  1.1  christos 		  size_t precision;
    283  1.1  christos 
    284  1.1  christos 		  width = 0;
    285  1.1  christos 		  if (dp->width_start != dp->width_end)
    286  1.1  christos 		    {
    287  1.1  christos 		      if (dp->width_arg_index != ARG_NONE)
    288  1.1  christos 			{
    289  1.1  christos 			  int arg;
    290  1.1  christos 
    291  1.1  christos 			  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
    292  1.1  christos 			    abort ();
    293  1.1  christos 			  arg = a.arg[dp->width_arg_index].a.a_int;
    294  1.1  christos 			  width = (arg < 0 ? (unsigned int) (-arg) : arg);
    295  1.1  christos 			}
    296  1.1  christos 		      else
    297  1.1  christos 			{
    298  1.1  christos 			  const CHAR_T *digitp = dp->width_start;
    299  1.1  christos 
    300  1.1  christos 			  do
    301  1.1  christos 			    width = xsum (xtimes (width, 10), *digitp++ - '0');
    302  1.1  christos 			  while (digitp != dp->width_end);
    303  1.1  christos 			}
    304  1.1  christos 		    }
    305  1.1  christos 
    306  1.1  christos 		  precision = 6;
    307  1.1  christos 		  if (dp->precision_start != dp->precision_end)
    308  1.1  christos 		    {
    309  1.1  christos 		      if (dp->precision_arg_index != ARG_NONE)
    310  1.1  christos 			{
    311  1.1  christos 			  int arg;
    312  1.1  christos 
    313  1.1  christos 			  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
    314  1.1  christos 			    abort ();
    315  1.1  christos 			  arg = a.arg[dp->precision_arg_index].a.a_int;
    316  1.1  christos 			  precision = (arg < 0 ? 0 : arg);
    317  1.1  christos 			}
    318  1.1  christos 		      else
    319  1.1  christos 			{
    320  1.1  christos 			  const CHAR_T *digitp = dp->precision_start + 1;
    321  1.1  christos 
    322  1.1  christos 			  precision = 0;
    323  1.1  christos 			  while (digitp != dp->precision_end)
    324  1.1  christos 			    precision = xsum (xtimes (precision, 10), *digitp++ - '0');
    325  1.1  christos 			}
    326  1.1  christos 		    }
    327  1.1  christos 
    328  1.1  christos 		  switch (dp->conversion)
    329  1.1  christos 		    {
    330  1.1  christos 
    331  1.1  christos 		    case 'd': case 'i': case 'u':
    332  1.1  christos # ifdef HAVE_LONG_LONG
    333  1.1  christos 		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
    334  1.1  christos 			tmp_length =
    335  1.1  christos 			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
    336  1.1  christos 					  * 0.30103 /* binary -> decimal */
    337  1.1  christos 					  * 2 /* estimate for FLAG_GROUP */
    338  1.1  christos 					 )
    339  1.1  christos 			  + 1 /* turn floor into ceil */
    340  1.1  christos 			  + 1; /* account for leading sign */
    341  1.1  christos 		      else
    342  1.1  christos # endif
    343  1.1  christos 		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
    344  1.1  christos 			tmp_length =
    345  1.1  christos 			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
    346  1.1  christos 					  * 0.30103 /* binary -> decimal */
    347  1.1  christos 					  * 2 /* estimate for FLAG_GROUP */
    348  1.1  christos 					 )
    349  1.1  christos 			  + 1 /* turn floor into ceil */
    350  1.1  christos 			  + 1; /* account for leading sign */
    351  1.1  christos 		      else
    352  1.1  christos 			tmp_length =
    353  1.1  christos 			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
    354  1.1  christos 					  * 0.30103 /* binary -> decimal */
    355  1.1  christos 					  * 2 /* estimate for FLAG_GROUP */
    356  1.1  christos 					 )
    357  1.1  christos 			  + 1 /* turn floor into ceil */
    358  1.1  christos 			  + 1; /* account for leading sign */
    359  1.1  christos 		      break;
    360  1.1  christos 
    361  1.1  christos 		    case 'o':
    362  1.1  christos # ifdef HAVE_LONG_LONG
    363  1.1  christos 		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
    364  1.1  christos 			tmp_length =
    365  1.1  christos 			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
    366  1.1  christos 					  * 0.333334 /* binary -> octal */
    367  1.1  christos 					 )
    368  1.1  christos 			  + 1 /* turn floor into ceil */
    369  1.1  christos 			  + 1; /* account for leading sign */
    370  1.1  christos 		      else
    371  1.1  christos # endif
    372  1.1  christos 		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
    373  1.1  christos 			tmp_length =
    374  1.1  christos 			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
    375  1.1  christos 					  * 0.333334 /* binary -> octal */
    376  1.1  christos 					 )
    377  1.1  christos 			  + 1 /* turn floor into ceil */
    378  1.1  christos 			  + 1; /* account for leading sign */
    379  1.1  christos 		      else
    380  1.1  christos 			tmp_length =
    381  1.1  christos 			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
    382  1.1  christos 					  * 0.333334 /* binary -> octal */
    383  1.1  christos 					 )
    384  1.1  christos 			  + 1 /* turn floor into ceil */
    385  1.1  christos 			  + 1; /* account for leading sign */
    386  1.1  christos 		      break;
    387  1.1  christos 
    388  1.1  christos 		    case 'x': case 'X':
    389  1.1  christos # ifdef HAVE_LONG_LONG
    390  1.1  christos 		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
    391  1.1  christos 			tmp_length =
    392  1.1  christos 			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
    393  1.1  christos 					  * 0.25 /* binary -> hexadecimal */
    394  1.1  christos 					 )
    395  1.1  christos 			  + 1 /* turn floor into ceil */
    396  1.1  christos 			  + 2; /* account for leading sign or alternate form */
    397  1.1  christos 		      else
    398  1.1  christos # endif
    399  1.1  christos 		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
    400  1.1  christos 			tmp_length =
    401  1.1  christos 			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
    402  1.1  christos 					  * 0.25 /* binary -> hexadecimal */
    403  1.1  christos 					 )
    404  1.1  christos 			  + 1 /* turn floor into ceil */
    405  1.1  christos 			  + 2; /* account for leading sign or alternate form */
    406  1.1  christos 		      else
    407  1.1  christos 			tmp_length =
    408  1.1  christos 			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
    409  1.1  christos 					  * 0.25 /* binary -> hexadecimal */
    410  1.1  christos 					 )
    411  1.1  christos 			  + 1 /* turn floor into ceil */
    412  1.1  christos 			  + 2; /* account for leading sign or alternate form */
    413  1.1  christos 		      break;
    414  1.1  christos 
    415  1.1  christos 		    case 'f': case 'F':
    416  1.1  christos # ifdef HAVE_LONG_DOUBLE
    417  1.1  christos 		      if (type == TYPE_LONGDOUBLE)
    418  1.1  christos 			tmp_length =
    419  1.1  christos 			  (unsigned int) (LDBL_MAX_EXP
    420  1.1  christos 					  * 0.30103 /* binary -> decimal */
    421  1.1  christos 					  * 2 /* estimate for FLAG_GROUP */
    422  1.1  christos 					 )
    423  1.1  christos 			  + 1 /* turn floor into ceil */
    424  1.1  christos 			  + 10; /* sign, decimal point etc. */
    425  1.1  christos 		      else
    426  1.1  christos # endif
    427  1.1  christos 			tmp_length =
    428  1.1  christos 			  (unsigned int) (DBL_MAX_EXP
    429  1.1  christos 					  * 0.30103 /* binary -> decimal */
    430  1.1  christos 					  * 2 /* estimate for FLAG_GROUP */
    431  1.1  christos 					 )
    432  1.1  christos 			  + 1 /* turn floor into ceil */
    433  1.1  christos 			  + 10; /* sign, decimal point etc. */
    434  1.1  christos 		      tmp_length = xsum (tmp_length, precision);
    435  1.1  christos 		      break;
    436  1.1  christos 
    437  1.1  christos 		    case 'e': case 'E': case 'g': case 'G':
    438  1.1  christos 		    case 'a': case 'A':
    439  1.1  christos 		      tmp_length =
    440  1.1  christos 			12; /* sign, decimal point, exponent etc. */
    441  1.1  christos 		      tmp_length = xsum (tmp_length, precision);
    442  1.1  christos 		      break;
    443  1.1  christos 
    444  1.1  christos 		    case 'c':
    445  1.1  christos # if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
    446  1.1  christos 		      if (type == TYPE_WIDE_CHAR)
    447  1.1  christos 			tmp_length = MB_CUR_MAX;
    448  1.1  christos 		      else
    449  1.1  christos # endif
    450  1.1  christos 			tmp_length = 1;
    451  1.1  christos 		      break;
    452  1.1  christos 
    453  1.1  christos 		    case 's':
    454  1.1  christos # ifdef HAVE_WCHAR_T
    455  1.1  christos 		      if (type == TYPE_WIDE_STRING)
    456  1.1  christos 			{
    457  1.1  christos 			  tmp_length =
    458  1.1  christos 			    local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
    459  1.1  christos 
    460  1.1  christos #  if !WIDE_CHAR_VERSION
    461  1.1  christos 			  tmp_length = xtimes (tmp_length, MB_CUR_MAX);
    462  1.1  christos #  endif
    463  1.1  christos 			}
    464  1.1  christos 		      else
    465  1.1  christos # endif
    466  1.1  christos 			tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
    467  1.1  christos 		      break;
    468  1.1  christos 
    469  1.1  christos 		    case 'p':
    470  1.1  christos 		      tmp_length =
    471  1.1  christos 			(unsigned int) (sizeof (void *) * CHAR_BIT
    472  1.1  christos 					* 0.25 /* binary -> hexadecimal */
    473  1.1  christos 				       )
    474  1.1  christos 			  + 1 /* turn floor into ceil */
    475  1.1  christos 			  + 2; /* account for leading 0x */
    476  1.1  christos 		      break;
    477  1.1  christos 
    478  1.1  christos 		    default:
    479  1.1  christos 		      abort ();
    480  1.1  christos 		    }
    481  1.1  christos 
    482  1.1  christos 		  if (tmp_length < width)
    483  1.1  christos 		    tmp_length = width;
    484  1.1  christos 
    485  1.1  christos 		  tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
    486  1.1  christos 		}
    487  1.1  christos 
    488  1.1  christos 		if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
    489  1.1  christos 		  tmp = tmpbuf;
    490  1.1  christos 		else
    491  1.1  christos 		  {
    492  1.1  christos 		    size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
    493  1.1  christos 
    494  1.1  christos 		    if (size_overflow_p (tmp_memsize))
    495  1.1  christos 		      /* Overflow, would lead to out of memory.  */
    496  1.1  christos 		      goto out_of_memory;
    497  1.1  christos 		    tmp = (CHAR_T *) malloc (tmp_memsize);
    498  1.1  christos 		    if (tmp == NULL)
    499  1.1  christos 		      /* Out of memory.  */
    500  1.1  christos 		      goto out_of_memory;
    501  1.1  christos 		  }
    502  1.1  christos #endif
    503  1.1  christos 
    504  1.1  christos 		/* Construct the format string for calling snprintf or
    505  1.1  christos 		   sprintf.  */
    506  1.1  christos 		p = buf;
    507  1.1  christos 		*p++ = '%';
    508  1.1  christos 		if (dp->flags & FLAG_GROUP)
    509  1.1  christos 		  *p++ = '\'';
    510  1.1  christos 		if (dp->flags & FLAG_LEFT)
    511  1.1  christos 		  *p++ = '-';
    512  1.1  christos 		if (dp->flags & FLAG_SHOWSIGN)
    513  1.1  christos 		  *p++ = '+';
    514  1.1  christos 		if (dp->flags & FLAG_SPACE)
    515  1.1  christos 		  *p++ = ' ';
    516  1.1  christos 		if (dp->flags & FLAG_ALT)
    517  1.1  christos 		  *p++ = '#';
    518  1.1  christos 		if (dp->flags & FLAG_ZERO)
    519  1.1  christos 		  *p++ = '0';
    520  1.1  christos 		if (dp->width_start != dp->width_end)
    521  1.1  christos 		  {
    522  1.1  christos 		    size_t n = dp->width_end - dp->width_start;
    523  1.1  christos 		    memcpy (p, dp->width_start, n * sizeof (CHAR_T));
    524  1.1  christos 		    p += n;
    525  1.1  christos 		  }
    526  1.1  christos 		if (dp->precision_start != dp->precision_end)
    527  1.1  christos 		  {
    528  1.1  christos 		    size_t n = dp->precision_end - dp->precision_start;
    529  1.1  christos 		    memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
    530  1.1  christos 		    p += n;
    531  1.1  christos 		  }
    532  1.1  christos 
    533  1.1  christos 		switch (type)
    534  1.1  christos 		  {
    535  1.1  christos #ifdef HAVE_LONG_LONG
    536  1.1  christos 		  case TYPE_LONGLONGINT:
    537  1.1  christos 		  case TYPE_ULONGLONGINT:
    538  1.1  christos 		    *p++ = 'l';
    539  1.1  christos 		    /*FALLTHROUGH*/
    540  1.1  christos #endif
    541  1.1  christos 		  case TYPE_LONGINT:
    542  1.1  christos 		  case TYPE_ULONGINT:
    543  1.1  christos #ifdef HAVE_WINT_T
    544  1.1  christos 		  case TYPE_WIDE_CHAR:
    545  1.1  christos #endif
    546  1.1  christos #ifdef HAVE_WCHAR_T
    547  1.1  christos 		  case TYPE_WIDE_STRING:
    548  1.1  christos #endif
    549  1.1  christos 		    *p++ = 'l';
    550  1.1  christos 		    break;
    551  1.1  christos #ifdef HAVE_LONG_DOUBLE
    552  1.1  christos 		  case TYPE_LONGDOUBLE:
    553  1.1  christos 		    *p++ = 'L';
    554  1.1  christos 		    break;
    555  1.1  christos #endif
    556  1.1  christos 		  default:
    557  1.1  christos 		    break;
    558  1.1  christos 		  }
    559  1.1  christos 		*p = dp->conversion;
    560  1.1  christos #if USE_SNPRINTF
    561  1.1  christos 		p[1] = '%';
    562  1.1  christos 		p[2] = 'n';
    563  1.1  christos 		p[3] = '\0';
    564  1.1  christos #else
    565  1.1  christos 		p[1] = '\0';
    566  1.1  christos #endif
    567  1.1  christos 
    568  1.1  christos 		/* Construct the arguments for calling snprintf or sprintf.  */
    569  1.1  christos 		prefix_count = 0;
    570  1.1  christos 		if (dp->width_arg_index != ARG_NONE)
    571  1.1  christos 		  {
    572  1.1  christos 		    if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
    573  1.1  christos 		      abort ();
    574  1.1  christos 		    prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
    575  1.1  christos 		  }
    576  1.1  christos 		if (dp->precision_arg_index != ARG_NONE)
    577  1.1  christos 		  {
    578  1.1  christos 		    if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
    579  1.1  christos 		      abort ();
    580  1.1  christos 		    prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
    581  1.1  christos 		  }
    582  1.1  christos 
    583  1.1  christos #if USE_SNPRINTF
    584  1.1  christos 		/* Prepare checking whether snprintf returns the count
    585  1.1  christos 		   via %n.  */
    586  1.1  christos 		ENSURE_ALLOCATION (xsum (length, 1));
    587  1.1  christos 		result[length] = '\0';
    588  1.1  christos #endif
    589  1.1  christos 
    590  1.1  christos 		for (;;)
    591  1.1  christos 		  {
    592  1.1  christos 		    size_t maxlen;
    593  1.1  christos 		    int count;
    594  1.1  christos 		    int retcount;
    595  1.1  christos 
    596  1.1  christos 		    maxlen = allocated - length;
    597  1.1  christos 		    count = -1;
    598  1.1  christos 		    retcount = 0;
    599  1.1  christos 
    600  1.1  christos #if USE_SNPRINTF
    601  1.1  christos # define SNPRINTF_BUF(arg) \
    602  1.1  christos 		    switch (prefix_count)				    \
    603  1.1  christos 		      {							    \
    604  1.1  christos 		      case 0:						    \
    605  1.1  christos 			retcount = SNPRINTF (result + length, maxlen, buf,  \
    606  1.1  christos 					     arg, &count);		    \
    607  1.1  christos 			break;						    \
    608  1.1  christos 		      case 1:						    \
    609  1.1  christos 			retcount = SNPRINTF (result + length, maxlen, buf,  \
    610  1.1  christos 					     prefixes[0], arg, &count);	    \
    611  1.1  christos 			break;						    \
    612  1.1  christos 		      case 2:						    \
    613  1.1  christos 			retcount = SNPRINTF (result + length, maxlen, buf,  \
    614  1.1  christos 					     prefixes[0], prefixes[1], arg, \
    615  1.1  christos 					     &count);			    \
    616  1.1  christos 			break;						    \
    617  1.1  christos 		      default:						    \
    618  1.1  christos 			abort ();					    \
    619  1.1  christos 		      }
    620  1.1  christos #else
    621  1.1  christos # define SNPRINTF_BUF(arg) \
    622  1.1  christos 		    switch (prefix_count)				    \
    623  1.1  christos 		      {							    \
    624  1.1  christos 		      case 0:						    \
    625  1.1  christos 			count = sprintf (tmp, buf, arg);		    \
    626  1.1  christos 			break;						    \
    627  1.1  christos 		      case 1:						    \
    628  1.1  christos 			count = sprintf (tmp, buf, prefixes[0], arg);	    \
    629  1.1  christos 			break;						    \
    630  1.1  christos 		      case 2:						    \
    631  1.1  christos 			count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
    632  1.1  christos 					 arg);				    \
    633  1.1  christos 			break;						    \
    634  1.1  christos 		      default:						    \
    635  1.1  christos 			abort ();					    \
    636  1.1  christos 		      }
    637  1.1  christos #endif
    638  1.1  christos 
    639  1.1  christos 		    switch (type)
    640  1.1  christos 		      {
    641  1.1  christos 		      case TYPE_SCHAR:
    642  1.1  christos 			{
    643  1.1  christos 			  int arg = a.arg[dp->arg_index].a.a_schar;
    644  1.1  christos 			  SNPRINTF_BUF (arg);
    645  1.1  christos 			}
    646  1.1  christos 			break;
    647  1.1  christos 		      case TYPE_UCHAR:
    648  1.1  christos 			{
    649  1.1  christos 			  unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
    650  1.1  christos 			  SNPRINTF_BUF (arg);
    651  1.1  christos 			}
    652  1.1  christos 			break;
    653  1.1  christos 		      case TYPE_SHORT:
    654  1.1  christos 			{
    655  1.1  christos 			  int arg = a.arg[dp->arg_index].a.a_short;
    656  1.1  christos 			  SNPRINTF_BUF (arg);
    657  1.1  christos 			}
    658  1.1  christos 			break;
    659  1.1  christos 		      case TYPE_USHORT:
    660  1.1  christos 			{
    661  1.1  christos 			  unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
    662  1.1  christos 			  SNPRINTF_BUF (arg);
    663  1.1  christos 			}
    664  1.1  christos 			break;
    665  1.1  christos 		      case TYPE_INT:
    666  1.1  christos 			{
    667  1.1  christos 			  int arg = a.arg[dp->arg_index].a.a_int;
    668  1.1  christos 			  SNPRINTF_BUF (arg);
    669  1.1  christos 			}
    670  1.1  christos 			break;
    671  1.1  christos 		      case TYPE_UINT:
    672  1.1  christos 			{
    673  1.1  christos 			  unsigned int arg = a.arg[dp->arg_index].a.a_uint;
    674  1.1  christos 			  SNPRINTF_BUF (arg);
    675  1.1  christos 			}
    676  1.1  christos 			break;
    677  1.1  christos 		      case TYPE_LONGINT:
    678  1.1  christos 			{
    679  1.1  christos 			  long int arg = a.arg[dp->arg_index].a.a_longint;
    680  1.1  christos 			  SNPRINTF_BUF (arg);
    681  1.1  christos 			}
    682  1.1  christos 			break;
    683  1.1  christos 		      case TYPE_ULONGINT:
    684  1.1  christos 			{
    685  1.1  christos 			  unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
    686  1.1  christos 			  SNPRINTF_BUF (arg);
    687  1.1  christos 			}
    688  1.1  christos 			break;
    689  1.1  christos #ifdef HAVE_LONG_LONG
    690  1.1  christos 		      case TYPE_LONGLONGINT:
    691  1.1  christos 			{
    692  1.1  christos 			  long long int arg = a.arg[dp->arg_index].a.a_longlongint;
    693  1.1  christos 			  SNPRINTF_BUF (arg);
    694  1.1  christos 			}
    695  1.1  christos 			break;
    696  1.1  christos 		      case TYPE_ULONGLONGINT:
    697  1.1  christos 			{
    698  1.1  christos 			  unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
    699  1.1  christos 			  SNPRINTF_BUF (arg);
    700  1.1  christos 			}
    701  1.1  christos 			break;
    702  1.1  christos #endif
    703  1.1  christos 		      case TYPE_DOUBLE:
    704  1.1  christos 			{
    705  1.1  christos 			  double arg = a.arg[dp->arg_index].a.a_double;
    706  1.1  christos 			  SNPRINTF_BUF (arg);
    707  1.1  christos 			}
    708  1.1  christos 			break;
    709  1.1  christos #ifdef HAVE_LONG_DOUBLE
    710  1.1  christos 		      case TYPE_LONGDOUBLE:
    711  1.1  christos 			{
    712  1.1  christos 			  long double arg = a.arg[dp->arg_index].a.a_longdouble;
    713  1.1  christos 			  SNPRINTF_BUF (arg);
    714  1.1  christos 			}
    715  1.1  christos 			break;
    716  1.1  christos #endif
    717  1.1  christos 		      case TYPE_CHAR:
    718  1.1  christos 			{
    719  1.1  christos 			  int arg = a.arg[dp->arg_index].a.a_char;
    720  1.1  christos 			  SNPRINTF_BUF (arg);
    721  1.1  christos 			}
    722  1.1  christos 			break;
    723  1.1  christos #ifdef HAVE_WINT_T
    724  1.1  christos 		      case TYPE_WIDE_CHAR:
    725  1.1  christos 			{
    726  1.1  christos 			  wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
    727  1.1  christos 			  SNPRINTF_BUF (arg);
    728  1.1  christos 			}
    729  1.1  christos 			break;
    730  1.1  christos #endif
    731  1.1  christos 		      case TYPE_STRING:
    732  1.1  christos 			{
    733  1.1  christos 			  const char *arg = a.arg[dp->arg_index].a.a_string;
    734  1.1  christos 			  SNPRINTF_BUF (arg);
    735  1.1  christos 			}
    736  1.1  christos 			break;
    737  1.1  christos #ifdef HAVE_WCHAR_T
    738  1.1  christos 		      case TYPE_WIDE_STRING:
    739  1.1  christos 			{
    740  1.1  christos 			  const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
    741  1.1  christos 			  SNPRINTF_BUF (arg);
    742  1.1  christos 			}
    743  1.1  christos 			break;
    744  1.1  christos #endif
    745  1.1  christos 		      case TYPE_POINTER:
    746  1.1  christos 			{
    747  1.1  christos 			  void *arg = a.arg[dp->arg_index].a.a_pointer;
    748  1.1  christos 			  SNPRINTF_BUF (arg);
    749  1.1  christos 			}
    750  1.1  christos 			break;
    751  1.1  christos 		      default:
    752  1.1  christos 			abort ();
    753  1.1  christos 		      }
    754  1.1  christos 
    755  1.1  christos #if USE_SNPRINTF
    756  1.1  christos 		    /* Portability: Not all implementations of snprintf()
    757  1.1  christos 		       are ISO C 99 compliant.  Determine the number of
    758  1.1  christos 		       bytes that snprintf() has produced or would have
    759  1.1  christos 		       produced.  */
    760  1.1  christos 		    if (count >= 0)
    761  1.1  christos 		      {
    762  1.1  christos 			/* Verify that snprintf() has NUL-terminated its
    763  1.1  christos 			   result.  */
    764  1.1  christos 			if (count < maxlen && result[length + count] != '\0')
    765  1.1  christos 			  abort ();
    766  1.1  christos 			/* Portability hack.  */
    767  1.1  christos 			if (retcount > count)
    768  1.1  christos 			  count = retcount;
    769  1.1  christos 		      }
    770  1.1  christos 		    else
    771  1.1  christos 		      {
    772  1.1  christos 			/* snprintf() doesn't understand the '%n'
    773  1.1  christos 			   directive.  */
    774  1.1  christos 			if (p[1] != '\0')
    775  1.1  christos 			  {
    776  1.1  christos 			    /* Don't use the '%n' directive; instead, look
    777  1.1  christos 			       at the snprintf() return value.  */
    778  1.1  christos 			    p[1] = '\0';
    779  1.1  christos 			    continue;
    780  1.1  christos 			  }
    781  1.1  christos 			else
    782  1.1  christos 			  {
    783  1.1  christos 			    /* Look at the snprintf() return value.  */
    784  1.1  christos 			    if (retcount < 0)
    785  1.1  christos 			      {
    786  1.1  christos 				/* HP-UX 10.20 snprintf() is doubly deficient:
    787  1.1  christos 				   It doesn't understand the '%n' directive,
    788  1.1  christos 				   *and* it returns -1 (rather than the length
    789  1.1  christos 				   that would have been required) when the
    790  1.1  christos 				   buffer is too small.  */
    791  1.1  christos 				size_t bigger_need =
    792  1.1  christos 				  xsum (xtimes (allocated, 2), 12);
    793  1.1  christos 				ENSURE_ALLOCATION (bigger_need);
    794  1.1  christos 				continue;
    795  1.1  christos 			      }
    796  1.1  christos 			    else
    797  1.1  christos 			      count = retcount;
    798  1.1  christos 			  }
    799  1.1  christos 		      }
    800  1.1  christos #endif
    801  1.1  christos 
    802  1.1  christos 		    /* Attempt to handle failure.  */
    803  1.1  christos 		    if (count < 0)
    804  1.1  christos 		      {
    805  1.1  christos 			if (!(result == resultbuf || result == NULL))
    806  1.1  christos 			  free (result);
    807  1.1  christos 			if (buf_malloced != NULL)
    808  1.1  christos 			  free (buf_malloced);
    809  1.1  christos 			CLEANUP ();
    810  1.1  christos 			errno = EINVAL;
    811  1.1  christos 			return NULL;
    812  1.1  christos 		      }
    813  1.1  christos 
    814  1.1  christos #if !USE_SNPRINTF
    815  1.1  christos 		    if (count >= tmp_length)
    816  1.1  christos 		      /* tmp_length was incorrectly calculated - fix the
    817  1.1  christos 			 code above!  */
    818  1.1  christos 		      abort ();
    819  1.1  christos #endif
    820  1.1  christos 
    821  1.1  christos 		    /* Make room for the result.  */
    822  1.1  christos 		    if (count >= maxlen)
    823  1.1  christos 		      {
    824  1.1  christos 			/* Need at least count bytes.  But allocate
    825  1.1  christos 			   proportionally, to avoid looping eternally if
    826  1.1  christos 			   snprintf() reports a too small count.  */
    827  1.1  christos 			size_t n =
    828  1.1  christos 			  xmax (xsum (length, count), xtimes (allocated, 2));
    829  1.1  christos 
    830  1.1  christos 			ENSURE_ALLOCATION (n);
    831  1.1  christos #if USE_SNPRINTF
    832  1.1  christos 			continue;
    833  1.1  christos #endif
    834  1.1  christos 		      }
    835  1.1  christos 
    836  1.1  christos #if USE_SNPRINTF
    837  1.1  christos 		    /* The snprintf() result did fit.  */
    838  1.1  christos #else
    839  1.1  christos 		    /* Append the sprintf() result.  */
    840  1.1  christos 		    memcpy (result + length, tmp, count * sizeof (CHAR_T));
    841  1.1  christos 		    if (tmp != tmpbuf)
    842  1.1  christos 		      free (tmp);
    843  1.1  christos #endif
    844  1.1  christos 
    845  1.1  christos 		    length += count;
    846  1.1  christos 		    break;
    847  1.1  christos 		  }
    848  1.1  christos 	      }
    849  1.1  christos 	  }
    850  1.1  christos       }
    851  1.1  christos 
    852  1.1  christos     /* Add the final NUL.  */
    853  1.1  christos     ENSURE_ALLOCATION (xsum (length, 1));
    854  1.1  christos     result[length] = '\0';
    855  1.1  christos 
    856  1.1  christos     if (result != resultbuf && length + 1 < allocated)
    857  1.1  christos       {
    858  1.1  christos 	/* Shrink the allocated memory if possible.  */
    859  1.1  christos 	CHAR_T *memory;
    860  1.1  christos 
    861  1.1  christos 	memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
    862  1.1  christos 	if (memory != NULL)
    863  1.1  christos 	  result = memory;
    864  1.1  christos       }
    865  1.1  christos 
    866  1.1  christos     if (buf_malloced != NULL)
    867  1.1  christos       free (buf_malloced);
    868  1.1  christos     CLEANUP ();
    869  1.1  christos     *lengthp = length;
    870  1.1  christos     if (length > INT_MAX)
    871  1.1  christos       goto length_overflow;
    872  1.1  christos     return result;
    873  1.1  christos 
    874  1.1  christos   length_overflow:
    875  1.1  christos     /* We could produce such a big string, but its length doesn't fit into
    876  1.1  christos        an 'int'.  POSIX says that snprintf() fails with errno = EOVERFLOW in
    877  1.1  christos        this case.  */
    878  1.1  christos     if (result != resultbuf)
    879  1.1  christos       free (result);
    880  1.1  christos     errno = EOVERFLOW;
    881  1.1  christos     return NULL;
    882  1.1  christos 
    883  1.1  christos   out_of_memory:
    884  1.1  christos     if (!(result == resultbuf || result == NULL))
    885  1.1  christos       free (result);
    886  1.1  christos     if (buf_malloced != NULL)
    887  1.1  christos       free (buf_malloced);
    888  1.1  christos   out_of_memory_1:
    889  1.1  christos     CLEANUP ();
    890  1.1  christos     errno = ENOMEM;
    891  1.1  christos     return NULL;
    892  1.1  christos   }
    893  1.1  christos }
    894  1.1  christos 
    895  1.1  christos #undef SNPRINTF
    896  1.1  christos #undef USE_SNPRINTF
    897  1.1  christos #undef PRINTF_PARSE
    898  1.1  christos #undef DIRECTIVES
    899  1.1  christos #undef DIRECTIVE
    900  1.1  christos #undef CHAR_T
    901  1.1  christos #undef VASNPRINTF
    902