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