1 /* vsprintf with automatic memory allocation.
2 Copyright (C) 1999, 2002-2005 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 #include <sys/cdefs.h>
18 __RCSID("$NetBSD: vasnprintf.c,v 1.4 2016/05/17 14:00:09 christos Exp $");
19
20
21 /* Tell glibc's <stdio.h> to provide a prototype for snprintf().
22 This must come before <config.h> because <config.h> may include
23 <features.h>, and once <features.h> has been included, it's too late. */
24 #ifndef _GNU_SOURCE
25 # define _GNU_SOURCE 1
26 #endif
27
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31 #ifdef __SSP__
32 #undef HAVE_ALLOCA
33 #endif
34 #ifndef __NetBSD__
35 #ifndef IN_LIBINTL
36 # include <alloca.h>
37 #endif
38 #endif
39
40 /* Specification. */
41 #if WIDE_CHAR_VERSION
42 # include "vasnwprintf.h"
43 #else
44 # include "vasnprintf.h"
45 #endif
46
47 #include <stdio.h> /* snprintf(), sprintf() */
48 #include <stdlib.h> /* abort(), malloc(), realloc(), free() */
49 #include <string.h> /* memcpy(), strlen() */
50 #include <errno.h> /* errno */
51 #include <limits.h> /* CHAR_BIT, INT_MAX */
52 #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
53 #if WIDE_CHAR_VERSION
54 # include "wprintf-parse.h"
55 #else
56 # include "printf-parse.h"
57 #endif
58
59 /* Checked size_t computations. */
60 #include "xsize.h"
61
62 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
63 #ifndef EOVERFLOW
64 # define EOVERFLOW E2BIG
65 #endif
66
67 #ifdef HAVE_WCHAR_T
68 # ifdef HAVE_WCSLEN
69 # define local_wcslen wcslen
70 # else
71 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
72 a dependency towards this library, here is a local substitute.
73 Define this substitute only once, even if this file is included
74 twice in the same compilation unit. */
75 # ifndef local_wcslen_defined
76 # define local_wcslen_defined 1
77 static size_t
local_wcslen(const wchar_t * s)78 local_wcslen (const wchar_t *s)
79 {
80 const wchar_t *ptr;
81
82 for (ptr = s; *ptr != (wchar_t) 0; ptr++)
83 ;
84 return ptr - s;
85 }
86 # endif
87 # endif
88 #endif
89
90 #if WIDE_CHAR_VERSION
91 # define VASNPRINTF vasnwprintf
92 # define CHAR_T wchar_t
93 # define DIRECTIVE wchar_t_directive
94 # define DIRECTIVES wchar_t_directives
95 # define PRINTF_PARSE wprintf_parse
96 # define USE_SNPRINTF 1
97 # if HAVE_DECL__SNWPRINTF
98 /* On Windows, the function swprintf() has a different signature than
99 on Unix; we use the _snwprintf() function instead. */
100 # define SNPRINTF _snwprintf
101 # else
102 /* Unix. */
103 # define SNPRINTF swprintf
104 # endif
105 #else
106 # define VASNPRINTF vasnprintf
107 # define CHAR_T char
108 # define DIRECTIVE char_directive
109 # define DIRECTIVES char_directives
110 # define PRINTF_PARSE printf_parse
111 # define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
112 # if HAVE_DECL__SNPRINTF
113 /* Windows. */
114 # define SNPRINTF _snprintf
115 # else
116 /* Unix. */
117 # define SNPRINTF snprintf
118 # endif
119 #endif
120
121 CHAR_T *
VASNPRINTF(CHAR_T * resultbuf,size_t * lengthp,const CHAR_T * format,va_list args)122 VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list args)
123 {
124 DIRECTIVES d;
125 arguments a;
126
127 if (PRINTF_PARSE (format, &d, &a) < 0)
128 {
129 errno = EINVAL;
130 return NULL;
131 }
132
133 #define CLEANUP() \
134 free (d.dir); \
135 if (a.arg) \
136 free (a.arg);
137
138 if (printf_fetchargs (args, &a) < 0)
139 {
140 CLEANUP ();
141 errno = EINVAL;
142 return NULL;
143 }
144
145 {
146 size_t buf_neededlength;
147 CHAR_T *buf;
148 CHAR_T *buf_malloced;
149 const CHAR_T *cp;
150 size_t i;
151 DIRECTIVE *dp;
152 /* Output string accumulator. */
153 CHAR_T *result;
154 size_t allocated;
155 size_t length;
156
157 /* Allocate a small buffer that will hold a directive passed to
158 sprintf or snprintf. */
159 buf_neededlength =
160 xsum4 (7, d.max_width_length, d.max_precision_length, 6);
161 #if HAVE_ALLOCA
162 if (buf_neededlength < 4000 / sizeof (CHAR_T))
163 {
164 buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
165 buf_malloced = NULL;
166 }
167 else
168 #endif
169 {
170 size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
171 if (size_overflow_p (buf_memsize))
172 goto out_of_memory_1;
173 buf = (CHAR_T *) malloc (buf_memsize);
174 if (buf == NULL)
175 goto out_of_memory_1;
176 buf_malloced = buf;
177 }
178
179 if (resultbuf != NULL)
180 {
181 result = resultbuf;
182 allocated = *lengthp;
183 }
184 else
185 {
186 result = NULL;
187 allocated = 0;
188 }
189 length = 0;
190 /* Invariants:
191 result is either == resultbuf or == NULL or malloc-allocated.
192 If length > 0, then result != NULL. */
193
194 /* Ensures that allocated >= needed. Aborts through a jump to
195 out_of_memory if needed is SIZE_MAX or otherwise too big. */
196 #define ENSURE_ALLOCATION(needed) \
197 if ((needed) > allocated) \
198 { \
199 size_t memory_size; \
200 CHAR_T *memory; \
201 \
202 allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
203 if ((needed) > allocated) \
204 allocated = (needed); \
205 memory_size = xtimes (allocated, sizeof (CHAR_T)); \
206 if (size_overflow_p (memory_size)) \
207 goto out_of_memory; \
208 if (result == resultbuf || result == NULL) \
209 memory = (CHAR_T *) malloc (memory_size); \
210 else \
211 memory = (CHAR_T *) realloc (result, memory_size); \
212 if (memory == NULL) \
213 goto out_of_memory; \
214 if (result == resultbuf && length > 0) \
215 memcpy (memory, result, length * sizeof (CHAR_T)); \
216 result = memory; \
217 }
218
219 for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
220 {
221 if (cp != dp->dir_start)
222 {
223 size_t n = dp->dir_start - cp;
224 size_t augmented_length = xsum (length, n);
225
226 ENSURE_ALLOCATION (augmented_length);
227 memcpy (result + length, cp, n * sizeof (CHAR_T));
228 length = augmented_length;
229 }
230 if (i == d.count)
231 break;
232
233 /* Execute a single directive. */
234 if (dp->conversion == '%')
235 {
236 size_t augmented_length;
237
238 if (!(dp->arg_index == ARG_NONE))
239 abort ();
240 augmented_length = xsum (length, 1);
241 ENSURE_ALLOCATION (augmented_length);
242 result[length] = '%';
243 length = augmented_length;
244 }
245 else
246 {
247 if (!(dp->arg_index != ARG_NONE))
248 abort ();
249
250 if (dp->conversion == 'n')
251 {
252 switch (a.arg[dp->arg_index].type)
253 {
254 case TYPE_COUNT_SCHAR_POINTER:
255 *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
256 break;
257 case TYPE_COUNT_SHORT_POINTER:
258 *a.arg[dp->arg_index].a.a_count_short_pointer = length;
259 break;
260 case TYPE_COUNT_INT_POINTER:
261 *a.arg[dp->arg_index].a.a_count_int_pointer = length;
262 break;
263 case TYPE_COUNT_LONGINT_POINTER:
264 *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
265 break;
266 #ifdef HAVE_LONG_LONG
267 case TYPE_COUNT_LONGLONGINT_POINTER:
268 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
269 break;
270 #endif
271 default:
272 abort ();
273 }
274 }
275 else
276 {
277 arg_type type = a.arg[dp->arg_index].type;
278 CHAR_T *p;
279 unsigned int prefix_count;
280 int prefixes[2];
281 #if !USE_SNPRINTF
282 size_t tmp_length;
283 CHAR_T tmpbuf[700];
284 CHAR_T *tmp;
285
286 /* Allocate a temporary buffer of sufficient size for calling
287 sprintf. */
288 {
289 size_t width;
290 size_t precision;
291
292 width = 0;
293 if (dp->width_start != dp->width_end)
294 {
295 if (dp->width_arg_index != ARG_NONE)
296 {
297 int arg;
298
299 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
300 abort ();
301 arg = a.arg[dp->width_arg_index].a.a_int;
302 width = (arg < 0 ? (unsigned int) (-arg) : arg);
303 }
304 else
305 {
306 const CHAR_T *digitp = dp->width_start;
307
308 do
309 width = xsum (xtimes (width, 10), *digitp++ - '0');
310 while (digitp != dp->width_end);
311 }
312 }
313
314 precision = 6;
315 if (dp->precision_start != dp->precision_end)
316 {
317 if (dp->precision_arg_index != ARG_NONE)
318 {
319 int arg;
320
321 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
322 abort ();
323 arg = a.arg[dp->precision_arg_index].a.a_int;
324 precision = (arg < 0 ? 0 : arg);
325 }
326 else
327 {
328 const CHAR_T *digitp = dp->precision_start + 1;
329
330 precision = 0;
331 while (digitp != dp->precision_end)
332 precision = xsum (xtimes (precision, 10), *digitp++ - '0');
333 }
334 }
335
336 switch (dp->conversion)
337 {
338
339 case 'd': case 'i': case 'u':
340 # ifdef HAVE_LONG_LONG
341 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
342 tmp_length =
343 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
344 * 0.30103 /* binary -> decimal */
345 * 2 /* estimate for FLAG_GROUP */
346 )
347 + 1 /* turn floor into ceil */
348 + 1; /* account for leading sign */
349 else
350 # endif
351 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
352 tmp_length =
353 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
354 * 0.30103 /* binary -> decimal */
355 * 2 /* estimate for FLAG_GROUP */
356 )
357 + 1 /* turn floor into ceil */
358 + 1; /* account for leading sign */
359 else
360 tmp_length =
361 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
362 * 0.30103 /* binary -> decimal */
363 * 2 /* estimate for FLAG_GROUP */
364 )
365 + 1 /* turn floor into ceil */
366 + 1; /* account for leading sign */
367 break;
368
369 case 'o':
370 # ifdef HAVE_LONG_LONG
371 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
372 tmp_length =
373 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
374 * 0.333334 /* binary -> octal */
375 )
376 + 1 /* turn floor into ceil */
377 + 1; /* account for leading sign */
378 else
379 # endif
380 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
381 tmp_length =
382 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
383 * 0.333334 /* binary -> octal */
384 )
385 + 1 /* turn floor into ceil */
386 + 1; /* account for leading sign */
387 else
388 tmp_length =
389 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
390 * 0.333334 /* binary -> octal */
391 )
392 + 1 /* turn floor into ceil */
393 + 1; /* account for leading sign */
394 break;
395
396 case 'x': case 'X':
397 # ifdef HAVE_LONG_LONG
398 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
399 tmp_length =
400 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
401 * 0.25 /* binary -> hexadecimal */
402 )
403 + 1 /* turn floor into ceil */
404 + 2; /* account for leading sign or alternate form */
405 else
406 # endif
407 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
408 tmp_length =
409 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
410 * 0.25 /* binary -> hexadecimal */
411 )
412 + 1 /* turn floor into ceil */
413 + 2; /* account for leading sign or alternate form */
414 else
415 tmp_length =
416 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
417 * 0.25 /* binary -> hexadecimal */
418 )
419 + 1 /* turn floor into ceil */
420 + 2; /* account for leading sign or alternate form */
421 break;
422
423 case 'f': case 'F':
424 # ifdef HAVE_LONG_DOUBLE
425 if (type == TYPE_LONGDOUBLE)
426 tmp_length =
427 (unsigned int) (LDBL_MAX_EXP
428 * 0.30103 /* binary -> decimal */
429 * 2 /* estimate for FLAG_GROUP */
430 )
431 + 1 /* turn floor into ceil */
432 + 10; /* sign, decimal point etc. */
433 else
434 # endif
435 tmp_length =
436 (unsigned int) (DBL_MAX_EXP
437 * 0.30103 /* binary -> decimal */
438 * 2 /* estimate for FLAG_GROUP */
439 )
440 + 1 /* turn floor into ceil */
441 + 10; /* sign, decimal point etc. */
442 tmp_length = xsum (tmp_length, precision);
443 break;
444
445 case 'e': case 'E': case 'g': case 'G':
446 case 'a': case 'A':
447 tmp_length =
448 12; /* sign, decimal point, exponent etc. */
449 tmp_length = xsum (tmp_length, precision);
450 break;
451
452 case 'c':
453 # if defined HAVE_WINT_T && !WIDE_CHAR_VERSION
454 if (type == TYPE_WIDE_CHAR)
455 tmp_length = MB_CUR_MAX;
456 else
457 # endif
458 tmp_length = 1;
459 break;
460
461 case 's':
462 # ifdef HAVE_WCHAR_T
463 if (type == TYPE_WIDE_STRING)
464 {
465 tmp_length =
466 local_wcslen (a.arg[dp->arg_index].a.a_wide_string);
467
468 # if !WIDE_CHAR_VERSION
469 tmp_length = xtimes (tmp_length, MB_CUR_MAX);
470 # endif
471 }
472 else
473 # endif
474 tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
475 break;
476
477 case 'p':
478 tmp_length =
479 (unsigned int) (sizeof (void *) * CHAR_BIT
480 * 0.25 /* binary -> hexadecimal */
481 )
482 + 1 /* turn floor into ceil */
483 + 2; /* account for leading 0x */
484 break;
485
486 default:
487 abort ();
488 }
489
490 if (tmp_length < width)
491 tmp_length = width;
492
493 tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
494 }
495
496 if (tmp_length <= sizeof (tmpbuf) / sizeof (CHAR_T))
497 tmp = tmpbuf;
498 else
499 {
500 size_t tmp_memsize = xtimes (tmp_length, sizeof (CHAR_T));
501
502 if (size_overflow_p (tmp_memsize))
503 /* Overflow, would lead to out of memory. */
504 goto out_of_memory;
505 tmp = (CHAR_T *) malloc (tmp_memsize);
506 if (tmp == NULL)
507 /* Out of memory. */
508 goto out_of_memory;
509 }
510 #endif
511
512 /* Construct the format string for calling snprintf or
513 sprintf. */
514 p = buf;
515 *p++ = '%';
516 if (dp->flags & FLAG_GROUP)
517 *p++ = '\'';
518 if (dp->flags & FLAG_LEFT)
519 *p++ = '-';
520 if (dp->flags & FLAG_SHOWSIGN)
521 *p++ = '+';
522 if (dp->flags & FLAG_SPACE)
523 *p++ = ' ';
524 if (dp->flags & FLAG_ALT)
525 *p++ = '#';
526 if (dp->flags & FLAG_ZERO)
527 *p++ = '0';
528 if (dp->width_start != dp->width_end)
529 {
530 size_t n = dp->width_end - dp->width_start;
531 memcpy (p, dp->width_start, n * sizeof (CHAR_T));
532 p += n;
533 }
534 if (dp->precision_start != dp->precision_end)
535 {
536 size_t n = dp->precision_end - dp->precision_start;
537 memcpy (p, dp->precision_start, n * sizeof (CHAR_T));
538 p += n;
539 }
540
541 switch (type)
542 {
543 #ifdef HAVE_LONG_LONG
544 case TYPE_LONGLONGINT:
545 case TYPE_ULONGLONGINT:
546 *p++ = 'l';
547 /*FALLTHROUGH*/
548 #endif
549 case TYPE_LONGINT:
550 case TYPE_ULONGINT:
551 #ifdef HAVE_WINT_T
552 case TYPE_WIDE_CHAR:
553 #endif
554 #ifdef HAVE_WCHAR_T
555 case TYPE_WIDE_STRING:
556 #endif
557 *p++ = 'l';
558 break;
559 #ifdef HAVE_LONG_DOUBLE
560 case TYPE_LONGDOUBLE:
561 *p++ = 'L';
562 break;
563 #endif
564 default:
565 break;
566 }
567 *p = dp->conversion;
568 p[1] = '\0';
569
570 /* Construct the arguments for calling snprintf or sprintf. */
571 prefix_count = 0;
572 if (dp->width_arg_index != ARG_NONE)
573 {
574 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
575 abort ();
576 prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
577 }
578 if (dp->precision_arg_index != ARG_NONE)
579 {
580 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
581 abort ();
582 prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
583 }
584
585 #if USE_SNPRINTF
586 /* Prepare checking whether snprintf returns the count
587 via %n. */
588 ENSURE_ALLOCATION (xsum (length, 1));
589 result[length] = '\0';
590 #endif
591
592 for (;;)
593 {
594 size_t maxlen;
595 int count;
596
597 maxlen = allocated - length;
598 count = -1;
599
600 #if USE_SNPRINTF
601 # define SNPRINTF_BUF(arg) \
602 switch (prefix_count) \
603 { \
604 case 0: \
605 count = SNPRINTF (result + length, maxlen, buf, \
606 arg); \
607 break; \
608 case 1: \
609 count = SNPRINTF (result + length, maxlen, buf, \
610 prefixes[0], arg); \
611 break; \
612 case 2: \
613 count = SNPRINTF (result + length, maxlen, buf, \
614 prefixes[0], prefixes[1], arg); \
615 break; \
616 default: \
617 abort (); \
618 }
619 #else
620 # define SNPRINTF_BUF(arg) \
621 switch (prefix_count) \
622 { \
623 case 0: \
624 count = sprintf (tmp, buf, arg); \
625 break; \
626 case 1: \
627 count = sprintf (tmp, buf, prefixes[0], arg); \
628 break; \
629 case 2: \
630 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
631 arg); \
632 break; \
633 default: \
634 abort (); \
635 }
636 #endif
637
638 switch (type)
639 {
640 case TYPE_SCHAR:
641 {
642 int arg = a.arg[dp->arg_index].a.a_schar;
643 SNPRINTF_BUF (arg);
644 }
645 break;
646 case TYPE_UCHAR:
647 {
648 unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
649 SNPRINTF_BUF (arg);
650 }
651 break;
652 case TYPE_SHORT:
653 {
654 int arg = a.arg[dp->arg_index].a.a_short;
655 SNPRINTF_BUF (arg);
656 }
657 break;
658 case TYPE_USHORT:
659 {
660 unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
661 SNPRINTF_BUF (arg);
662 }
663 break;
664 case TYPE_INT:
665 {
666 int arg = a.arg[dp->arg_index].a.a_int;
667 SNPRINTF_BUF (arg);
668 }
669 break;
670 case TYPE_UINT:
671 {
672 unsigned int arg = a.arg[dp->arg_index].a.a_uint;
673 SNPRINTF_BUF (arg);
674 }
675 break;
676 case TYPE_LONGINT:
677 {
678 long int arg = a.arg[dp->arg_index].a.a_longint;
679 SNPRINTF_BUF (arg);
680 }
681 break;
682 case TYPE_ULONGINT:
683 {
684 unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
685 SNPRINTF_BUF (arg);
686 }
687 break;
688 #ifdef HAVE_LONG_LONG
689 case TYPE_LONGLONGINT:
690 {
691 long long int arg = a.arg[dp->arg_index].a.a_longlongint;
692 SNPRINTF_BUF (arg);
693 }
694 break;
695 case TYPE_ULONGLONGINT:
696 {
697 unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
698 SNPRINTF_BUF (arg);
699 }
700 break;
701 #endif
702 case TYPE_DOUBLE:
703 {
704 double arg = a.arg[dp->arg_index].a.a_double;
705 SNPRINTF_BUF (arg);
706 }
707 break;
708 #ifdef HAVE_LONG_DOUBLE
709 case TYPE_LONGDOUBLE:
710 {
711 long double arg = a.arg[dp->arg_index].a.a_longdouble;
712 SNPRINTF_BUF (arg);
713 }
714 break;
715 #endif
716 case TYPE_CHAR:
717 {
718 int arg = a.arg[dp->arg_index].a.a_char;
719 SNPRINTF_BUF (arg);
720 }
721 break;
722 #ifdef HAVE_WINT_T
723 case TYPE_WIDE_CHAR:
724 {
725 wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
726 SNPRINTF_BUF (arg);
727 }
728 break;
729 #endif
730 case TYPE_STRING:
731 {
732 const char *arg = a.arg[dp->arg_index].a.a_string;
733 SNPRINTF_BUF (arg);
734 }
735 break;
736 #ifdef HAVE_WCHAR_T
737 case TYPE_WIDE_STRING:
738 {
739 const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
740 SNPRINTF_BUF (arg);
741 }
742 break;
743 #endif
744 case TYPE_POINTER:
745 {
746 void *arg = a.arg[dp->arg_index].a.a_pointer;
747 SNPRINTF_BUF (arg);
748 }
749 break;
750 default:
751 abort ();
752 }
753
754 #if USE_SNPRINTF
755 /* Portability: Not all implementations of snprintf()
756 are ISO C 99 compliant. Determine the number of
757 bytes that snprintf() has produced or would have
758 produced. */
759 if (count >= 0)
760 {
761 /* Verify that snprintf() has NUL-terminated its
762 result. */
763 if (count < maxlen && result[length + count] != '\0')
764 abort ();
765 }
766 #endif
767
768 /* Attempt to handle failure. */
769 if (count < 0)
770 {
771 if (!(result == resultbuf || result == NULL))
772 free (result);
773 if (buf_malloced != NULL)
774 free (buf_malloced);
775 CLEANUP ();
776 errno = EINVAL;
777 return NULL;
778 }
779
780 #if !USE_SNPRINTF
781 if (count >= tmp_length)
782 /* tmp_length was incorrectly calculated - fix the
783 code above! */
784 abort ();
785 #endif
786
787 /* Make room for the result. */
788 if (count >= maxlen)
789 {
790 /* Need at least count bytes. But allocate
791 proportionally, to avoid looping eternally if
792 snprintf() reports a too small count. */
793 size_t n =
794 xmax (xsum (length, count), xtimes (allocated, 2));
795
796 ENSURE_ALLOCATION (n);
797 #if USE_SNPRINTF
798 continue;
799 #endif
800 }
801
802 #if USE_SNPRINTF
803 /* The snprintf() result did fit. */
804 #else
805 /* Append the sprintf() result. */
806 memcpy (result + length, tmp, count * sizeof (CHAR_T));
807 if (tmp != tmpbuf)
808 free (tmp);
809 #endif
810
811 length += count;
812 break;
813 }
814 }
815 }
816 }
817
818 /* Add the final NUL. */
819 ENSURE_ALLOCATION (xsum (length, 1));
820 result[length] = '\0';
821
822 if (result != resultbuf && length + 1 < allocated)
823 {
824 /* Shrink the allocated memory if possible. */
825 CHAR_T *memory;
826
827 memory = (CHAR_T *) realloc (result, (length + 1) * sizeof (CHAR_T));
828 if (memory != NULL)
829 result = memory;
830 }
831
832 if (buf_malloced != NULL)
833 free (buf_malloced);
834 CLEANUP ();
835 *lengthp = length;
836 if (length > INT_MAX)
837 goto length_overflow;
838 return result;
839
840 length_overflow:
841 /* We could produce such a big string, but its length doesn't fit into
842 an 'int'. POSIX says that snprintf() fails with errno = EOVERFLOW in
843 this case. */
844 if (result != resultbuf)
845 free (result);
846 errno = EOVERFLOW;
847 return NULL;
848
849 out_of_memory:
850 if (!(result == resultbuf || result == NULL))
851 free (result);
852 if (buf_malloced != NULL)
853 free (buf_malloced);
854 out_of_memory_1:
855 CLEANUP ();
856 errno = ENOMEM;
857 return NULL;
858 }
859 }
860
861 #undef SNPRINTF
862 #undef USE_SNPRINTF
863 #undef PRINTF_PARSE
864 #undef DIRECTIVES
865 #undef DIRECTIVE
866 #undef CHAR_T
867 #undef VASNPRINTF
868