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