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