Update.
[gsasl.git] / lib / gl / vasnprintf.c
blob23b626fea2e31e502afff0faf7b71ad43accc07f
1 /* vsprintf with automatic memory allocation.
2 Copyright (C) 1999, 2002-2006 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1, or (at your option)
7 any later version.
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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser 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. */
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
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 #ifndef IN_LIBINTL
29 # include <alloca.h>
30 #endif
32 /* Specification. */
33 #if WIDE_CHAR_VERSION
34 # include "vasnwprintf.h"
35 #else
36 # include "vasnprintf.h"
37 #endif
39 #include <stdio.h> /* snprintf(), sprintf() */
40 #include <stdlib.h> /* abort(), malloc(), realloc(), free() */
41 #include <string.h> /* memcpy(), strlen() */
42 #include <errno.h> /* errno */
43 #include <limits.h> /* CHAR_BIT */
44 #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
45 #if WIDE_CHAR_VERSION
46 # include "wprintf-parse.h"
47 #else
48 # include "printf-parse.h"
49 #endif
51 /* Checked size_t computations. */
52 #include "xsize.h"
54 #ifdef HAVE_WCHAR_T
55 # ifdef HAVE_WCSLEN
56 # define local_wcslen wcslen
57 # else
58 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
59 a dependency towards this library, here is a local substitute.
60 Define this substitute only once, even if this file is included
61 twice in the same compilation unit. */
62 # ifndef local_wcslen_defined
63 # define local_wcslen_defined 1
64 static size_t
65 local_wcslen (const wchar_t *s)
67 const wchar_t *ptr;
69 for (ptr = s; *ptr != (wchar_t) 0; ptr++)
71 return ptr - s;
73 # endif
74 # endif
75 #endif
77 #if WIDE_CHAR_VERSION
78 # define VASNPRINTF vasnwprintf
79 # define CHAR_T wchar_t
80 # define DIRECTIVE wchar_t_directive
81 # define DIRECTIVES wchar_t_directives
82 # define PRINTF_PARSE wprintf_parse
83 # define USE_SNPRINTF 1
84 # if HAVE_DECL__SNWPRINTF
85 /* On Windows, the function swprintf() has a different signature than
86 on Unix; we use the _snwprintf() function instead. */
87 # define SNPRINTF _snwprintf
88 # else
89 /* Unix. */
90 # define SNPRINTF swprintf
91 # endif
92 #else
93 # define VASNPRINTF vasnprintf
94 # define CHAR_T char
95 # define DIRECTIVE char_directive
96 # define DIRECTIVES char_directives
97 # define PRINTF_PARSE printf_parse
98 # define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
99 # if HAVE_DECL__SNPRINTF
100 /* Windows. */
101 # define SNPRINTF _snprintf
102 # else
103 /* Unix. */
104 # define SNPRINTF snprintf
105 # endif
106 #endif
108 CHAR_T *
109 VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
111 DIRECTIVES d;
112 arguments a;
114 if (PRINTF_PARSE (format, &d, &a) < 0)
116 errno = EINVAL;
117 return NULL;
120 #define CLEANUP() \
121 free (d.dir); \
122 if (a.arg) \
123 free (a.arg);
125 if (printf_fetchargs (args, &a) < 0)
127 CLEANUP ();
128 errno = EINVAL;
129 return NULL;
133 size_t buf_neededlength;
134 CHAR_T *buf;
135 CHAR_T *buf_malloced;
136 const CHAR_T *cp;
137 size_t i;
138 DIRECTIVE *dp;
139 /* Output string accumulator. */
140 CHAR_T *result;
141 size_t allocated;
142 size_t length;
144 /* Allocate a small buffer that will hold a directive passed to
145 sprintf or snprintf. */
146 buf_neededlength =
147 xsum4 (7, d.max_width_length, d.max_precision_length, 6);
148 #if HAVE_ALLOCA
149 if (buf_neededlength < 4000 / sizeof (CHAR_T))
151 buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
152 buf_malloced = NULL;
154 else
155 #endif
157 size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
158 if (size_overflow_p (buf_memsize))
159 goto out_of_memory_1;
160 buf = (CHAR_T *) malloc (buf_memsize);
161 if (buf == NULL)
162 goto out_of_memory_1;
163 buf_malloced = buf;
166 if (resultbuf != NULL)
168 result = resultbuf;
169 allocated = *lengthp;
171 else
173 result = NULL;
174 allocated = 0;
176 length = 0;
177 /* Invariants:
178 result is either == resultbuf or == NULL or malloc-allocated.
179 If length > 0, then result != NULL. */
181 /* Ensures that allocated >= needed. Aborts through a jump to
182 out_of_memory if needed is SIZE_MAX or otherwise too big. */
183 #define ENSURE_ALLOCATION(needed) \
184 if ((needed) > allocated) \
186 size_t memory_size; \
187 CHAR_T *memory; \
189 allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
190 if ((needed) > allocated) \
191 allocated = (needed); \
192 memory_size = xtimes (allocated, sizeof (CHAR_T)); \
193 if (size_overflow_p (memory_size)) \
194 goto out_of_memory; \
195 if (result == resultbuf || result == NULL) \
196 memory = (CHAR_T *) malloc (memory_size); \
197 else \
198 memory = (CHAR_T *) realloc (result, memory_size); \
199 if (memory == NULL) \
200 goto out_of_memory; \
201 if (result == resultbuf && length > 0) \
202 memcpy (memory, result, length * sizeof (CHAR_T)); \
203 result = memory; \
206 for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
208 if (cp != dp->dir_start)
210 size_t n = dp->dir_start - cp;
211 size_t augmented_length = xsum (length, n);
213 ENSURE_ALLOCATION (augmented_length);
214 memcpy (result + length, cp, n * sizeof (CHAR_T));
215 length = augmented_length;
217 if (i == d.count)
218 break;
220 /* Execute a single directive. */
221 if (dp->conversion == '%')
223 size_t augmented_length;
225 if (!(dp->arg_index == ARG_NONE))
226 abort ();
227 augmented_length = xsum (length, 1);
228 ENSURE_ALLOCATION (augmented_length);
229 result[length] = '%';
230 length = augmented_length;
232 else
234 if (!(dp->arg_index != ARG_NONE))
235 abort ();
237 if (dp->conversion == 'n')
239 switch (a.arg[dp->arg_index].type)
241 case TYPE_COUNT_SCHAR_POINTER:
242 *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
243 break;
244 case TYPE_COUNT_SHORT_POINTER:
245 *a.arg[dp->arg_index].a.a_count_short_pointer = length;
246 break;
247 case TYPE_COUNT_INT_POINTER:
248 *a.arg[dp->arg_index].a.a_count_int_pointer = length;
249 break;
250 case TYPE_COUNT_LONGINT_POINTER:
251 *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
252 break;
253 #ifdef HAVE_LONG_LONG
254 case TYPE_COUNT_LONGLONGINT_POINTER:
255 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
256 break;
257 #endif
258 default:
259 abort ();
262 else
264 arg_type type = a.arg[dp->arg_index].type;
265 CHAR_T *p;
266 unsigned int prefix_count;
267 int prefixes[2];
268 #if !USE_SNPRINTF
269 size_t tmp_length;
270 CHAR_T tmpbuf[700];
271 CHAR_T *tmp;
273 /* Allocate a temporary buffer of sufficient size for calling
274 sprintf. */
276 size_t width;
277 size_t precision;
279 width = 0;
280 if (dp->width_start != dp->width_end)
282 if (dp->width_arg_index != ARG_NONE)
284 int arg;
286 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
287 abort ();
288 arg = a.arg[dp->width_arg_index].a.a_int;
289 width = (arg < 0 ? (unsigned int) (-arg) : arg);
291 else
293 const CHAR_T *digitp = dp->width_start;
296 width = xsum (xtimes (width, 10), *digitp++ - '0');
297 while (digitp != dp->width_end);
301 precision = 6;
302 if (dp->precision_start != dp->precision_end)
304 if (dp->precision_arg_index != ARG_NONE)
306 int arg;
308 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
309 abort ();
310 arg = a.arg[dp->precision_arg_index].a.a_int;
311 precision = (arg < 0 ? 0 : arg);
313 else
315 const CHAR_T *digitp = dp->precision_start + 1;
317 precision = 0;
318 while (digitp != dp->precision_end)
319 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
323 switch (dp->conversion)
326 case 'd': case 'i': case 'u':
327 # ifdef HAVE_LONG_LONG
328 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
329 tmp_length =
330 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
331 * 0.30103 /* binary -> decimal */
333 + 1; /* turn floor into ceil */
334 else
335 # endif
336 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
337 tmp_length =
338 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
339 * 0.30103 /* binary -> decimal */
341 + 1; /* turn floor into ceil */
342 else
343 tmp_length =
344 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
345 * 0.30103 /* binary -> decimal */
347 + 1; /* turn floor into ceil */
348 if (tmp_length < precision)
349 tmp_length = precision;
350 /* Multiply by 2, as an estimate for FLAG_GROUP. */
351 tmp_length = xsum (tmp_length, tmp_length);
352 /* Add 1, to account for a leading sign. */
353 tmp_length = xsum (tmp_length, 1);
354 break;
356 case 'o':
357 # ifdef HAVE_LONG_LONG
358 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
359 tmp_length =
360 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
361 * 0.333334 /* binary -> octal */
363 + 1; /* turn floor into ceil */
364 else
365 # endif
366 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
367 tmp_length =
368 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
369 * 0.333334 /* binary -> octal */
371 + 1; /* turn floor into ceil */
372 else
373 tmp_length =
374 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
375 * 0.333334 /* binary -> octal */
377 + 1; /* turn floor into ceil */
378 if (tmp_length < precision)
379 tmp_length = precision;
380 /* Add 1, to account for a leading sign. */
381 tmp_length = xsum (tmp_length, 1);
382 break;
384 case 'x': case 'X':
385 # ifdef HAVE_LONG_LONG
386 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
387 tmp_length =
388 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
389 * 0.25 /* binary -> hexadecimal */
391 + 1; /* turn floor into ceil */
392 else
393 # endif
394 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
395 tmp_length =
396 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
397 * 0.25 /* binary -> hexadecimal */
399 + 1; /* turn floor into ceil */
400 else
401 tmp_length =
402 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
403 * 0.25 /* binary -> hexadecimal */
405 + 1; /* turn floor into ceil */
406 if (tmp_length < precision)
407 tmp_length = precision;
408 /* Add 2, to account for a leading sign or alternate form. */
409 tmp_length = xsum (tmp_length, 2);
410 break;
412 case 'f': case 'F':
413 # ifdef HAVE_LONG_DOUBLE
414 if (type == TYPE_LONGDOUBLE)
415 tmp_length =
416 (unsigned int) (LDBL_MAX_EXP
417 * 0.30103 /* binary -> decimal */
418 * 2 /* estimate for FLAG_GROUP */
420 + 1 /* turn floor into ceil */
421 + 10; /* sign, decimal point etc. */
422 else
423 # endif
424 tmp_length =
425 (unsigned int) (DBL_MAX_EXP
426 * 0.30103 /* binary -> decimal */
427 * 2 /* estimate for FLAG_GROUP */
429 + 1 /* turn floor into ceil */
430 + 10; /* sign, decimal point etc. */
431 tmp_length = xsum (tmp_length, precision);
432 break;
434 case 'e': case 'E': case 'g': case 'G':
435 case 'a': case 'A':
436 tmp_length =
437 12; /* sign, decimal point, exponent etc. */
438 tmp_length = xsum (tmp_length, precision);
439 break;
441 case 'c':
442 # if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
443 if (type == TYPE_WIDE_CHAR)
444 tmp_length = MB_CUR_MAX;
445 else
446 # endif
447 tmp_length = 1;
448 break;
450 case 's':
451 # ifdef HAVE_WCHAR_T
452 if (type == TYPE_WIDE_STRING)
454 tmp_length =
455 local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
457 # if !WIDE_CHAR_VERSION
458 tmp_length = xtimes (tmp_length, MB_CUR_MAX);
459 # endif
461 else
462 # endif
463 tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
464 break;
466 case 'p':
467 tmp_length =
468 (unsigned int) (sizeof (void *) * CHAR_BIT
469 * 0.25 /* binary -> hexadecimal */
471 + 1 /* turn floor into ceil */
472 + 2; /* account for leading 0x */
473 break;
475 default:
476 abort ();
479 if (tmp_length < width)
480 tmp_length = width;
482 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
485 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
486 tmp = tmpbuf;
487 else
489 size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
491 if (size_overflow_p (tmp_memsize))
492 /* Overflow, would lead to out of memory. */
493 goto out_of_memory;
494 tmp = (CHAR_T *) malloc (tmp_memsize);
495 if (tmp == NULL)
496 /* Out of memory. */
497 goto out_of_memory;
499 #endif
501 /* Construct the format string for calling snprintf or
502 sprintf. */
503 p = buf;
504 *p++ = '%';
505 if (dp->flags & FLAG_GROUP)
506 *p++ = '\'';
507 if (dp->flags & FLAG_LEFT)
508 *p++ = '-';
509 if (dp->flags & FLAG_SHOWSIGN)
510 *p++ = '+';
511 if (dp->flags & FLAG_SPACE)
512 *p++ = ' ';
513 if (dp->flags & FLAG_ALT)
514 *p++ = '#';
515 if (dp->flags & FLAG_ZERO)
516 *p++ = '0';
517 if (dp->width_start != dp->width_end)
519 size_t n = dp->width_end - dp->width_start;
520 memcpy (p, dp->width_start, n * sizeof (CHAR_T));
521 p += n;
523 if (dp->precision_start != dp->precision_end)
525 size_t n = dp->precision_end - dp->precision_start;
526 memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
527 p += n;
530 switch (type)
532 #ifdef HAVE_LONG_LONG
533 case TYPE_LONGLONGINT:
534 case TYPE_ULONGLONGINT:
535 *p++ = 'l';
536 /*FALLTHROUGH*/
537 #endif
538 case TYPE_LONGINT:
539 case TYPE_ULONGINT:
540 #ifdef HAVE_WINT_T
541 case TYPE_WIDE_CHAR:
542 #endif
543 #ifdef HAVE_WCHAR_T
544 case TYPE_WIDE_STRING:
545 #endif
546 *p++ = 'l';
547 break;
548 #ifdef HAVE_LONG_DOUBLE
549 case TYPE_LONGDOUBLE:
550 *p++ = 'L';
551 break;
552 #endif
553 default:
554 break;
556 *p = dp->conversion;
557 #if USE_SNPRINTF
558 p[1] = '%';
559 p[2] = 'n';
560 p[3] = '\0';
561 #else
562 p[1] = '\0';
563 #endif
565 /* Construct the arguments for calling snprintf or sprintf. */
566 prefix_count = 0;
567 if (dp->width_arg_index != ARG_NONE)
569 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
570 abort ();
571 prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
573 if (dp->precision_arg_index != ARG_NONE)
575 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
576 abort ();
577 prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
580 #if USE_SNPRINTF
581 /* Prepare checking whether snprintf returns the count
582 via %n. */
583 ENSURE_ALLOCATION (xsum (length, 1));
584 result[length] = '\0';
585 #endif
587 for (;;)
589 size_t maxlen;
590 int count;
591 int retcount;
593 maxlen = allocated - length;
594 count = -1;
595 retcount = 0;
597 #if USE_SNPRINTF
598 # define SNPRINTF_BUF(arg) \
599 switch (prefix_count) \
601 case 0: \
602 retcount = SNPRINTF (result + length, maxlen, buf, \
603 arg, &count); \
604 break; \
605 case 1: \
606 retcount = SNPRINTF (result + length, maxlen, buf, \
607 prefixes[0], arg, &count); \
608 break; \
609 case 2: \
610 retcount = SNPRINTF (result + length, maxlen, buf, \
611 prefixes[0], prefixes[1], arg, \
612 &count); \
613 break; \
614 default: \
615 abort (); \
617 #else
618 # define SNPRINTF_BUF(arg) \
619 switch (prefix_count) \
621 case 0: \
622 count = sprintf (tmp, buf, arg); \
623 break; \
624 case 1: \
625 count = sprintf (tmp, buf, prefixes[0], arg); \
626 break; \
627 case 2: \
628 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
629 arg); \
630 break; \
631 default: \
632 abort (); \
634 #endif
636 switch (type)
638 case TYPE_SCHAR:
640 int arg = a.arg[dp->arg_index].a.a_schar;
641 SNPRINTF_BUF (arg);
643 break;
644 case TYPE_UCHAR:
646 unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
647 SNPRINTF_BUF (arg);
649 break;
650 case TYPE_SHORT:
652 int arg = a.arg[dp->arg_index].a.a_short;
653 SNPRINTF_BUF (arg);
655 break;
656 case TYPE_USHORT:
658 unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
659 SNPRINTF_BUF (arg);
661 break;
662 case TYPE_INT:
664 int arg = a.arg[dp->arg_index].a.a_int;
665 SNPRINTF_BUF (arg);
667 break;
668 case TYPE_UINT:
670 unsigned int arg = a.arg[dp->arg_index].a.a_uint;
671 SNPRINTF_BUF (arg);
673 break;
674 case TYPE_LONGINT:
676 long int arg = a.arg[dp->arg_index].a.a_longint;
677 SNPRINTF_BUF (arg);
679 break;
680 case TYPE_ULONGINT:
682 unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
683 SNPRINTF_BUF (arg);
685 break;
686 #ifdef HAVE_LONG_LONG
687 case TYPE_LONGLONGINT:
689 long long int arg = a.arg[dp->arg_index].a.a_longlongint;
690 SNPRINTF_BUF (arg);
692 break;
693 case TYPE_ULONGLONGINT:
695 unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
696 SNPRINTF_BUF (arg);
698 break;
699 #endif
700 case TYPE_DOUBLE:
702 double arg = a.arg[dp->arg_index].a.a_double;
703 SNPRINTF_BUF (arg);
705 break;
706 #ifdef HAVE_LONG_DOUBLE
707 case TYPE_LONGDOUBLE:
709 long double arg = a.arg[dp->arg_index].a.a_longdouble;
710 SNPRINTF_BUF (arg);
712 break;
713 #endif
714 case TYPE_CHAR:
716 int arg = a.arg[dp->arg_index].a.a_char;
717 SNPRINTF_BUF (arg);
719 break;
720 #ifdef HAVE_WINT_T
721 case TYPE_WIDE_CHAR:
723 wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
724 SNPRINTF_BUF (arg);
726 break;
727 #endif
728 case TYPE_STRING:
730 const char *arg = a.arg[dp->arg_index].a.a_string;
731 SNPRINTF_BUF (arg);
733 break;
734 #ifdef HAVE_WCHAR_T
735 case TYPE_WIDE_STRING:
737 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
738 SNPRINTF_BUF (arg);
740 break;
741 #endif
742 case TYPE_POINTER:
744 void *arg = a.arg[dp->arg_index].a.a_pointer;
745 SNPRINTF_BUF (arg);
747 break;
748 default:
749 abort ();
752 #if USE_SNPRINTF
753 /* Portability: Not all implementations of snprintf()
754 are ISO C 99 compliant. Determine the number of
755 bytes that snprintf() has produced or would have
756 produced. */
757 if (count >= 0)
759 /* Verify that snprintf() has NUL-terminated its
760 result. */
761 if (count < maxlen && result[length + count] != '\0')
762 abort ();
763 /* Portability hack. */
764 if (retcount > count)
765 count = retcount;
767 else
769 /* snprintf() doesn't understand the '%n'
770 directive. */
771 if (p[1] != '\0')
773 /* Don't use the '%n' directive; instead, look
774 at the snprintf() return value. */
775 p[1] = '\0';
776 continue;
778 else
780 /* Look at the snprintf() return value. */
781 if (retcount < 0)
783 /* HP-UX 10.20 snprintf() is doubly deficient:
784 It doesn't understand the '%n' directive,
785 *and* it returns -1 (rather than the length
786 that would have been required) when the
787 buffer is too small. */
788 size_t bigger_need =
789 xsum (xtimes (allocated, 2), 12);
790 ENSURE_ALLOCATION (bigger_need);
791 continue;
793 else
794 count = retcount;
797 #endif
799 /* Attempt to handle failure. */
800 if (count < 0)
802 if (!(result == resultbuf || result == NULL))
803 free (result);
804 if (buf_malloced != NULL)
805 free (buf_malloced);
806 CLEANUP ();
807 errno = EINVAL;
808 return NULL;
811 #if !USE_SNPRINTF
812 if (count >= tmp_length)
813 /* tmp_length was incorrectly calculated - fix the
814 code above! */
815 abort ();
816 #endif
818 /* Make room for the result. */
819 if (count >= maxlen)
821 /* Need at least count bytes. But allocate
822 proportionally, to avoid looping eternally if
823 snprintf() reports a too small count. */
824 size_t n =
825 xmax (xsum (length, count), xtimes (allocated, 2));
827 ENSURE_ALLOCATION (n);
828 #if USE_SNPRINTF
829 continue;
830 #endif
833 #if USE_SNPRINTF
834 /* The snprintf() result did fit. */
835 #else
836 /* Append the sprintf() result. */
837 memcpy (result + length, tmp, count * sizeof (CHAR_T));
838 if (tmp != tmpbuf)
839 free (tmp);
840 #endif
842 length += count;
843 break;
849 /* Add the final NUL. */
850 ENSURE_ALLOCATION (xsum (length, 1));
851 result[length] = '\0';
853 if (result != resultbuf && length + 1 < allocated)
855 /* Shrink the allocated memory if possible. */
856 CHAR_T *memory;
858 memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
859 if (memory != NULL)
860 result = memory;
863 if (buf_malloced != NULL)
864 free (buf_malloced);
865 CLEANUP ();
866 *lengthp = length;
867 /* Note that we can produce a big string of a length > INT_MAX. POSIX
868 says that snprintf() fails with errno = EOVERFLOW in this case, but
869 that's only because snprintf() returns an 'int'. This function does
870 not have this limitation. */
871 return result;
873 out_of_memory:
874 if (!(result == resultbuf || result == NULL))
875 free (result);
876 if (buf_malloced != NULL)
877 free (buf_malloced);
878 out_of_memory_1:
879 CLEANUP ();
880 errno = ENOMEM;
881 return NULL;
885 #undef SNPRINTF
886 #undef USE_SNPRINTF
887 #undef PRINTF_PARSE
888 #undef DIRECTIVES
889 #undef DIRECTIVE
890 #undef CHAR_T
891 #undef VASNPRINTF