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