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