00419aaaaff32f284998e58a6df9126ad1e96ea2
[gnulib.git] / lib / vasnprintf.c
1 /* vsprintf with automatic memory allocation.
2    Copyright (C) 1999, 2002-2007 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    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
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License along
15    with this program; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Tell glibc's <stdio.h> to provide a prototype for snprintf().
19    This must come before <config.h> because <config.h> may include
20    <features.h>, and once <features.h> has been included, it's too late.  */
21 #ifndef _GNU_SOURCE
22 # define _GNU_SOURCE    1
23 #endif
24
25 #include <config.h>
26 #ifndef IN_LIBINTL
27 # include <alloca.h>
28 #endif
29
30 /* Specification.  */
31 #if WIDE_CHAR_VERSION
32 # include "vasnwprintf.h"
33 #else
34 # include "vasnprintf.h"
35 #endif
36
37 #include <locale.h>     /* localeconv() */
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 #if WIDE_CHAR_VERSION
45 # include "wprintf-parse.h"
46 #else
47 # include "printf-parse.h"
48 #endif
49
50 /* Checked size_t computations.  */
51 #include "xsize.h"
52
53 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
54 # include "float+.h"
55 # include "isnan.h"
56 # include "printf-frexp.h"
57 # if HAVE_LONG_DOUBLE
58 #  include "isnanl-nolibm.h"
59 #  include "printf-frexpl.h"
60 # endif
61 #endif
62
63 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW.  */
64 #ifndef EOVERFLOW
65 # define EOVERFLOW E2BIG
66 #endif
67
68 #if HAVE_WCHAR_T
69 # if HAVE_WCSLEN
70 #  define local_wcslen wcslen
71 # else
72    /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
73       a dependency towards this library, here is a local substitute.
74       Define this substitute only once, even if this file is included
75       twice in the same compilation unit.  */
76 #  ifndef local_wcslen_defined
77 #   define local_wcslen_defined 1
78 static size_t
79 local_wcslen (const wchar_t *s)
80 {
81   const wchar_t *ptr;
82
83   for (ptr = s; *ptr != (wchar_t) 0; ptr++)
84     ;
85   return ptr - s;
86 }
87 #  endif
88 # endif
89 #endif
90
91 #if WIDE_CHAR_VERSION
92 # define VASNPRINTF vasnwprintf
93 # define CHAR_T wchar_t
94 # define DIRECTIVE wchar_t_directive
95 # define DIRECTIVES wchar_t_directives
96 # define PRINTF_PARSE wprintf_parse
97 # define USE_SNPRINTF 1
98 # if HAVE_DECL__SNWPRINTF
99    /* On Windows, the function swprintf() has a different signature than
100       on Unix; we use the _snwprintf() function instead.  */
101 #  define SNPRINTF _snwprintf
102 # else
103    /* Unix.  */
104 #  define SNPRINTF swprintf
105 # endif
106 #else
107 # define VASNPRINTF vasnprintf
108 # define CHAR_T char
109 # define DIRECTIVE char_directive
110 # define DIRECTIVES char_directives
111 # define PRINTF_PARSE printf_parse
112 # define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
113 # if HAVE_DECL__SNPRINTF
114    /* Windows.  */
115 #  define SNPRINTF _snprintf
116 # else
117    /* Unix.  */
118 #  define SNPRINTF snprintf
119    /* Here we need to call the native snprintf, not rpl_snprintf.  */
120 #  undef snprintf
121 # endif
122 #endif
123 /* Here we need to call the native sprintf, not rpl_sprintf.  */
124 #undef sprintf
125
126 CHAR_T *
127 VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
128 {
129   DIRECTIVES d;
130   arguments a;
131
132   if (PRINTF_PARSE (format, &d, &a) < 0)
133     {
134       errno = EINVAL;
135       return NULL;
136     }
137
138 #define CLEANUP() \
139   free (d.dir);                                                         \
140   if (a.arg)                                                            \
141     free (a.arg);
142
143   if (printf_fetchargs (args, &a) < 0)
144     {
145       CLEANUP ();
146       errno = EINVAL;
147       return NULL;
148     }
149
150   {
151     size_t buf_neededlength;
152     CHAR_T *buf;
153     CHAR_T *buf_malloced;
154     const CHAR_T *cp;
155     size_t i;
156     DIRECTIVE *dp;
157     /* Output string accumulator.  */
158     CHAR_T *result;
159     size_t allocated;
160     size_t length;
161
162     /* Allocate a small buffer that will hold a directive passed to
163        sprintf or snprintf.  */
164     buf_neededlength =
165       xsum4 (7, d.max_width_length, d.max_precision_length, 6);
166 #if HAVE_ALLOCA
167     if (buf_neededlength < 4000 / sizeof (CHAR_T))
168       {
169         buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
170         buf_malloced = NULL;
171       }
172     else
173 #endif
174       {
175         size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
176         if (size_overflow_p (buf_memsize))
177           goto out_of_memory_1;
178         buf = (CHAR_T *) malloc (buf_memsize);
179         if (buf == NULL)
180           goto out_of_memory_1;
181         buf_malloced = buf;
182       }
183
184     if (resultbuf != NULL)
185       {
186         result = resultbuf;
187         allocated = *lengthp;
188       }
189     else
190       {
191         result = NULL;
192         allocated = 0;
193       }
194     length = 0;
195     /* Invariants:
196        result is either == resultbuf or == NULL or malloc-allocated.
197        If length > 0, then result != NULL.  */
198
199     /* Ensures that allocated >= needed.  Aborts through a jump to
200        out_of_memory if needed is SIZE_MAX or otherwise too big.  */
201 #define ENSURE_ALLOCATION(needed) \
202     if ((needed) > allocated)                                                \
203       {                                                                      \
204         size_t memory_size;                                                  \
205         CHAR_T *memory;                                                      \
206                                                                              \
207         allocated = (allocated > 0 ? xtimes (allocated, 2) : 12);            \
208         if ((needed) > allocated)                                            \
209           allocated = (needed);                                              \
210         memory_size = xtimes (allocated, sizeof (CHAR_T));                   \
211         if (size_overflow_p (memory_size))                                   \
212           goto out_of_memory;                                                \
213         if (result == resultbuf || result == NULL)                           \
214           memory = (CHAR_T *) malloc (memory_size);                          \
215         else                                                                 \
216           memory = (CHAR_T *) realloc (result, memory_size);                 \
217         if (memory == NULL)                                                  \
218           goto out_of_memory;                                                \
219         if (result == resultbuf && length > 0)                               \
220           memcpy (memory, result, length * sizeof (CHAR_T));                 \
221         result = memory;                                                     \
222       }
223
224     for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
225       {
226         if (cp != dp->dir_start)
227           {
228             size_t n = dp->dir_start - cp;
229             size_t augmented_length = xsum (length, n);
230
231             ENSURE_ALLOCATION (augmented_length);
232             memcpy (result + length, cp, n * sizeof (CHAR_T));
233             length = augmented_length;
234           }
235         if (i == d.count)
236           break;
237
238         /* Execute a single directive.  */
239         if (dp->conversion == '%')
240           {
241             size_t augmented_length;
242
243             if (!(dp->arg_index == ARG_NONE))
244               abort ();
245             augmented_length = xsum (length, 1);
246             ENSURE_ALLOCATION (augmented_length);
247             result[length] = '%';
248             length = augmented_length;
249           }
250         else
251           {
252             if (!(dp->arg_index != ARG_NONE))
253               abort ();
254
255             if (dp->conversion == 'n')
256               {
257                 switch (a.arg[dp->arg_index].type)
258                   {
259                   case TYPE_COUNT_SCHAR_POINTER:
260                     *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
261                     break;
262                   case TYPE_COUNT_SHORT_POINTER:
263                     *a.arg[dp->arg_index].a.a_count_short_pointer = length;
264                     break;
265                   case TYPE_COUNT_INT_POINTER:
266                     *a.arg[dp->arg_index].a.a_count_int_pointer = length;
267                     break;
268                   case TYPE_COUNT_LONGINT_POINTER:
269                     *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
270                     break;
271 #if HAVE_LONG_LONG_INT
272                   case TYPE_COUNT_LONGLONGINT_POINTER:
273                     *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
274                     break;
275 #endif
276                   default:
277                     abort ();
278                   }
279               }
280 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
281             else if (dp->conversion == 'a' || dp->conversion == 'A')
282               {
283                 arg_type type = a.arg[dp->arg_index].type;
284                 int flags = dp->flags;
285                 int has_width;
286                 size_t width;
287                 int has_precision;
288                 size_t precision;
289                 size_t tmp_length;
290                 CHAR_T tmpbuf[700];
291                 CHAR_T *tmp;
292                 CHAR_T *pad_ptr;
293                 CHAR_T *p;
294
295                 has_width = 0;
296                 width = 0;
297                 if (dp->width_start != dp->width_end)
298                   {
299                     if (dp->width_arg_index != ARG_NONE)
300                       {
301                         int arg;
302
303                         if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
304                           abort ();
305                         arg = a.arg[dp->width_arg_index].a.a_int;
306                         if (arg < 0)
307                           {
308                             /* "A negative field width is taken as a '-' flag
309                                 followed by a positive field width."  */
310                             flags |= FLAG_LEFT;
311                             width = (unsigned int) (-arg);
312                           }
313                         else
314                           width = arg;
315                       }
316                     else
317                       {
318                         const CHAR_T *digitp = dp->width_start;
319
320                         do
321                           width = xsum (xtimes (width, 10), *digitp++ - '0');
322                         while (digitp != dp->width_end);
323                       }
324                     has_width = 1;
325                   }
326
327                 has_precision = 0;
328                 precision = 0;
329                 if (dp->precision_start != dp->precision_end)
330                   {
331                     if (dp->precision_arg_index != ARG_NONE)
332                       {
333                         int arg;
334
335                         if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
336                           abort ();
337                         arg = a.arg[dp->precision_arg_index].a.a_int;
338                         /* "A negative precision is taken as if the precision
339                             were omitted."  */
340                         if (arg >= 0)
341                           {
342                             precision = arg;
343                             has_precision = 1;
344                           }
345                       }
346                     else
347                       {
348                         const CHAR_T *digitp = dp->precision_start + 1;
349
350                         precision = 0;
351                         while (digitp != dp->precision_end)
352                           precision = xsum (xtimes (precision, 10), *digitp++ - '0');
353                         has_precision = 1;
354                       }
355                   }
356
357                 /* Allocate a temporary buffer of sufficient size.  */
358 # if HAVE_LONG_DOUBLE
359                 if (type == TYPE_LONGDOUBLE)
360                   tmp_length =
361                     (unsigned int) ((LDBL_DIG + 1)
362                                     * 0.831 /* decimal -> hexadecimal */
363                                    )
364                     + 1; /* turn floor into ceil */
365                 else
366 # endif
367                   tmp_length =
368                     (unsigned int) ((DBL_DIG + 1)
369                                     * 0.831 /* decimal -> hexadecimal */
370                                    )
371                     + 1; /* turn floor into ceil */
372                 if (tmp_length < precision)
373                   tmp_length = precision;
374                 /* Account for sign, decimal point etc. */
375                 tmp_length = xsum (tmp_length, 12);
376
377                 if (tmp_length < width)
378                   tmp_length = width;
379
380                 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
381
382                 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
383                   tmp = tmpbuf;
384                 else
385                   {
386                     size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
387
388                     if (size_overflow_p (tmp_memsize))
389                       /* Overflow, would lead to out of memory.  */
390                       goto out_of_memory;
391                     tmp = (CHAR_T *) malloc (tmp_memsize);
392                     if (tmp == NULL)
393                       /* Out of memory.  */
394                       goto out_of_memory;
395                   }
396
397                 pad_ptr = NULL;
398                 p = tmp;
399 # if HAVE_LONG_DOUBLE
400                 if (type == TYPE_LONGDOUBLE)
401                   {
402                     long double arg = a.arg[dp->arg_index].a.a_longdouble;
403
404                     if (isnanl (arg))
405                       {
406                         if (dp->conversion == 'A')
407                           {
408                             *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
409                           }
410                         else
411                           {
412                             *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
413                           }
414                       }
415                     else
416                       {
417                         int sign = 0;
418
419                         if (arg < 0.0L)
420                           {
421                             sign = -1;
422                             arg = -arg;
423                           }
424                         else if (arg == 0.0L)
425                           {
426                             /* Distinguish 0.0L and -0.0L.  */
427                             static long double plus_zero = 0.0L;
428                             long double arg_mem = arg;
429                             if (memcmp (&plus_zero, &arg_mem, SIZEOF_LDBL) != 0)
430                               {
431                                 sign = -1;
432                                 arg = -arg;
433                               }
434                           }
435
436                         if (sign < 0)
437                           *p++ = '-';
438                         else if (flags & FLAG_SHOWSIGN)
439                           *p++ = '+';
440                         else if (flags & FLAG_SPACE)
441                           *p++ = ' ';
442
443                         if (arg > 0.0L && arg + arg == arg)
444                           {
445                             if (dp->conversion == 'A')
446                               {
447                                 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
448                               }
449                             else
450                               {
451                                 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
452                               }
453                           }
454                         else
455                           {
456                             int exponent;
457                             long double mantissa;
458
459                             if (arg > 0.0L)
460                               mantissa = printf_frexpl (arg, &exponent);
461                             else
462                               {
463                                 exponent = 0;
464                                 mantissa = 0.0L;
465                               }
466
467                             if (has_precision
468                                 && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
469                               {
470                                 /* Round the mantissa.  */
471                                 long double tail = mantissa;
472                                 size_t q;
473
474                                 for (q = precision; ; q--)
475                                   {
476                                     int digit = (int) tail;
477                                     tail -= digit;
478                                     if (q == 0)
479                                       {
480                                         if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
481                                           tail = 1 - tail;
482                                         else
483                                           tail = - tail;
484                                         break;
485                                       }
486                                     tail *= 16.0L;
487                                   }
488                                 if (tail != 0.0L)
489                                   for (q = precision; q > 0; q--)
490                                     tail *= 0.0625L;
491                                 mantissa += tail;
492                               }
493
494                             *p++ = '0';
495                             *p++ = dp->conversion - 'A' + 'X';
496                             pad_ptr = p;
497                             {
498                               int digit;
499
500                               digit = (int) mantissa;
501                               mantissa -= digit;
502                               *p++ = '0' + digit;
503                               if ((flags & FLAG_ALT)
504                                   || mantissa > 0.0L || precision > 0)
505                                 {
506                                   const char *point =
507                                     localeconv () -> decimal_point;
508                                   /* The decimal point is always a single byte:
509                                      either '.' or ','.  */
510                                   *p++ = (point[0] != '\0' ? point[0] : '.');
511                                   /* This loop terminates because we assume
512                                      that FLT_RADIX is a power of 2.  */
513                                   while (mantissa > 0.0L)
514                                     {
515                                       mantissa *= 16.0L;
516                                       digit = (int) mantissa;
517                                       mantissa -= digit;
518                                       *p++ = digit
519                                              + (digit < 10
520                                                 ? '0'
521                                                 : dp->conversion - 10);
522                                       if (precision > 0)
523                                         precision--;
524                                     }
525                                   while (precision > 0)
526                                     {
527                                       *p++ = '0';
528                                       precision--;
529                                     }
530                                 }
531                               }
532                               *p++ = dp->conversion - 'A' + 'P';
533 #  if WIDE_CHAR_VERSION
534                               {
535                                 static const wchar_t decimal_format[] =
536                                   { '%', '+', 'd', '\0' };
537                                 SNPRINTF (p, 6 + 1, decimal_format, exponent);
538                               }
539 #  else
540                               sprintf (p, "%+d", exponent);
541 #  endif
542                               while (*p != '\0')
543                                 p++;
544                           }
545                       }
546                   }
547                 else
548 # endif
549                   {
550                     double arg = a.arg[dp->arg_index].a.a_double;
551
552                     if (isnan (arg))
553                       {
554                         if (dp->conversion == 'A')
555                           {
556                             *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
557                           }
558                         else
559                           {
560                             *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
561                           }
562                       }
563                     else
564                       {
565                         int sign = 0;
566
567                         if (arg < 0.0)
568                           {
569                             sign = -1;
570                             arg = -arg;
571                           }
572                         else if (arg == 0.0)
573                           {
574                             /* Distinguish 0.0 and -0.0.  */
575                             static double plus_zero = 0.0;
576                             double arg_mem = arg;
577                             if (memcmp (&plus_zero, &arg_mem, SIZEOF_DBL) != 0)
578                               {
579                                 sign = -1;
580                                 arg = -arg;
581                               }
582                           }
583
584                         if (sign < 0)
585                           *p++ = '-';
586                         else if (flags & FLAG_SHOWSIGN)
587                           *p++ = '+';
588                         else if (flags & FLAG_SPACE)
589                           *p++ = ' ';
590
591                         if (arg > 0.0 && arg + arg == arg)
592                           {
593                             if (dp->conversion == 'A')
594                               {
595                                 *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
596                               }
597                             else
598                               {
599                                 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
600                               }
601                           }
602                         else
603                           {
604                             int exponent;
605                             double mantissa;
606
607                             if (arg > 0.0)
608                               mantissa = printf_frexp (arg, &exponent);
609                             else
610                               {
611                                 exponent = 0;
612                                 mantissa = 0.0;
613                               }
614
615                             if (has_precision
616                                 && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
617                               {
618                                 /* Round the mantissa.  */
619                                 double tail = mantissa;
620                                 size_t q;
621
622                                 for (q = precision; ; q--)
623                                   {
624                                     int digit = (int) tail;
625                                     tail -= digit;
626                                     if (q == 0)
627                                       {
628                                         if (digit & 1 ? tail >= 0.5 : tail > 0.5)
629                                           tail = 1 - tail;
630                                         else
631                                           tail = - tail;
632                                         break;
633                                       }
634                                     tail *= 16.0;
635                                   }
636                                 if (tail != 0.0)
637                                   for (q = precision; q > 0; q--)
638                                     tail *= 0.0625;
639                                 mantissa += tail;
640                               }
641
642                             *p++ = '0';
643                             *p++ = dp->conversion - 'A' + 'X';
644                             pad_ptr = p;
645                             {
646                               int digit;
647
648                               digit = (int) mantissa;
649                               mantissa -= digit;
650                               *p++ = '0' + digit;
651                               if ((flags & FLAG_ALT)
652                                   || mantissa > 0.0 || precision > 0)
653                                 {
654                                   const char *point =
655                                     localeconv () -> decimal_point;
656                                   /* The decimal point is always a single byte:
657                                      either '.' or ','.  */
658                                   *p++ = (point[0] != '\0' ? point[0] : '.');
659                                   /* This loop terminates because we assume
660                                      that FLT_RADIX is a power of 2.  */
661                                   while (mantissa > 0.0)
662                                     {
663                                       mantissa *= 16.0;
664                                       digit = (int) mantissa;
665                                       mantissa -= digit;
666                                       *p++ = digit
667                                              + (digit < 10
668                                                 ? '0'
669                                                 : dp->conversion - 10);
670                                       if (precision > 0)
671                                         precision--;
672                                     }
673                                   while (precision > 0)
674                                     {
675                                       *p++ = '0';
676                                       precision--;
677                                     }
678                                 }
679                               }
680                               *p++ = dp->conversion - 'A' + 'P';
681 # if WIDE_CHAR_VERSION
682                               {
683                                 static const wchar_t decimal_format[] =
684                                   { '%', '+', 'd', '\0' };
685                                 SNPRINTF (p, 6 + 1, decimal_format, exponent);
686                               }
687 # else
688                               sprintf (p, "%+d", exponent);
689 # endif
690                               while (*p != '\0')
691                                 p++;
692                           }
693                       }
694                   }
695                 /* The generated string now extends from tmp to p, with the
696                    zero padding insertion point being at pad_ptr.  */
697                 if (has_width && p - tmp < width)
698                   {
699                     size_t pad = width - (p - tmp);
700                     CHAR_T *end = p + pad;
701
702                     if (flags & FLAG_LEFT)
703                       {
704                         /* Pad with spaces on the right.  */
705                         for (; pad > 0; pad--)
706                           *p++ = ' ';
707                       }
708                     else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
709                       {
710                         /* Pad with zeroes.  */
711                         CHAR_T *q = end;
712
713                         while (p > pad_ptr)
714                           *--q = *--p;
715                         for (; pad > 0; pad--)
716                           *p++ = '0';
717                       }
718                     else
719                       {
720                         /* Pad with spaces on the left.  */
721                         CHAR_T *q = end;
722
723                         while (p > tmp)
724                           *--q = *--p;
725                         for (; pad > 0; pad--)
726                           *p++ = ' ';
727                       }
728
729                     p = end;
730                   }
731
732                 {
733                   size_t count = p - tmp;
734
735                   if (count >= tmp_length)
736                     /* tmp_length was incorrectly calculated - fix the
737                        code above!  */
738                     abort ();
739
740                   /* Make room for the result.  */
741                   if (count >= allocated - length)
742                     {
743                       size_t n = xsum (length, count);
744
745                       ENSURE_ALLOCATION (n);
746                     }
747
748                   /* Append the result.  */
749                   memcpy (result + length, tmp, count * sizeof (CHAR_T));
750                   if (tmp != tmpbuf)
751                     free (tmp);
752                   length += count;
753                 }
754               }
755 #endif
756             else
757               {
758                 arg_type type = a.arg[dp->arg_index].type;
759                 CHAR_T *p;
760                 unsigned int prefix_count;
761                 int prefixes[2];
762 #if !USE_SNPRINTF
763                 size_t tmp_length;
764                 CHAR_T tmpbuf[700];
765                 CHAR_T *tmp;
766
767                 /* Allocate a temporary buffer of sufficient size for calling
768                    sprintf.  */
769                 {
770                   size_t width;
771                   size_t precision;
772
773                   width = 0;
774                   if (dp->width_start != dp->width_end)
775                     {
776                       if (dp->width_arg_index != ARG_NONE)
777                         {
778                           int arg;
779
780                           if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
781                             abort ();
782                           arg = a.arg[dp->width_arg_index].a.a_int;
783                           width = (arg < 0 ? (unsigned int) (-arg) : arg);
784                         }
785                       else
786                         {
787                           const CHAR_T *digitp = dp->width_start;
788
789                           do
790                             width = xsum (xtimes (width, 10), *digitp++ - '0');
791                           while (digitp != dp->width_end);
792                         }
793                     }
794
795                   precision = 6;
796                   if (dp->precision_start != dp->precision_end)
797                     {
798                       if (dp->precision_arg_index != ARG_NONE)
799                         {
800                           int arg;
801
802                           if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
803                             abort ();
804                           arg = a.arg[dp->precision_arg_index].a.a_int;
805                           precision = (arg < 0 ? 0 : arg);
806                         }
807                       else
808                         {
809                           const CHAR_T *digitp = dp->precision_start + 1;
810
811                           precision = 0;
812                           while (digitp != dp->precision_end)
813                             precision = xsum (xtimes (precision, 10), *digitp++ - '0');
814                         }
815                     }
816
817                   switch (dp->conversion)
818                     {
819
820                     case 'd': case 'i': case 'u':
821 # if HAVE_LONG_LONG_INT
822                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
823                         tmp_length =
824                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
825                                           * 0.30103 /* binary -> decimal */
826                                          )
827                           + 1; /* turn floor into ceil */
828                       else
829 # endif
830                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
831                         tmp_length =
832                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
833                                           * 0.30103 /* binary -> decimal */
834                                          )
835                           + 1; /* turn floor into ceil */
836                       else
837                         tmp_length =
838                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
839                                           * 0.30103 /* binary -> decimal */
840                                          )
841                           + 1; /* turn floor into ceil */
842                       if (tmp_length < precision)
843                         tmp_length = precision;
844                       /* Multiply by 2, as an estimate for FLAG_GROUP.  */
845                       tmp_length = xsum (tmp_length, tmp_length);
846                       /* Add 1, to account for a leading sign.  */
847                       tmp_length = xsum (tmp_length, 1);
848                       break;
849
850                     case 'o':
851 # if HAVE_LONG_LONG_INT
852                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
853                         tmp_length =
854                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
855                                           * 0.333334 /* binary -> octal */
856                                          )
857                           + 1; /* turn floor into ceil */
858                       else
859 # endif
860                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
861                         tmp_length =
862                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
863                                           * 0.333334 /* binary -> octal */
864                                          )
865                           + 1; /* turn floor into ceil */
866                       else
867                         tmp_length =
868                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
869                                           * 0.333334 /* binary -> octal */
870                                          )
871                           + 1; /* turn floor into ceil */
872                       if (tmp_length < precision)
873                         tmp_length = precision;
874                       /* Add 1, to account for a leading sign.  */
875                       tmp_length = xsum (tmp_length, 1);
876                       break;
877
878                     case 'x': case 'X':
879 # if HAVE_LONG_LONG_INT
880                       if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
881                         tmp_length =
882                           (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
883                                           * 0.25 /* binary -> hexadecimal */
884                                          )
885                           + 1; /* turn floor into ceil */
886                       else
887 # endif
888                       if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
889                         tmp_length =
890                           (unsigned int) (sizeof (unsigned long) * CHAR_BIT
891                                           * 0.25 /* binary -> hexadecimal */
892                                          )
893                           + 1; /* turn floor into ceil */
894                       else
895                         tmp_length =
896                           (unsigned int) (sizeof (unsigned int) * CHAR_BIT
897                                           * 0.25 /* binary -> hexadecimal */
898                                          )
899                           + 1; /* turn floor into ceil */
900                       if (tmp_length < precision)
901                         tmp_length = precision;
902                       /* Add 2, to account for a leading sign or alternate form.  */
903                       tmp_length = xsum (tmp_length, 2);
904                       break;
905
906                     case 'f': case 'F':
907 # if HAVE_LONG_DOUBLE
908                       if (type == TYPE_LONGDOUBLE)
909                         tmp_length =
910                           (unsigned int) (LDBL_MAX_EXP
911                                           * 0.30103 /* binary -> decimal */
912                                           * 2 /* estimate for FLAG_GROUP */
913                                          )
914                           + 1 /* turn floor into ceil */
915                           + 10; /* sign, decimal point etc. */
916                       else
917 # endif
918                         tmp_length =
919                           (unsigned int) (DBL_MAX_EXP
920                                           * 0.30103 /* binary -> decimal */
921                                           * 2 /* estimate for FLAG_GROUP */
922                                          )
923                           + 1 /* turn floor into ceil */
924                           + 10; /* sign, decimal point etc. */
925                       tmp_length = xsum (tmp_length, precision);
926                       break;
927
928                     case 'e': case 'E': case 'g': case 'G':
929                       tmp_length =
930                         12; /* sign, decimal point, exponent etc. */
931                       tmp_length = xsum (tmp_length, precision);
932                       break;
933
934                     case 'a': case 'A':
935 # if HAVE_LONG_DOUBLE
936                       if (type == TYPE_LONGDOUBLE)
937                         tmp_length =
938                           (unsigned int) (LDBL_DIG
939                                           * 0.831 /* decimal -> hexadecimal */
940                                          )
941                           + 1; /* turn floor into ceil */
942                       else
943 # endif
944                         tmp_length =
945                           (unsigned int) (DBL_DIG
946                                           * 0.831 /* decimal -> hexadecimal */
947                                          )
948                           + 1; /* turn floor into ceil */
949                       if (tmp_length < precision)
950                         tmp_length = precision;
951                       /* Account for sign, decimal point etc. */
952                       tmp_length = xsum (tmp_length, 12);
953                       break;
954
955                     case 'c':
956 # if HAVE_WINT_T && !WIDE_CHAR_VERSION
957                       if (type == TYPE_WIDE_CHAR)
958                         tmp_length = MB_CUR_MAX;
959                       else
960 # endif
961                         tmp_length = 1;
962                       break;
963
964                     case 's':
965 # if HAVE_WCHAR_T
966                       if (type == TYPE_WIDE_STRING)
967                         {
968                           tmp_length =
969                             local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
970
971 #  if !WIDE_CHAR_VERSION
972                           tmp_length = xtimes (tmp_length, MB_CUR_MAX);
973 #  endif
974                         }
975                       else
976 # endif
977                         tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
978                       break;
979
980                     case 'p':
981                       tmp_length =
982                         (unsigned int) (sizeof (void *) * CHAR_BIT
983                                         * 0.25 /* binary -> hexadecimal */
984                                        )
985                           + 1 /* turn floor into ceil */
986                           + 2; /* account for leading 0x */
987                       break;
988
989                     default:
990                       abort ();
991                     }
992
993                   if (tmp_length < width)
994                     tmp_length = width;
995
996                   tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
997                 }
998
999                 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
1000                   tmp = tmpbuf;
1001                 else
1002                   {
1003                     size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
1004
1005                     if (size_overflow_p (tmp_memsize))
1006                       /* Overflow, would lead to out of memory.  */
1007                       goto out_of_memory;
1008                     tmp = (CHAR_T *) malloc (tmp_memsize);
1009                     if (tmp == NULL)
1010                       /* Out of memory.  */
1011                       goto out_of_memory;
1012                   }
1013 #endif
1014
1015                 /* Construct the format string for calling snprintf or
1016                    sprintf.  */
1017                 p = buf;
1018                 *p++ = '%';
1019                 if (dp->flags & FLAG_GROUP)
1020                   *p++ = '\'';
1021                 if (dp->flags & FLAG_LEFT)
1022                   *p++ = '-';
1023                 if (dp->flags & FLAG_SHOWSIGN)
1024                   *p++ = '+';
1025                 if (dp->flags & FLAG_SPACE)
1026                   *p++ = ' ';
1027                 if (dp->flags & FLAG_ALT)
1028                   *p++ = '#';
1029                 if (dp->flags & FLAG_ZERO)
1030                   *p++ = '0';
1031                 if (dp->width_start != dp->width_end)
1032                   {
1033                     size_t n = dp->width_end - dp->width_start;
1034                     memcpy (p, dp->width_start, n * sizeof (CHAR_T));
1035                     p += n;
1036                   }
1037                 if (dp->precision_start != dp->precision_end)
1038                   {
1039                     size_t n = dp->precision_end - dp->precision_start;
1040                     memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
1041                     p += n;
1042                   }
1043
1044                 switch (type)
1045                   {
1046 #if HAVE_LONG_LONG_INT
1047                   case TYPE_LONGLONGINT:
1048                   case TYPE_ULONGLONGINT:
1049                     *p++ = 'l';
1050                     /*FALLTHROUGH*/
1051 #endif
1052                   case TYPE_LONGINT:
1053                   case TYPE_ULONGINT:
1054 #if HAVE_WINT_T
1055                   case TYPE_WIDE_CHAR:
1056 #endif
1057 #if HAVE_WCHAR_T
1058                   case TYPE_WIDE_STRING:
1059 #endif
1060                     *p++ = 'l';
1061                     break;
1062 #if HAVE_LONG_DOUBLE
1063                   case TYPE_LONGDOUBLE:
1064                     *p++ = 'L';
1065                     break;
1066 #endif
1067                   default:
1068                     break;
1069                   }
1070                 *p = dp->conversion;
1071 #if USE_SNPRINTF
1072                 p[1] = '%';
1073                 p[2] = 'n';
1074                 p[3] = '\0';
1075 #else
1076                 p[1] = '\0';
1077 #endif
1078
1079                 /* Construct the arguments for calling snprintf or sprintf.  */
1080                 prefix_count = 0;
1081                 if (dp->width_arg_index != ARG_NONE)
1082                   {
1083                     if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
1084                       abort ();
1085                     prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
1086                   }
1087                 if (dp->precision_arg_index != ARG_NONE)
1088                   {
1089                     if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
1090                       abort ();
1091                     prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
1092                   }
1093
1094 #if USE_SNPRINTF
1095                 /* Prepare checking whether snprintf returns the count
1096                    via %n.  */
1097                 ENSURE_ALLOCATION (xsum (length, 1));
1098                 result[length] = '\0';
1099 #endif
1100
1101                 for (;;)
1102                   {
1103                     size_t maxlen;
1104                     int count;
1105                     int retcount;
1106
1107                     maxlen = allocated - length;
1108                     count = -1;
1109                     retcount = 0;
1110
1111 #if USE_SNPRINTF
1112                     /* SNPRINTF can fail if maxlen > INT_MAX.  */
1113                     if (maxlen > INT_MAX)
1114                       goto overflow;
1115 # define SNPRINTF_BUF(arg) \
1116                     switch (prefix_count)                                   \
1117                       {                                                     \
1118                       case 0:                                               \
1119                         retcount = SNPRINTF (result + length, maxlen, buf,  \
1120                                              arg, &count);                  \
1121                         break;                                              \
1122                       case 1:                                               \
1123                         retcount = SNPRINTF (result + length, maxlen, buf,  \
1124                                              prefixes[0], arg, &count);     \
1125                         break;                                              \
1126                       case 2:                                               \
1127                         retcount = SNPRINTF (result + length, maxlen, buf,  \
1128                                              prefixes[0], prefixes[1], arg, \
1129                                              &count);                       \
1130                         break;                                              \
1131                       default:                                              \
1132                         abort ();                                           \
1133                       }
1134 #else
1135 # define SNPRINTF_BUF(arg) \
1136                     switch (prefix_count)                                   \
1137                       {                                                     \
1138                       case 0:                                               \
1139                         count = sprintf (tmp, buf, arg);                    \
1140                         break;                                              \
1141                       case 1:                                               \
1142                         count = sprintf (tmp, buf, prefixes[0], arg);       \
1143                         break;                                              \
1144                       case 2:                                               \
1145                         count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
1146                                          arg);                              \
1147                         break;                                              \
1148                       default:                                              \
1149                         abort ();                                           \
1150                       }
1151 #endif
1152
1153                     switch (type)
1154                       {
1155                       case TYPE_SCHAR:
1156                         {
1157                           int arg = a.arg[dp->arg_index].a.a_schar;
1158                           SNPRINTF_BUF (arg);
1159                         }
1160                         break;
1161                       case TYPE_UCHAR:
1162                         {
1163                           unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
1164                           SNPRINTF_BUF (arg);
1165                         }
1166                         break;
1167                       case TYPE_SHORT:
1168                         {
1169                           int arg = a.arg[dp->arg_index].a.a_short;
1170                           SNPRINTF_BUF (arg);
1171                         }
1172                         break;
1173                       case TYPE_USHORT:
1174                         {
1175                           unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
1176                           SNPRINTF_BUF (arg);
1177                         }
1178                         break;
1179                       case TYPE_INT:
1180                         {
1181                           int arg = a.arg[dp->arg_index].a.a_int;
1182                           SNPRINTF_BUF (arg);
1183                         }
1184                         break;
1185                       case TYPE_UINT:
1186                         {
1187                           unsigned int arg = a.arg[dp->arg_index].a.a_uint;
1188                           SNPRINTF_BUF (arg);
1189                         }
1190                         break;
1191                       case TYPE_LONGINT:
1192                         {
1193                           long int arg = a.arg[dp->arg_index].a.a_longint;
1194                           SNPRINTF_BUF (arg);
1195                         }
1196                         break;
1197                       case TYPE_ULONGINT:
1198                         {
1199                           unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
1200                           SNPRINTF_BUF (arg);
1201                         }
1202                         break;
1203 #if HAVE_LONG_LONG_INT
1204                       case TYPE_LONGLONGINT:
1205                         {
1206                           long long int arg = a.arg[dp->arg_index].a.a_longlongint;
1207                           SNPRINTF_BUF (arg);
1208                         }
1209                         break;
1210                       case TYPE_ULONGLONGINT:
1211                         {
1212                           unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
1213                           SNPRINTF_BUF (arg);
1214                         }
1215                         break;
1216 #endif
1217                       case TYPE_DOUBLE:
1218                         {
1219                           double arg = a.arg[dp->arg_index].a.a_double;
1220                           SNPRINTF_BUF (arg);
1221                         }
1222                         break;
1223 #if HAVE_LONG_DOUBLE
1224                       case TYPE_LONGDOUBLE:
1225                         {
1226                           long double arg = a.arg[dp->arg_index].a.a_longdouble;
1227                           SNPRINTF_BUF (arg);
1228                         }
1229                         break;
1230 #endif
1231                       case TYPE_CHAR:
1232                         {
1233                           int arg = a.arg[dp->arg_index].a.a_char;
1234                           SNPRINTF_BUF (arg);
1235                         }
1236                         break;
1237 #if HAVE_WINT_T
1238                       case TYPE_WIDE_CHAR:
1239                         {
1240                           wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
1241                           SNPRINTF_BUF (arg);
1242                         }
1243                         break;
1244 #endif
1245                       case TYPE_STRING:
1246                         {
1247                           const char *arg = a.arg[dp->arg_index].a.a_string;
1248                           SNPRINTF_BUF (arg);
1249                         }
1250                         break;
1251 #if HAVE_WCHAR_T
1252                       case TYPE_WIDE_STRING:
1253                         {
1254                           const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
1255                           SNPRINTF_BUF (arg);
1256                         }
1257                         break;
1258 #endif
1259                       case TYPE_POINTER:
1260                         {
1261                           void *arg = a.arg[dp->arg_index].a.a_pointer;
1262                           SNPRINTF_BUF (arg);
1263                         }
1264                         break;
1265                       default:
1266                         abort ();
1267                       }
1268
1269 #if USE_SNPRINTF
1270                     /* Portability: Not all implementations of snprintf()
1271                        are ISO C 99 compliant.  Determine the number of
1272                        bytes that snprintf() has produced or would have
1273                        produced.  */
1274                     if (count >= 0)
1275                       {
1276                         /* Verify that snprintf() has NUL-terminated its
1277                            result.  */
1278                         if (count < maxlen && result[length + count] != '\0')
1279                           abort ();
1280                         /* Portability hack.  */
1281                         if (retcount > count)
1282                           count = retcount;
1283                       }
1284                     else
1285                       {
1286                         /* snprintf() doesn't understand the '%n'
1287                            directive.  */
1288                         if (p[1] != '\0')
1289                           {
1290                             /* Don't use the '%n' directive; instead, look
1291                                at the snprintf() return value.  */
1292                             p[1] = '\0';
1293                             continue;
1294                           }
1295                         else
1296                           {
1297                             /* Look at the snprintf() return value.  */
1298                             if (retcount < 0)
1299                               {
1300                                 /* HP-UX 10.20 snprintf() is doubly deficient:
1301                                    It doesn't understand the '%n' directive,
1302                                    *and* it returns -1 (rather than the length
1303                                    that would have been required) when the
1304                                    buffer is too small.  */
1305                                 size_t bigger_need =
1306                                   xsum (xtimes (allocated, 2), 12);
1307                                 ENSURE_ALLOCATION (bigger_need);
1308                                 continue;
1309                               }
1310                             else
1311                               count = retcount;
1312                           }
1313                       }
1314 #endif
1315
1316                     /* Attempt to handle failure.  */
1317                     if (count < 0)
1318                       {
1319                         if (!(result == resultbuf || result == NULL))
1320                           free (result);
1321                         if (buf_malloced != NULL)
1322                           free (buf_malloced);
1323                         CLEANUP ();
1324                         errno = EINVAL;
1325                         return NULL;
1326                       }
1327
1328 #if !USE_SNPRINTF
1329                     if (count >= tmp_length)
1330                       /* tmp_length was incorrectly calculated - fix the
1331                          code above!  */
1332                       abort ();
1333 #endif
1334
1335                     /* Make room for the result.  */
1336                     if (count >= maxlen)
1337                       {
1338                         /* Need at least count bytes.  But allocate
1339                            proportionally, to avoid looping eternally if
1340                            snprintf() reports a too small count.  */
1341                         size_t n =
1342                           xmax (xsum (length, count), xtimes (allocated, 2));
1343
1344                         ENSURE_ALLOCATION (n);
1345 #if USE_SNPRINTF
1346                         continue;
1347 #endif
1348                       }
1349
1350 #if USE_SNPRINTF
1351                     /* The snprintf() result did fit.  */
1352 #else
1353                     /* Append the sprintf() result.  */
1354                     memcpy (result + length, tmp, count * sizeof (CHAR_T));
1355                     if (tmp != tmpbuf)
1356                       free (tmp);
1357 #endif
1358
1359                     length += count;
1360                     break;
1361                   }
1362               }
1363           }
1364       }
1365
1366     /* Add the final NUL.  */
1367     ENSURE_ALLOCATION (xsum (length, 1));
1368     result[length] = '\0';
1369
1370     if (result != resultbuf && length + 1 < allocated)
1371       {
1372         /* Shrink the allocated memory if possible.  */
1373         CHAR_T *memory;
1374
1375         memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
1376         if (memory != NULL)
1377           result = memory;
1378       }
1379
1380     if (buf_malloced != NULL)
1381       free (buf_malloced);
1382     CLEANUP ();
1383     *lengthp = length;
1384     /* Note that we can produce a big string of a length > INT_MAX.  POSIX
1385        says that snprintf() fails with errno = EOVERFLOW in this case, but
1386        that's only because snprintf() returns an 'int'.  This function does
1387        not have this limitation.  */
1388     return result;
1389
1390   overflow:
1391     if (!(result == resultbuf || result == NULL))
1392       free (result);
1393     if (buf_malloced != NULL)
1394       free (buf_malloced);
1395     CLEANUP ();
1396     errno = EOVERFLOW;
1397     return NULL;
1398
1399   out_of_memory:
1400     if (!(result == resultbuf || result == NULL))
1401       free (result);
1402     if (buf_malloced != NULL)
1403       free (buf_malloced);
1404   out_of_memory_1:
1405     CLEANUP ();
1406     errno = ENOMEM;
1407     return NULL;
1408   }
1409 }
1410
1411 #undef SNPRINTF
1412 #undef USE_SNPRINTF
1413 #undef PRINTF_PARSE
1414 #undef DIRECTIVES
1415 #undef DIRECTIVE
1416 #undef CHAR_T
1417 #undef VASNPRINTF