1/* vsprintf with automatic memory allocation.
2   Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
3
4   This program is free software; you can redistribute it and/or modify it
5   under the terms of the GNU Library General Public License as published
6   by 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 GNU
12   Library General Public License for more details.
13
14   You should have received a copy of the GNU Library General Public
15   License along with this program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17   USA.  */
18
19#ifndef _WIN32
20/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
21   This must come before <config.h> because <config.h> may include
22   <features.h>, and once <features.h> has been included, it's too late.  */
23#ifndef _GNU_SOURCE
24# define _GNU_SOURCE    1
25#endif
26#endif
27
28#ifdef HAVE_CONFIG_H
29# include <config.h>
30#endif
31#include "glib/galloca.h"
32
33#include "g-gnulib.h"
34
35/* Specification.  */
36#include "vasnprintf.h"
37
38#include <stdio.h>	/* snprintf(), sprintf() */
39#include <stdlib.h>	/* abort(), malloc(), realloc(), free() */
40#include <string.h>	/* memcpy(), strlen() */
41#include <errno.h>	/* errno */
42#include <limits.h>	/* CHAR_BIT */
43#include <float.h>	/* DBL_MAX_EXP, LDBL_MAX_EXP */
44#include "printf-parse.h"
45
46#ifdef HAVE_WCHAR_T
47# ifdef HAVE_WCSLEN
48#  define local_wcslen wcslen
49# else
50   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
51      a dependency towards this library, here is a local substitute.
52      Define this substitute only once, even if this file is included
53      twice in the same compilation unit.  */
54#  ifndef local_wcslen_defined
55#   define local_wcslen_defined 1
56static size_t
57local_wcslen (const wchar_t *s)
58{
59  const wchar_t *ptr;
60
61  for (ptr = s; *ptr != (wchar_t) 0; ptr++)
62    ;
63  return ptr - s;
64}
65#  endif
66# endif
67#endif
68
69/* For those losing systems which don't have 'alloca' we have to add
70   some additional code emulating it.  */
71#ifdef HAVE_ALLOCA
72# define freea(p) /* nothing */
73#else
74# define alloca(n) malloc (n)
75# define freea(p) free (p)
76#endif
77
78#ifndef HAVE_LONG_LONG_FORMAT
79static int
80print_long_long (char *buf,
81		 int len,
82		 int width,
83		 int precision,
84		 unsigned long flags,
85		 char conversion,
86		 unsigned long long number)
87{
88  int negative = FALSE;
89  char buffer[128];
90  char *bufferend;
91  char *pointer;
92  int base;
93  static const char *upper = "0123456789ABCDEFX";
94  static const char *lower = "0123456789abcdefx";
95  const char *digits;
96  int i;
97  char *p;
98  int count;
99
100#define EMIT(c)           \
101  if (p - buf == len - 1) \
102    {                     \
103      *p++ = '\0';        \
104      return len;         \
105    }                     \
106  else                    \
107    *p++ = c;
108
109  p = buf;
110
111  switch (conversion)
112    {
113    case 'o':
114      base = 8;
115      digits = lower;
116      negative = FALSE;
117      break;
118    case 'x':
119      base = 16;
120      digits = lower;
121      negative = FALSE;
122      break;
123    case 'X':
124      base = 16;
125      digits = upper;
126      negative = FALSE;
127      break;
128    default:
129      base = 10;
130      digits = lower;
131      negative = (long long)number < 0;
132      if (negative)
133	number = -((long long)number);
134      break;
135    }
136
137  /* Build number */
138  pointer = bufferend = &buffer[sizeof(buffer) - 1];
139  *pointer-- = '\0';
140  for (i = 1; i < (int)sizeof(buffer); i++)
141    {
142      *pointer-- = digits[number % base];
143      number /= base;
144      if (number == 0)
145	break;
146    }
147
148  /* Adjust width */
149  width -= (bufferend - pointer) - 1;
150
151  /* Adjust precision */
152  if (precision != -1)
153    {
154      precision -= (bufferend - pointer) - 1;
155      if (precision < 0)
156	precision = 0;
157      flags |= FLAG_ZERO;
158    }
159
160  /* Adjust width further */
161  if (negative || (flags & FLAG_SHOWSIGN) || (flags & FLAG_SPACE))
162    width--;
163  if (flags & FLAG_ALT)
164    {
165      switch (base)
166	{
167	case 16:
168	  width -= 2;
169	  break;
170	case 8:
171	  width--;
172	  break;
173        default:
174	  break;
175	}
176    }
177
178  /* Output prefixes spaces if needed */
179  if (! ((flags & FLAG_LEFT) ||
180	 ((flags & FLAG_ZERO) && (precision == -1))))
181    {
182      count = (precision == -1) ? 0 : precision;
183      while (width-- > count)
184	*p++ = ' ';
185    }
186
187  /* width has been adjusted for signs and alternatives */
188  if (negative)
189    {
190      EMIT ('-');
191    }
192  else if (flags & FLAG_SHOWSIGN)
193    {
194      EMIT('+');
195    }
196  else if (flags & FLAG_SPACE)
197    {
198      EMIT(' ');
199    }
200
201  if (flags & FLAG_ALT)
202    {
203      switch (base)
204	{
205	case 8:
206	  EMIT('0');
207	  break;
208	case 16:
209	  EMIT('0');
210	  EMIT(digits[16]);
211	  break;
212	default:
213	  break;
214	} /* switch base */
215    }
216
217  /* Output prefixed zero padding if needed */
218  if (flags & FLAG_ZERO)
219    {
220      if (precision == -1)
221	precision = width;
222      while (precision-- > 0)
223	{
224	  EMIT('0');
225	  width--;
226	}
227    }
228
229  /* Output the number itself */
230  while (*(++pointer))
231    {
232      EMIT(*pointer);
233    }
234
235  /* Output trailing spaces if needed */
236  if (flags & FLAG_LEFT)
237    {
238      while (width-- > 0)
239	EMIT(' ');
240    }
241
242  EMIT('\0');
243
244  return p - buf - 1;
245}
246#endif
247
248char *
249vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
250{
251  char_directives d;
252  arguments a;
253
254  if (printf_parse (format, &d, &a) < 0)
255    {
256      errno = EINVAL;
257      return NULL;
258    }
259
260#define CLEANUP() \
261  free (d.dir);								\
262  if (a.arg)								\
263    free (a.arg);
264
265  if (printf_fetchargs (args, &a) < 0)
266    {
267      CLEANUP ();
268      errno = EINVAL;
269      return NULL;
270    }
271
272  {
273    char *buf =
274      (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);
275    const char *cp;
276    unsigned int i;
277    char_directive *dp;
278    /* Output string accumulator.  */
279    char *result;
280    size_t allocated;
281    size_t length;
282
283    if (resultbuf != NULL)
284      {
285	result = resultbuf;
286	allocated = *lengthp;
287      }
288    else
289      {
290	result = NULL;
291	allocated = 0;
292      }
293    length = 0;
294    /* Invariants:
295       result is either == resultbuf or == NULL or malloc-allocated.
296       If length > 0, then result != NULL.  */
297
298#define ENSURE_ALLOCATION(needed) \
299    if ((needed) > allocated)						\
300      {									\
301	char *memory;							\
302									\
303	allocated = (allocated > 0 ? 2 * allocated : 12);		\
304	if ((needed) > allocated)					\
305	  allocated = (needed);						\
306	if (result == resultbuf || result == NULL)			\
307	  memory = (char *) malloc (allocated);				\
308	else								\
309	  memory = (char *) realloc (result, allocated);		\
310									\
311	if (memory == NULL)						\
312	  {								\
313	    if (!(result == resultbuf || result == NULL))		\
314	      free (result);						\
315	    freea (buf);						\
316	    CLEANUP ();							\
317	    errno = ENOMEM;						\
318	    return NULL;						\
319	  }								\
320	if (result == resultbuf && length > 0)				\
321	  memcpy (memory, result, length);				\
322	result = memory;						\
323      }
324
325    for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
326      {
327	if (cp != dp->dir_start)
328	  {
329	    size_t n = dp->dir_start - cp;
330
331	    ENSURE_ALLOCATION (length + n);
332	    memcpy (result + length, cp, n);
333	    length += n;
334	  }
335	if (i == d.count)
336	  break;
337
338	/* Execute a single directive.  */
339	if (dp->conversion == '%')
340	  {
341	    if (!(dp->arg_index < 0))
342	      abort ();
343	    ENSURE_ALLOCATION (length + 1);
344	    result[length] = '%';
345	    length += 1;
346	  }
347	else
348	  {
349	    if (!(dp->arg_index >= 0))
350	      abort ();
351
352	    if (dp->conversion == 'n')
353	      {
354		switch (a.arg[dp->arg_index].type)
355		  {
356		  case TYPE_COUNT_SCHAR_POINTER:
357		    *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
358		    break;
359		  case TYPE_COUNT_SHORT_POINTER:
360		    *a.arg[dp->arg_index].a.a_count_short_pointer = length;
361		    break;
362		  case TYPE_COUNT_INT_POINTER:
363		    *a.arg[dp->arg_index].a.a_count_int_pointer = length;
364		    break;
365		  case TYPE_COUNT_LONGINT_POINTER:
366		    *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
367		    break;
368#ifdef HAVE_LONG_LONG
369		  case TYPE_COUNT_LONGLONGINT_POINTER:
370		    *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
371		    break;
372#endif
373		  default:
374		    abort ();
375		  }
376	      }
377	    else
378	      {
379		arg_type type = a.arg[dp->arg_index].type;
380		char *p;
381		unsigned int prefix_count;
382		int prefixes[2];
383#if !HAVE_SNPRINTF
384		unsigned int tmp_length;
385		char tmpbuf[700];
386		char *tmp;
387
388		/* Allocate a temporary buffer of sufficient size for calling
389		   sprintf.  */
390		{
391		  unsigned int width;
392		  unsigned int precision;
393
394		  width = 0;
395		  if (dp->width_start != dp->width_end)
396		    {
397		      if (dp->width_arg_index >= 0)
398			{
399			  int arg;
400
401			  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
402			    abort ();
403			  arg = a.arg[dp->width_arg_index].a.a_int;
404			  width = (arg < 0 ? -arg : arg);
405			}
406		      else
407			{
408			  const char *digitp = dp->width_start;
409
410			  do
411			    width = width * 10 + (*digitp++ - '0');
412			  while (digitp != dp->width_end);
413			}
414		    }
415
416		  precision = 6;
417		  if (dp->precision_start != dp->precision_end)
418		    {
419		      if (dp->precision_arg_index >= 0)
420			{
421			  int arg;
422
423			  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
424			    abort ();
425			  arg = a.arg[dp->precision_arg_index].a.a_int;
426			  precision = (arg < 0 ? 0 : arg);
427			}
428		      else
429			{
430			  const char *digitp = dp->precision_start + 1;
431
432			  precision = 0;
433			  while (digitp != dp->precision_end)
434			    precision = precision * 10 + (*digitp++ - '0');
435			}
436		    }
437
438		  switch (dp->conversion)
439		    {
440		    case 'd': case 'i': case 'u':
441# ifdef HAVE_LONG_LONG
442		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
443			tmp_length =
444			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
445					  * 0.30103 /* binary -> decimal */
446					  * 2 /* estimate for FLAG_GROUP */
447					 )
448			  + 1 /* turn floor into ceil */
449			  + 1; /* account for leading sign */
450		      else
451# endif
452		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
453			tmp_length =
454			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
455					  * 0.30103 /* binary -> decimal */
456					  * 2 /* estimate for FLAG_GROUP */
457					 )
458			  + 1 /* turn floor into ceil */
459			  + 1; /* account for leading sign */
460		      else
461			tmp_length =
462			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
463					  * 0.30103 /* binary -> decimal */
464					  * 2 /* estimate for FLAG_GROUP */
465					 )
466			  + 1 /* turn floor into ceil */
467			  + 1; /* account for leading sign */
468		      break;
469
470		    case 'o':
471# ifdef HAVE_LONG_LONG
472		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
473			tmp_length =
474			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
475					  * 0.333334 /* binary -> octal */
476					 )
477			  + 1 /* turn floor into ceil */
478			  + 1; /* account for leading sign */
479		      else
480# endif
481		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
482			tmp_length =
483			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
484					  * 0.333334 /* binary -> octal */
485					 )
486			  + 1 /* turn floor into ceil */
487			  + 1; /* account for leading sign */
488		      else
489			tmp_length =
490			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
491					  * 0.333334 /* binary -> octal */
492					 )
493			  + 1 /* turn floor into ceil */
494			  + 1; /* account for leading sign */
495		      break;
496
497		    case 'x': case 'X':
498# ifdef HAVE_LONG_LONG
499		      if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
500			tmp_length =
501			  (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
502					  * 0.25 /* binary -> hexadecimal */
503					 )
504			  + 1 /* turn floor into ceil */
505			  + 2; /* account for leading sign or alternate form */
506		      else
507# endif
508# ifdef HAVE_INT64_AND_I64
509		      if (type == TYPE_INT64 || type == TYPE_UINT64)
510			tmp_length =
511			  (unsigned int) (sizeof (unsigned __int64) * CHAR_BIT
512					  * 0.25 /* binary -> hexadecimal */
513					  )
514			  + 1 /* turn floor into ceil */
515			  + 2; /* account for leading sign or alternate form */
516		      else
517# endif
518		      if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
519			tmp_length =
520			  (unsigned int) (sizeof (unsigned long) * CHAR_BIT
521					  * 0.25 /* binary -> hexadecimal */
522					 )
523			  + 1 /* turn floor into ceil */
524			  + 2; /* account for leading sign or alternate form */
525		      else
526			tmp_length =
527			  (unsigned int) (sizeof (unsigned int) * CHAR_BIT
528					  * 0.25 /* binary -> hexadecimal */
529					 )
530			  + 1 /* turn floor into ceil */
531			  + 2; /* account for leading sign or alternate form */
532		      break;
533
534		    case 'f': case 'F':
535# ifdef HAVE_LONG_DOUBLE
536		      if (type == TYPE_LONGDOUBLE)
537			tmp_length =
538			  (unsigned int) (LDBL_MAX_EXP
539					  * 0.30103 /* binary -> decimal */
540					  * 2 /* estimate for FLAG_GROUP */
541					 )
542			  + 1 /* turn floor into ceil */
543			  + precision
544			  + 10; /* sign, decimal point etc. */
545		      else
546# endif
547			tmp_length =
548			  (unsigned int) (DBL_MAX_EXP
549					  * 0.30103 /* binary -> decimal */
550					  * 2 /* estimate for FLAG_GROUP */
551					 )
552			  + 1 /* turn floor into ceil */
553			  + precision
554			  + 10; /* sign, decimal point etc. */
555		      break;
556
557		    case 'e': case 'E': case 'g': case 'G':
558		    case 'a': case 'A':
559		      tmp_length =
560			precision
561			+ 12; /* sign, decimal point, exponent etc. */
562		      break;
563
564		    case 'c':
565# ifdef HAVE_WINT_T
566		      if (type == TYPE_WIDE_CHAR)
567			tmp_length = MB_CUR_MAX;
568		      else
569# endif
570			tmp_length = 1;
571		      break;
572
573		    case 's':
574# ifdef HAVE_WCHAR_T
575		      if (type == TYPE_WIDE_STRING)
576			tmp_length =
577			  (a.arg[dp->arg_index].a.a_wide_string == NULL
578			  ? 6 /* wcslen(L"(null)") */
579			   : local_wcslen (a.arg[dp->arg_index].a.a_wide_string))
580			  * MB_CUR_MAX;
581		      else
582# endif
583			tmp_length = a.arg[dp->arg_index].a.a_string == NULL
584			  ? 6 /* strlen("(null)") */
585			  : strlen (a.arg[dp->arg_index].a.a_string);
586		      break;
587
588		    case 'p':
589		      tmp_length =
590			(unsigned int) (sizeof (void *) * CHAR_BIT
591					* 0.25 /* binary -> hexadecimal */
592				       )
593			  + 1 /* turn floor into ceil */
594			  + 2; /* account for leading 0x */
595		      break;
596
597		    default:
598		      abort ();
599		    }
600
601		  if (tmp_length < width)
602		    tmp_length = width;
603
604		  tmp_length++; /* account for trailing NUL */
605		}
606
607		if (tmp_length <= sizeof (tmpbuf))
608		  tmp = tmpbuf;
609		else
610		  {
611		    tmp = (char *) malloc (tmp_length);
612		    if (tmp == NULL)
613		      {
614			/* Out of memory.  */
615			if (!(result == resultbuf || result == NULL))
616			  free (result);
617			freea (buf);
618			CLEANUP ();
619			errno = ENOMEM;
620			return NULL;
621		      }
622		  }
623#endif
624
625		/* Construct the format string for calling snprintf or
626		   sprintf.  */
627		p = buf;
628		*p++ = '%';
629		if (dp->flags & FLAG_GROUP)
630		  *p++ = '\'';
631		if (dp->flags & FLAG_LEFT)
632		  *p++ = '-';
633		if (dp->flags & FLAG_SHOWSIGN)
634		  *p++ = '+';
635		if (dp->flags & FLAG_SPACE)
636		  *p++ = ' ';
637		if (dp->flags & FLAG_ALT)
638		  *p++ = '#';
639		if (dp->flags & FLAG_ZERO)
640		  *p++ = '0';
641		if (dp->width_start != dp->width_end)
642		  {
643		    size_t n = dp->width_end - dp->width_start;
644		    memcpy (p, dp->width_start, n);
645		    p += n;
646		  }
647		if (dp->precision_start != dp->precision_end)
648		  {
649		    size_t n = dp->precision_end - dp->precision_start;
650		    memcpy (p, dp->precision_start, n);
651		    p += n;
652		  }
653
654		switch (type)
655		  {
656#ifdef HAVE_INT64_AND_I64
657		  case TYPE_INT64:
658		  case TYPE_UINT64:
659		    *p++ = 'I';
660		    *p++ = '6';
661		    *p++ = '4';
662		    break;
663#endif
664#ifdef HAVE_LONG_LONG
665		  case TYPE_LONGLONGINT:
666		  case TYPE_ULONGLONGINT:
667#ifdef HAVE_INT64_AND_I64	/* The system (sn)printf uses %I64. Also assume
668				 * that long long == __int64.
669				 */
670		    *p++ = 'I';
671		    *p++ = '6';
672		    *p++ = '4';
673		    break;
674#else
675		    *p++ = 'l';
676		    /*FALLTHROUGH*/
677#endif
678#endif
679		  case TYPE_LONGINT:
680		  case TYPE_ULONGINT:
681#ifdef HAVE_WINT_T
682		  case TYPE_WIDE_CHAR:
683#endif
684#ifdef HAVE_WCHAR_T
685		  case TYPE_WIDE_STRING:
686#endif
687		    *p++ = 'l';
688		    break;
689#ifdef HAVE_LONG_DOUBLE
690		  case TYPE_LONGDOUBLE:
691		    *p++ = 'L';
692		    break;
693#endif
694		  default:
695		    break;
696		  }
697		*p = dp->conversion;
698#if HAVE_SNPRINTF
699		p[1] = '%';
700		p[2] = 'n';
701		p[3] = '\0';
702#else
703		p[1] = '\0';
704#endif
705
706		/* Construct the arguments for calling snprintf or sprintf.  */
707		prefix_count = 0;
708		if (dp->width_arg_index >= 0)
709		  {
710		    if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
711		      abort ();
712		    prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
713		  }
714		if (dp->precision_arg_index >= 0)
715		  {
716		    if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
717		      abort ();
718		    prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
719		  }
720
721#if HAVE_SNPRINTF
722		/* Prepare checking whether snprintf returns the count
723		   via %n.  */
724		ENSURE_ALLOCATION (length + 1);
725		result[length] = '\0';
726#endif
727
728		for (;;)
729		  {
730		    size_t maxlen;
731		    int count;
732		    int retcount;
733
734		    maxlen = allocated - length;
735		    count = -1;
736		    retcount = 0;
737
738#if HAVE_SNPRINTF
739#define SNPRINTF_BUF(arg) \
740		    switch (prefix_count)				    \
741		      {							    \
742		      case 0:						    \
743			retcount = snprintf (result + length, maxlen, buf,  \
744					     arg, &count);		    \
745			break;						    \
746		      case 1:						    \
747			retcount = snprintf (result + length, maxlen, buf,  \
748					     prefixes[0], arg, &count);	    \
749			break;						    \
750		      case 2:						    \
751			retcount = snprintf (result + length, maxlen, buf,  \
752					     prefixes[0], prefixes[1], arg, \
753					     &count);			    \
754			break;						    \
755		      default:						    \
756			abort ();					    \
757		      }
758#else
759#define SNPRINTF_BUF(arg) \
760		    switch (prefix_count)				    \
761		      {							    \
762		      case 0:						    \
763			count = sprintf (tmp, buf, arg);		    \
764			break;						    \
765		      case 1:						    \
766			count = sprintf (tmp, buf, prefixes[0], arg);	    \
767			break;						    \
768		      case 2:						    \
769			count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
770					 arg);				    \
771			break;						    \
772		      default:						    \
773			abort ();					    \
774		      }
775#endif
776
777		    switch (type)
778		      {
779		      case TYPE_SCHAR:
780			{
781			  int arg = a.arg[dp->arg_index].a.a_schar;
782			  SNPRINTF_BUF (arg);
783			}
784			break;
785		      case TYPE_UCHAR:
786			{
787			  unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
788			  SNPRINTF_BUF (arg);
789			}
790			break;
791		      case TYPE_SHORT:
792			{
793			  int arg = a.arg[dp->arg_index].a.a_short;
794			  SNPRINTF_BUF (arg);
795			}
796			break;
797		      case TYPE_USHORT:
798			{
799			  unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
800			  SNPRINTF_BUF (arg);
801			}
802			break;
803		      case TYPE_INT:
804			{
805			  int arg = a.arg[dp->arg_index].a.a_int;
806			  SNPRINTF_BUF (arg);
807			}
808			break;
809		      case TYPE_UINT:
810			{
811			  unsigned int arg = a.arg[dp->arg_index].a.a_uint;
812			  SNPRINTF_BUF (arg);
813			}
814			break;
815		      case TYPE_LONGINT:
816			{
817			  long int arg = a.arg[dp->arg_index].a.a_longint;
818			  SNPRINTF_BUF (arg);
819			}
820			break;
821		      case TYPE_ULONGINT:
822			{
823			  unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
824			  SNPRINTF_BUF (arg);
825			}
826			break;
827#ifdef HAVE_INT64_AND_I64
828		      case TYPE_INT64:
829			{
830			  __int64 arg = a.arg[dp->arg_index].a.a_int64;
831			  SNPRINTF_BUF (arg);
832			}
833			break;
834		      case TYPE_UINT64:
835			{
836			  unsigned __int64 arg = a.arg[dp->arg_index].a.a_uint64;
837			  SNPRINTF_BUF (arg);
838			}
839			break;
840#endif
841#ifdef HAVE_LONG_LONG
842#ifndef HAVE_LONG_LONG_FORMAT
843		      case TYPE_LONGLONGINT:
844		      case TYPE_ULONGLONGINT:
845			{
846			  unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
847			  int width;
848			  int precision;
849
850			  width = 0;
851			  if (dp->width_start != dp->width_end)
852			    {
853			      if (dp->width_arg_index >= 0)
854				{
855				  int arg;
856
857				  if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
858				    abort ();
859				  arg = a.arg[dp->width_arg_index].a.a_int;
860				  width = (arg < 0 ? -arg : arg);
861				}
862			      else
863				{
864				  const char *digitp = dp->width_start;
865
866				  do
867				    width = width * 10 + (*digitp++ - '0');
868				  while (digitp != dp->width_end);
869				}
870			    }
871
872			  precision = -1;
873			  if (dp->precision_start != dp->precision_end)
874			    {
875			      if (dp->precision_arg_index >= 0)
876				{
877				  int arg;
878
879				  if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
880				    abort ();
881				  arg = a.arg[dp->precision_arg_index].a.a_int;
882				  precision = (arg < 0 ? 0 : arg);
883				}
884			      else
885				{
886				  const char *digitp = dp->precision_start + 1;
887
888				  precision = 0;
889				  do
890				    precision = precision * 10 + (*digitp++ - '0');
891				  while (digitp != dp->precision_end);
892				}
893			    }
894
895#if HAVE_SNPRINTF
896 			  count = print_long_long (result + length, maxlen,
897 						   width, precision,
898 						   dp->flags,
899 						   dp->conversion,
900 						   arg);
901#else
902			  count = print_long_long (tmp, tmp_length,
903						   width, precision,
904						   dp->flags,
905						   dp->conversion,
906						   arg);
907#endif
908			}
909			break;
910#else
911		      case TYPE_LONGLONGINT:
912			{
913			  long long int arg = a.arg[dp->arg_index].a.a_longlongint;
914			  SNPRINTF_BUF (arg);
915			}
916			break;
917		      case TYPE_ULONGLONGINT:
918			{
919			  unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
920			  SNPRINTF_BUF (arg);
921			}
922			break;
923#endif
924#endif
925		      case TYPE_DOUBLE:
926			{
927			  double arg = a.arg[dp->arg_index].a.a_double;
928			  SNPRINTF_BUF (arg);
929			}
930			break;
931#ifdef HAVE_LONG_DOUBLE
932		      case TYPE_LONGDOUBLE:
933			{
934			  long double arg = a.arg[dp->arg_index].a.a_longdouble;
935			  SNPRINTF_BUF (arg);
936			}
937			break;
938#endif
939		      case TYPE_CHAR:
940			{
941			  int arg = a.arg[dp->arg_index].a.a_char;
942			  SNPRINTF_BUF (arg);
943			}
944			break;
945#ifdef HAVE_WINT_T
946		      case TYPE_WIDE_CHAR:
947			{
948			  wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
949			  SNPRINTF_BUF (arg);
950			}
951			break;
952#endif
953		      case TYPE_STRING:
954			{
955			  const char *arg = a.arg[dp->arg_index].a.a_string == NULL
956			    ? "(null)"
957			    : a.arg[dp->arg_index].a.a_string;
958			  SNPRINTF_BUF (arg);
959			}
960			break;
961#ifdef HAVE_WCHAR_T
962		      case TYPE_WIDE_STRING:
963			{
964			  const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string == NULL
965			    ? L"(null)"
966			    : a.arg[dp->arg_index].a.a_wide_string;
967			  SNPRINTF_BUF (arg);
968			}
969			break;
970#endif
971		      case TYPE_POINTER:
972			{
973			  void *arg = a.arg[dp->arg_index].a.a_pointer;
974			  SNPRINTF_BUF (arg);
975			}
976			break;
977		      default:
978			abort ();
979		      }
980
981#if HAVE_SNPRINTF
982		    /* Portability: Not all implementations of snprintf()
983		       are ISO C 99 compliant.  Determine the number of
984		       bytes that snprintf() has produced or would have
985		       produced.  */
986		    if (count >= 0)
987		      {
988			/* Verify that snprintf() has NUL-terminated its
989			   result.  */
990			if (count < maxlen && result[length + count] != '\0')
991			  abort ();
992			/* Portability hack.  */
993			if (retcount > count)
994			  count = retcount;
995		      }
996		    else
997		      {
998			/* snprintf() doesn't understand the '%n'
999			   directive.  */
1000			if (p[1] != '\0')
1001			  {
1002			    /* Don't use the '%n' directive; instead, look
1003			       at the snprintf() return value.  */
1004			    p[1] = '\0';
1005			    continue;
1006			  }
1007			count = retcount;
1008		      }
1009#endif
1010
1011		    /* Attempt to handle failure.  */
1012		    if (count < 0)
1013		      {
1014			if (!(result == resultbuf || result == NULL))
1015			  free (result);
1016			freea (buf);
1017			CLEANUP ();
1018			errno = EINVAL;
1019			return NULL;
1020		      }
1021
1022#if !HAVE_SNPRINTF
1023		    if (count >= tmp_length)
1024		      /* tmp_length was incorrectly calculated - fix the
1025			 code above!  */
1026		      abort ();
1027#endif
1028
1029		    /* Make room for the result.  */
1030		    if (count >= maxlen)
1031		      {
1032			/* Need at least count bytes.  But allocate
1033			   proportionally, to avoid looping eternally if
1034			   snprintf() reports a too small count.  */
1035			size_t n = length + count;
1036
1037			if (n < 2 * allocated)
1038			  n = 2 * allocated;
1039
1040			ENSURE_ALLOCATION (n);
1041#if HAVE_SNPRINTF
1042			continue;
1043#endif
1044		      }
1045
1046#if HAVE_SNPRINTF
1047		    /* The snprintf() result did fit.  */
1048#else
1049		    /* Append the sprintf() result.  */
1050		    memcpy (result + length, tmp, count);
1051		    if (tmp != tmpbuf)
1052		      free (tmp);
1053#endif
1054
1055		    length += count;
1056		    break;
1057		  }
1058	      }
1059	  }
1060      }
1061
1062    /* Add the final NUL.  */
1063    ENSURE_ALLOCATION (length + 1);
1064    result[length] = '\0';
1065
1066    if (result != resultbuf && length + 1 < allocated)
1067      {
1068	/* Shrink the allocated memory if possible.  */
1069	char *memory;
1070
1071	memory = (char *) realloc (result, length + 1);
1072	if (memory != NULL)
1073	  result = memory;
1074      }
1075
1076    freea (buf);
1077    CLEANUP ();
1078    *lengthp = length;
1079    return result;
1080  }
1081}
1082