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