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