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