Fix 64bit printing for MSVC builds (#119292, Hans Breuer):
[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                           do
409                             precision = precision * 10 + (*digitp++ - '0');
410                           while (digitp != dp->precision_end);
411                         }
412                     }
413
414                   switch (dp->conversion)
415                     {
416                     case 'd': case 'i': case 'u':
417 # ifdef HAVE_LONG_LONG
418                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
419                         tmp_length =
420                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
421                                           * 0.30103 /* binary -> decimal */
422                                           * 2 /* estimate for FLAG_GROUP */
423                                          )
424                           + 1 /* turn floor into ceil */
425                           + 1; /* account for leading sign */
426                       else
427 # endif
428                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
429                         tmp_length =
430                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
431                                           * 0.30103 /* binary -> decimal */
432                                           * 2 /* estimate for FLAG_GROUP */
433                                          )
434                           + 1 /* turn floor into ceil */
435                           + 1; /* account for leading sign */
436                       else
437                         tmp_length =
438                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
439                                           * 0.30103 /* binary -> decimal */
440                                           * 2 /* estimate for FLAG_GROUP */
441                                          )
442                           + 1 /* turn floor into ceil */
443                           + 1; /* account for leading sign */
444                       break;
445
446                     case 'o':
447 # ifdef HAVE_LONG_LONG
448                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
449                         tmp_length =
450                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
451                                           * 0.333334 /* binary -> octal */
452                                          )
453                           + 1 /* turn floor into ceil */
454                           + 1; /* account for leading sign */
455                       else
456 # endif
457                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
458                         tmp_length =
459                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
460                                           * 0.333334 /* binary -> octal */
461                                          )
462                           + 1 /* turn floor into ceil */
463                           + 1; /* account for leading sign */
464                       else
465                         tmp_length =
466                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
467                                           * 0.333334 /* binary -> octal */
468                                          )
469                           + 1 /* turn floor into ceil */
470                           + 1; /* account for leading sign */
471                       break;
472
473                     case 'x': case 'X':
474 # ifdef HAVE_LONG_LONG
475                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
476                         tmp_length =
477                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
478                                           * 0.25 /* binary -> hexadecimal */
479                                          )
480                           + 1 /* turn floor into ceil */
481                           + 2; /* account for leading sign or alternate form */
482                       else
483 # endif
484                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
485                         tmp_length =
486                           (unsigned int) (sizeof (unsigned long) * 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                         tmp_length =
493                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
494                                           * 0.25 /* binary -> hexadecimal */
495                                          )
496                           + 1 /* turn floor into ceil */
497                           + 2; /* account for leading sign or alternate form */
498                       break;
499
500                     case 'f': case 'F':
501 # ifdef HAVE_LONG_DOUBLE
502                       if (type == TYPE_LONGDOUBLE)
503                         tmp_length =
504                           (unsigned int) (LDBL_MAX_EXP
505                                           * 0.30103 /* binary -> decimal */
506                                           * 2 /* estimate for FLAG_GROUP */
507                                          )
508                           + 1 /* turn floor into ceil */
509                           + precision
510                           + 10; /* sign, decimal point etc. */
511                       else
512 # endif
513                         tmp_length =
514                           (unsigned int) (DBL_MAX_EXP
515                                           * 0.30103 /* binary -> decimal */
516                                           * 2 /* estimate for FLAG_GROUP */
517                                          )
518                           + 1 /* turn floor into ceil */
519                           + precision
520                           + 10; /* sign, decimal point etc. */
521                       break;
522
523                     case 'e': case 'E': case 'g': case 'G':
524                     case 'a': case 'A':
525                       tmp_length =
526                         precision
527                         + 12; /* sign, decimal point, exponent etc. */
528                       break;
529
530                     case 'c':
531 # ifdef HAVE_WINT_T
532                       if (type == TYPE_WIDE_CHAR)
533                         tmp_length = MB_CUR_MAX;
534                       else
535 # endif
536                         tmp_length = 1;
537                       break;
538
539                     case 's':
540 # ifdef HAVE_WCHAR_T
541                       if (type == TYPE_WIDE_STRING)
542                         tmp_length =
543                           wcslen (a.arg[dp->arg_index].a.a_wide_string)
544                           * MB_CUR_MAX;
545                       else
546 # endif
547                         tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
548                       break;
549
550                     case 'p':
551                       tmp_length =
552                         (unsigned int) (sizeof (void *) * CHAR_BIT
553                                         * 0.25 /* binary -> hexadecimal */
554                                        )
555                           + 1 /* turn floor into ceil */
556                           + 2; /* account for leading 0x */
557                       break;
558
559                     default:
560                       abort ();
561                     }
562
563                   if (tmp_length < width)
564                     tmp_length = width;
565
566                   tmp_length++; /* account for trailing NUL */
567                 }
568
569                 if (tmp_length <= sizeof (tmpbuf))
570                   tmp = tmpbuf;
571                 else
572                   {
573                     tmp = (char *) malloc (tmp_length);
574                     if (tmp == NULL)
575                       {
576                         /* Out of memory.  */
577                         if (!(result == resultbuf || result == NULL))
578                           free (result);
579                         freea (buf);
580                         CLEANUP ();
581                         errno = ENOMEM;
582                         return NULL;
583                       }
584                   }
585 #endif
586
587                 /* Construct the format string for calling snprintf or
588                    sprintf.  */
589                 p = buf;
590                 *p++ = '%';
591                 if (dp->flags & FLAG_GROUP)
592                   *p++ = '\'';
593                 if (dp->flags & FLAG_LEFT)
594                   *p++ = '-';
595                 if (dp->flags & FLAG_SHOWSIGN)
596                   *p++ = '+';
597                 if (dp->flags & FLAG_SPACE)
598                   *p++ = ' ';
599                 if (dp->flags & FLAG_ALT)
600                   *p++ = '#';
601                 if (dp->flags & FLAG_ZERO)
602                   *p++ = '0';
603                 if (dp->width_start != dp->width_end)
604                   {
605                     size_t n = dp->width_end - dp->width_start;
606                     memcpy (p, dp->width_start, n);
607                     p += n;
608                   }
609                 if (dp->precision_start != dp->precision_end)
610                   {
611                     size_t n = dp->precision_end - dp->precision_start;
612                     memcpy (p, dp->precision_start, n);
613                     p += n;
614                   }
615
616                 switch (type)
617                   {
618 #ifdef HAVE_INT64_AND_I64
619                   case TYPE_INT64:
620                   case TYPE_UINT64:
621                     *p++ = 'I';
622                     *p++ = '6';
623                     *p++ = '4';
624                     break;
625 #endif
626 #ifdef HAVE_LONG_LONG
627                   case TYPE_LONGLONGINT:
628                   case TYPE_ULONGLONGINT:
629                     *p++ = 'l';
630                     /*FALLTHROUGH*/
631 #endif
632                   case TYPE_LONGINT:
633                   case TYPE_ULONGINT:
634 #ifdef HAVE_WINT_T
635                   case TYPE_WIDE_CHAR:
636 #endif
637 #ifdef HAVE_WCHAR_T
638                   case TYPE_WIDE_STRING:
639 #endif
640                     *p++ = 'l';
641                     break;
642 #ifdef HAVE_LONG_DOUBLE
643                   case TYPE_LONGDOUBLE:
644                     *p++ = 'L';
645                     break;
646 #endif
647                   default:
648                     break;
649                   }
650                 *p = dp->conversion;
651 #if HAVE_SNPRINTF
652                 p[1] = '%';
653                 p[2] = 'n';
654                 p[3] = '\0';
655 #else
656                 p[1] = '\0';
657 #endif
658
659                 /* Construct the arguments for calling snprintf or sprintf.  */
660                 prefix_count = 0;
661                 if (dp->width_arg_index >= 0)
662                   {
663                     if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
664                       abort ();
665                     prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
666                   }
667                 if (dp->precision_arg_index >= 0)
668                   {
669                     if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
670                       abort ();
671                     prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
672                   }
673
674 #if HAVE_SNPRINTF
675                 /* Prepare checking whether snprintf returns the count
676                    via %n.  */
677                 ENSURE_ALLOCATION (length + 1);
678                 result[length] = '\0';
679 #endif
680
681                 for (;;)
682                   {
683                     size_t maxlen;
684                     int count;
685                     int retcount;
686
687                     maxlen = allocated - length;
688                     count = -1;
689                     retcount = 0;
690
691 #if HAVE_SNPRINTF
692 #define SNPRINTF_BUF(arg) \
693                     switch (prefix_count)                                   \
694                       {                                                     \
695                       case 0:                                               \
696                         retcount = snprintf (result + length, maxlen, buf,  \
697                                              arg, &count);                  \
698                         break;                                              \
699                       case 1:                                               \
700                         retcount = snprintf (result + length, maxlen, buf,  \
701                                              prefixes[0], arg, &count);     \
702                         break;                                              \
703                       case 2:                                               \
704                         retcount = snprintf (result + length, maxlen, buf,  \
705                                              prefixes[0], prefixes[1], arg, \
706                                              &count);                       \
707                         break;                                              \
708                       default:                                              \
709                         abort ();                                           \
710                       }
711 #else
712 #define SNPRINTF_BUF(arg) \
713                     switch (prefix_count)                                   \
714                       {                                                     \
715                       case 0:                                               \
716                         count = sprintf (tmp, buf, arg);                    \
717                         break;                                              \
718                       case 1:                                               \
719                         count = sprintf (tmp, buf, prefixes[0], arg);       \
720                         break;                                              \
721                       case 2:                                               \
722                         count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
723                                          arg);                              \
724                         break;                                              \
725                       default:                                              \
726                         abort ();                                           \
727                       }
728 #endif
729
730                     switch (type)
731                       {
732                       case TYPE_SCHAR:
733                         {
734                           int arg = a.arg[dp->arg_index].a.a_schar;
735                           SNPRINTF_BUF (arg);
736                         }
737                         break;
738                       case TYPE_UCHAR:
739                         {
740                           unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
741                           SNPRINTF_BUF (arg);
742                         }
743                         break;
744                       case TYPE_SHORT:
745                         {
746                           int arg = a.arg[dp->arg_index].a.a_short;
747                           SNPRINTF_BUF (arg);
748                         }
749                         break;
750                       case TYPE_USHORT:
751                         {
752                           unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
753                           SNPRINTF_BUF (arg);
754                         }
755                         break;
756                       case TYPE_INT:
757                         {
758                           int arg = a.arg[dp->arg_index].a.a_int;
759                           SNPRINTF_BUF (arg);
760                         }
761                         break;
762                       case TYPE_UINT:
763                         {
764                           unsigned int arg = a.arg[dp->arg_index].a.a_uint;
765                           SNPRINTF_BUF (arg);
766                         }
767                         break;
768                       case TYPE_LONGINT:
769                         {
770                           long int arg = a.arg[dp->arg_index].a.a_longint;
771                           SNPRINTF_BUF (arg);
772                         }
773                         break;
774                       case TYPE_ULONGINT:
775                         {
776                           unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
777                           SNPRINTF_BUF (arg);
778                         }
779                         break;
780 #ifdef HAVE_INT64_AND_I64
781                       case TYPE_INT64:
782                         {
783                           __int64 arg = a.arg[dp->arg_index].a.a_int64;
784                           SNPRINTF_BUF (arg);
785                         }
786                         break;
787                       case TYPE_UINT64:
788                         {
789                           unsigned __int64 arg = a.arg[dp->arg_index].a.a_uint64;
790                           SNPRINTF_BUF (arg);
791                         }
792                         break;                  
793 #endif
794 #ifdef HAVE_LONG_LONG
795 #ifndef HAVE_LONG_LONG_FORMAT
796                       case TYPE_LONGLONGINT:
797                       case TYPE_ULONGLONGINT:
798                         {
799                           unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
800                           int width;
801                           int precision;
802
803                           width = 0;
804                           if (dp->width_start != dp->width_end)
805                             {
806                               if (dp->width_arg_index >= 0)
807                                 {
808                                   int arg;
809                                   
810                                   if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
811                                     abort ();
812                                   arg = a.arg[dp->width_arg_index].a.a_int;
813                                   width = (arg < 0 ? -arg : arg);
814                                 }
815                               else
816                                 {
817                                   const char *digitp = dp->width_start;
818                                   
819                                   do
820                                     width = width * 10 + (*digitp++ - '0');
821                                   while (digitp != dp->width_end);
822                                 }
823                             }
824
825                           precision = -1;
826                           if (dp->precision_start != dp->precision_end)
827                             {
828                               if (dp->precision_arg_index >= 0)
829                                 {
830                                   int arg;
831                                   
832                                   if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
833                                     abort ();
834                                   arg = a.arg[dp->precision_arg_index].a.a_int;
835                                   precision = (arg < 0 ? 0 : arg);
836                                 }
837                               else
838                                 {
839                                   const char *digitp = dp->precision_start + 1;
840                                   
841                                   precision = 0;
842                                   do
843                                     precision = precision * 10 + (*digitp++ - '0');
844                                   while (digitp != dp->precision_end);
845                                 }
846                             }
847                           
848                           count = print_long_long (result + length, maxlen,
849                                                    width, precision,
850                                                    dp->flags,
851                                                    dp->conversion,
852                                                    arg);
853                         }
854                         break;
855 #else
856                       case TYPE_LONGLONGINT:
857                         {
858                           long long int arg = a.arg[dp->arg_index].a.a_longlongint;
859                           SNPRINTF_BUF (arg);
860                         }
861                         break;
862                       case TYPE_ULONGLONGINT:
863                         {
864                           unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
865                           SNPRINTF_BUF (arg);
866                         }
867                         break;
868 #endif
869 #endif
870                       case TYPE_DOUBLE:
871                         {
872                           double arg = a.arg[dp->arg_index].a.a_double;
873                           SNPRINTF_BUF (arg);
874                         }
875                         break;
876 #ifdef HAVE_LONG_DOUBLE
877                       case TYPE_LONGDOUBLE:
878                         {
879                           long double arg = a.arg[dp->arg_index].a.a_longdouble;
880                           SNPRINTF_BUF (arg);
881                         }
882                         break;
883 #endif
884                       case TYPE_CHAR:
885                         {
886                           int arg = a.arg[dp->arg_index].a.a_char;
887                           SNPRINTF_BUF (arg);
888                         }
889                         break;
890 #ifdef HAVE_WINT_T
891                       case TYPE_WIDE_CHAR:
892                         {
893                           wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
894                           SNPRINTF_BUF (arg);
895                         }
896                         break;
897 #endif
898                       case TYPE_STRING:
899                         {
900                           const char *arg = a.arg[dp->arg_index].a.a_string;
901                           SNPRINTF_BUF (arg);
902                         }
903                         break;
904 #ifdef HAVE_WCHAR_T
905                       case TYPE_WIDE_STRING:
906                         {
907                           const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
908                           SNPRINTF_BUF (arg);
909                         }
910                         break;
911 #endif
912                       case TYPE_POINTER:
913                         {
914                           void *arg = a.arg[dp->arg_index].a.a_pointer;
915                           SNPRINTF_BUF (arg);
916                         }
917                         break;
918                       default:
919                         abort ();
920                       }
921
922 #if HAVE_SNPRINTF
923                     /* Portability: Not all implementations of snprintf()
924                        are ISO C 99 compliant.  Determine the number of
925                        bytes that snprintf() has produced or would have
926                        produced.  */
927                     if (count >= 0)
928                       {
929                         /* Verify that snprintf() has NUL-terminated its
930                            result.  */
931                         if (count < maxlen && result[length + count] != '\0')
932                           abort ();
933                         /* Portability hack.  */
934                         if (retcount > count)
935                           count = retcount;
936                       }
937                     else
938                       {
939                         /* snprintf() doesn't understand the '%n'
940                            directive.  */
941                         if (p[1] != '\0')
942                           {
943                             /* Don't use the '%n' directive; instead, look
944                                at the snprintf() return value.  */
945                             p[1] = '\0';
946                             continue;
947                           }
948                         count = retcount;
949                       }
950 #endif
951
952                     /* Attempt to handle failure.  */
953                     if (count < 0)
954                       {
955                         if (!(result == resultbuf || result == NULL))
956                           free (result);
957                         freea (buf);
958                         CLEANUP ();
959                         errno = EINVAL;
960                         return NULL;
961                       }
962
963 #if !HAVE_SNPRINTF
964                     if (count >= tmp_length)
965                       /* tmp_length was incorrectly calculated - fix the
966                          code above!  */
967                       abort ();
968 #endif
969
970                     /* Make room for the result.  */
971                     if (count >= maxlen)
972                       {
973                         /* Need at least count bytes.  But allocate
974                            proportionally, to avoid looping eternally if
975                            snprintf() reports a too small count.  */
976                         size_t n = length + count;
977
978                         if (n < 2 * allocated)
979                           n = 2 * allocated;
980
981                         ENSURE_ALLOCATION (n);
982 #if HAVE_SNPRINTF
983                         continue;
984 #endif
985                       }
986
987 #if HAVE_SNPRINTF
988                     /* The snprintf() result did fit.  */
989 #else
990                     /* Append the sprintf() result.  */
991                     memcpy (result + length, tmp, count);
992                     if (tmp != tmpbuf)
993                       free (tmp);
994 #endif
995
996                     length += count;
997                     break;
998                   }
999               }
1000           }
1001       }
1002
1003     /* Add the final NUL.  */
1004     ENSURE_ALLOCATION (length + 1);
1005     result[length] = '\0';
1006
1007     if (result != resultbuf && length + 1 < allocated)
1008       {
1009         /* Shrink the allocated memory if possible.  */
1010         char *memory;
1011
1012         memory = (char *) realloc (result, length + 1);
1013         if (memory != NULL)
1014           result = memory;
1015       }
1016
1017     freea (buf);
1018     CLEANUP ();
1019     *lengthp = length;
1020     return result;
1021   }
1022 }