1 /* vsprintf with automatic memory allocation.
2 Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published
6 by the Free Software Foundation; either version 2, or (at your option)
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 GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 /* Tell glibc's <stdio.h> to provide a prototype for snprintf().
21 This must come before <config.h> because <config.h> may include
22 <features.h>, and once <features.h> has been included, it's too late. */
24 # define _GNU_SOURCE 1
32 #include "gst-printf.h"
35 #include "vasnprintf.h"
37 #include <stdio.h> /* snprintf(), sprintf() */
38 #include <stdlib.h> /* abort(), malloc(), realloc(), free() */
39 #include <string.h> /* memcpy(), strlen() */
40 #include <errno.h> /* errno */
41 #include <limits.h> /* CHAR_BIT */
42 #include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
43 #include "printf-parse.h"
44 #include "printf-extension.h"
48 # define local_wcslen wcslen
50 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
51 a dependency towards this library, here is a local substitute.
52 Define this substitute only once, even if this file is included
53 twice in the same compilation unit. */
54 # ifndef local_wcslen_defined
55 # define local_wcslen_defined 1
57 local_wcslen (const wchar_t * s)
61 for (ptr = s; *ptr != (wchar_t) 0; ptr++);
68 /* For those losing systems which don't have 'alloca' we have to add
69 some additional code emulating it. */
70 #ifdef GLIB_HAVE_ALLOCA_H
71 # define freea(p) /* nothing */
73 # define alloca(n) malloc (n)
74 # define freea(p) free (p)
77 #ifndef HAVE_LONG_LONG_FORMAT
79 print_long_long (char *buf,
83 unsigned long flags, char conversion, unsigned long long number)
90 static const char *upper = "0123456789ABCDEFX";
91 static const char *lower = "0123456789abcdefx";
98 if (p - buf == len - 1) \
108 switch (conversion) {
127 negative = (long long) number < 0;
129 number = -((long long) number);
134 pointer = bufferend = &buffer[sizeof (buffer) - 1];
136 for (i = 1; i < (int) sizeof (buffer); i++) {
137 *pointer-- = digits[number % base];
144 width -= (bufferend - pointer) - 1;
146 /* Adjust precision */
147 if (precision != -1) {
148 precision -= (bufferend - pointer) - 1;
154 /* Adjust width further */
155 if (negative || (flags & FLAG_SHOWSIGN) || (flags & FLAG_SPACE))
157 if (flags & FLAG_ALT) {
170 /* Output prefixes spaces if needed */
171 if (!((flags & FLAG_LEFT) || ((flags & FLAG_ZERO) && (precision == -1)))) {
172 count = (precision == -1) ? 0 : precision;
173 while (width-- > count)
177 /* width has been adjusted for signs and alternatives */
180 } else if (flags & FLAG_SHOWSIGN) {
182 } else if (flags & FLAG_SPACE) {
186 if (flags & FLAG_ALT) {
200 /* Output prefixed zero padding if needed */
201 if (flags & FLAG_ZERO) {
204 while (precision-- > 0) {
210 /* Output the number itself */
211 while (*(++pointer)) {
215 /* Output trailing spaces if needed */
216 if (flags & FLAG_LEFT) {
228 printf_postprocess_args (char_directives * directives, arguments * arguments)
232 for (i = 0; i < directives->count; ++i) {
236 dp = &directives->dir[i];
237 a = &arguments->arg[dp->arg_index];
239 if (a->type == TYPE_POINTER_EXT) {
243 fmt[1] = POINTER_EXT_SIGNIFIER_CHAR;
244 fmt[2] = dp->ptr_ext_char;
248 __gst_printf_pointer_extension_serialize (fmt, a->a.a_pointer);
254 vasnprintf (char *resultbuf, size_t * lengthp, const char *format, va_list args)
259 if (printf_parse (format, &d, &a) < 0) {
266 while (a.count--) { \
267 if (a.arg[a.count].ext_string) \
268 free (a.arg[a.count].ext_string); \
273 if (printf_fetchargs (args, &a) < 0) {
279 /* collect TYPE_POINTER_EXT argument strings */
280 printf_postprocess_args (&d, &a);
284 (char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);
288 /* Output string accumulator. */
293 if (resultbuf != NULL) {
295 allocated = *lengthp;
302 result is either == resultbuf or == NULL or malloc-allocated.
303 If length > 0, then result != NULL. */
305 #define ENSURE_ALLOCATION(needed) \
306 if ((needed) > allocated) \
310 allocated = (allocated > 0 ? 2 * allocated : 12); \
311 if ((needed) > allocated) \
312 allocated = (needed); \
313 if (result == resultbuf || result == NULL) \
314 memory = (char *) malloc (allocated); \
316 memory = (char *) realloc (result, allocated); \
318 if (memory == NULL) \
320 if (!(result == resultbuf || result == NULL)) \
327 if (result == resultbuf && length > 0) \
328 memcpy (memory, result, length); \
332 for (cp = format, i = 0, dp = &d.dir[0];; cp = dp->dir_end, i++, dp++) {
333 if (cp != dp->dir_start) {
334 size_t n = dp->dir_start - cp;
336 ENSURE_ALLOCATION (length + n);
337 memcpy (result + length, cp, n);
343 /* Execute a single directive. */
344 if (dp->conversion == '%') {
345 if (!(dp->arg_index < 0))
347 ENSURE_ALLOCATION (length + 1);
348 result[length] = '%';
351 if (!(dp->arg_index >= 0))
354 if (dp->conversion == 'n') {
355 switch (a.arg[dp->arg_index].type) {
356 case TYPE_COUNT_SCHAR_POINTER:
357 *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
359 case TYPE_COUNT_SHORT_POINTER:
360 *a.arg[dp->arg_index].a.a_count_short_pointer = length;
362 case TYPE_COUNT_INT_POINTER:
363 *a.arg[dp->arg_index].a.a_count_int_pointer = length;
365 case TYPE_COUNT_LONGINT_POINTER:
366 *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
368 #ifdef HAVE_LONG_LONG
369 case TYPE_COUNT_LONGLONGINT_POINTER:
370 *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
377 arg_type type = a.arg[dp->arg_index].type;
379 unsigned int prefix_count;
382 unsigned int tmp_length;
386 /* Allocate a temporary buffer of sufficient size for calling
390 unsigned int precision;
393 if (dp->width_start != dp->width_end) {
394 if (dp->width_arg_index >= 0) {
397 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
399 arg = a.arg[dp->width_arg_index].a.a_int;
400 width = (arg < 0 ? -arg : arg);
402 const char *digitp = dp->width_start;
405 width = width * 10 + (*digitp++ - '0');
406 while (digitp != dp->width_end);
411 if (dp->precision_start != dp->precision_end) {
412 if (dp->precision_arg_index >= 0) {
415 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
417 arg = a.arg[dp->precision_arg_index].a.a_int;
418 precision = (arg < 0 ? 0 : arg);
420 const char *digitp = dp->precision_start + 1;
423 while (digitp != dp->precision_end)
424 precision = precision * 10 + (*digitp++ - '0');
428 switch (dp->conversion) {
432 # ifdef HAVE_LONG_LONG
433 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
434 tmp_length = (unsigned int) (sizeof (unsigned long long) * CHAR_BIT * 0.30103 /* binary -> decimal */
435 * 2 /* estimate for FLAG_GROUP */
437 + 1 /* turn floor into ceil */
438 + 1; /* account for leading sign */
441 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
442 tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT * 0.30103 /* binary -> decimal */
443 * 2 /* estimate for FLAG_GROUP */
445 + 1 /* turn floor into ceil */
446 + 1; /* account for leading sign */
448 tmp_length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT * 0.30103 /* binary -> decimal */
449 * 2 /* estimate for FLAG_GROUP */
451 + 1 /* turn floor into ceil */
452 + 1; /* account for leading sign */
456 # ifdef HAVE_LONG_LONG
457 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
458 tmp_length = (unsigned int) (sizeof (unsigned long long) * CHAR_BIT * 0.333334 /* binary -> octal */
460 + 1 /* turn floor into ceil */
461 + 1; /* account for leading sign */
464 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
465 tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT * 0.333334 /* binary -> octal */
467 + 1 /* turn floor into ceil */
468 + 1; /* account for leading sign */
470 tmp_length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT * 0.333334 /* binary -> octal */
472 + 1 /* turn floor into ceil */
473 + 1; /* account for leading sign */
478 # ifdef HAVE_LONG_LONG
479 if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
480 tmp_length = (unsigned int) (sizeof (unsigned long long) * CHAR_BIT * 0.25 /* binary -> hexadecimal */
482 + 1 /* turn floor into ceil */
483 + 2; /* account for leading sign or alternate form */
486 # ifdef HAVE_INT64_AND_I64
487 if (type == TYPE_INT64 || type == TYPE_UINT64)
488 tmp_length = (unsigned int) (sizeof (unsigned __int64) * CHAR_BIT * 0.25 /* binary -> hexadecimal */
490 + 1 /* turn floor into ceil */
491 + 2; /* account for leading sign or alternate form */
494 if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
495 tmp_length = (unsigned int) (sizeof (unsigned long) * CHAR_BIT * 0.25 /* binary -> hexadecimal */
497 + 1 /* turn floor into ceil */
498 + 2; /* account for leading sign or alternate form */
500 tmp_length = (unsigned int) (sizeof (unsigned int) * CHAR_BIT * 0.25 /* binary -> hexadecimal */
502 + 1 /* turn floor into ceil */
503 + 2; /* account for leading sign or alternate form */
508 # ifdef HAVE_LONG_DOUBLE
509 if (type == TYPE_LONGDOUBLE)
510 tmp_length = (unsigned int) (LDBL_MAX_EXP * 0.30103 /* binary -> decimal */
511 * 2 /* estimate for FLAG_GROUP */
513 + 1 /* turn floor into ceil */
514 + precision + 10; /* sign, decimal point etc. */
517 tmp_length = (unsigned int) (DBL_MAX_EXP * 0.30103 /* binary -> decimal */
518 * 2 /* estimate for FLAG_GROUP */
520 + 1 /* turn floor into ceil */
521 + precision + 10; /* sign, decimal point etc. */
530 tmp_length = precision + 12; /* sign, decimal point, exponent etc. */
535 if (type == TYPE_WIDE_CHAR)
536 tmp_length = MB_CUR_MAX;
544 if (type == TYPE_WIDE_STRING)
545 tmp_length = (a.arg[dp->arg_index].a.a_wide_string == NULL ? 6 /* wcslen(L"(null)") */
546 : local_wcslen (a.arg[dp->arg_index].a.a_wide_string))
550 tmp_length = a.arg[dp->arg_index].a.a_string == NULL ? 6 /* strlen("(null)") */
551 : strlen (a.arg[dp->arg_index].a.a_string);
555 tmp_length = (unsigned int) (sizeof (void *) * CHAR_BIT * 0.25 /* binary -> hexadecimal */
557 + 1 /* turn floor into ceil */
558 + 2; /* account for leading 0x */
560 /* make sure we always have enough space for a plain %p, so + */
561 if (dp->flags & FLAG_PTR_EXT && a.arg[dp->arg_index].ext_string)
562 tmp_length += strlen (a.arg[dp->arg_index].ext_string);
569 if (tmp_length < width)
572 tmp_length++; /* account for trailing NUL */
575 if (tmp_length <= sizeof (tmpbuf))
578 tmp = (char *) malloc (tmp_length);
581 if (!(result == resultbuf || result == NULL))
591 /* Construct the format string for calling snprintf or
595 if (dp->flags & FLAG_GROUP)
597 if (dp->flags & FLAG_LEFT)
599 if (dp->flags & FLAG_SHOWSIGN)
601 if (dp->flags & FLAG_SPACE)
603 if (dp->flags & FLAG_ALT)
605 if (dp->flags & FLAG_ZERO)
607 if (dp->width_start != dp->width_end) {
608 size_t n = dp->width_end - dp->width_start;
609 memcpy (p, dp->width_start, n);
612 if (dp->precision_start != dp->precision_end) {
613 size_t n = dp->precision_end - dp->precision_start;
614 memcpy (p, dp->precision_start, n);
619 #ifdef HAVE_INT64_AND_I64
627 #ifdef HAVE_LONG_LONG
628 case TYPE_LONGLONGINT:
629 case TYPE_ULONGLONGINT:
630 #ifdef HAVE_INT64_AND_I64 /* The system (sn)printf uses %I64. Also assume
631 * that long long == __int64.
648 case TYPE_WIDE_STRING:
652 #ifdef HAVE_LONG_DOUBLE
653 case TYPE_LONGDOUBLE:
669 /* Construct the arguments for calling snprintf or sprintf. */
671 if (dp->width_arg_index >= 0) {
672 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
674 prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
676 if (dp->precision_arg_index >= 0) {
677 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
679 prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
682 /* Prepare checking whether snprintf returns the count
684 ENSURE_ALLOCATION (length + 1);
685 result[length] = '\0';
695 maxlen = allocated - length;
701 #define SNPRINTF_BUF(arg) \
702 switch (prefix_count) \
705 retcount = snprintf (result + length, maxlen, buf, \
709 retcount = snprintf (result + length, maxlen, buf, \
710 prefixes[0], arg, &count); \
713 retcount = snprintf (result + length, maxlen, buf, \
714 prefixes[0], prefixes[1], arg, \
721 #define SNPRINTF_BUF(arg) \
722 switch (prefix_count) \
725 count = sprintf (tmp, buf, arg); \
728 count = sprintf (tmp, buf, prefixes[0], arg); \
731 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
742 int arg = a.arg[dp->arg_index].a.a_schar;
748 unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
754 int arg = a.arg[dp->arg_index].a.a_short;
760 unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
766 int arg = a.arg[dp->arg_index].a.a_int;
772 unsigned int arg = a.arg[dp->arg_index].a.a_uint;
778 long int arg = a.arg[dp->arg_index].a.a_longint;
784 unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
788 #ifdef HAVE_INT64_AND_I64
791 __int64 arg = a.arg[dp->arg_index].a.a_int64;
797 unsigned __int64 arg = a.arg[dp->arg_index].a.a_uint64;
802 #ifdef HAVE_LONG_LONG
803 #ifndef HAVE_LONG_LONG_FORMAT
804 case TYPE_LONGLONGINT:
805 case TYPE_ULONGLONGINT:
807 unsigned long long int arg =
808 a.arg[dp->arg_index].a.a_ulonglongint;
813 if (dp->width_start != dp->width_end) {
814 if (dp->width_arg_index >= 0) {
817 if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
819 arg = a.arg[dp->width_arg_index].a.a_int;
820 width = (arg < 0 ? -arg : arg);
822 const char *digitp = dp->width_start;
825 width = width * 10 + (*digitp++ - '0');
826 while (digitp != dp->width_end);
831 if (dp->precision_start != dp->precision_end) {
832 if (dp->precision_arg_index >= 0) {
835 if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
837 arg = a.arg[dp->precision_arg_index].a.a_int;
838 precision = (arg < 0 ? 0 : arg);
840 const char *digitp = dp->precision_start + 1;
844 precision = precision * 10 + (*digitp++ - '0');
845 while (digitp != dp->precision_end);
849 count = print_long_long (result + length, maxlen,
850 width, precision, dp->flags, dp->conversion, arg);
852 count = print_long_long (tmp, tmp_length,
853 width, precision, dp->flags, dp->conversion, arg);
858 case TYPE_LONGLONGINT:
860 long long int arg = a.arg[dp->arg_index].a.a_longlongint;
864 case TYPE_ULONGLONGINT:
866 unsigned long long int arg =
867 a.arg[dp->arg_index].a.a_ulonglongint;
875 double arg = a.arg[dp->arg_index].a.a_double;
879 #ifdef HAVE_LONG_DOUBLE
880 case TYPE_LONGDOUBLE:
882 long double arg = a.arg[dp->arg_index].a.a_longdouble;
889 int arg = a.arg[dp->arg_index].a.a_char;
896 wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
903 const char *arg = a.arg[dp->arg_index].a.a_string == NULL
904 ? "(null)" : a.arg[dp->arg_index].a.a_string;
909 case TYPE_WIDE_STRING:
912 a.arg[dp->arg_index].a.a_wide_string ==
913 NULL ? L"(null)" : a.arg[dp->arg_index].a.a_wide_string;
920 void *arg = a.arg[dp->arg_index].a.a_pointer;
924 case TYPE_POINTER_EXT:
926 void *arg = a.arg[dp->arg_index].a.a_pointer;
928 if (a.arg[dp->arg_index].ext_string != NULL) {
929 arg = a.arg[dp->arg_index].ext_string;
941 /* Portability: Not all implementations of snprintf()
942 are ISO C 99 compliant. Determine the number of
943 bytes that snprintf() has produced or would have
946 /* Verify that snprintf() has NUL-terminated its
948 if (count < maxlen && result[length + count] != '\0')
950 /* Portability hack. */
951 if (retcount > count)
954 /* snprintf() doesn't understand the '%n'
957 /* Don't use the '%n' directive; instead, look
958 at the snprintf() return value. */
966 /* Attempt to handle failure. */
968 if (!(result == resultbuf || result == NULL))
976 if (count >= tmp_length)
977 /* tmp_length was incorrectly calculated - fix the
982 /* Make room for the result. */
983 if (count >= maxlen) {
984 /* Need at least count bytes. But allocate
985 proportionally, to avoid looping eternally if
986 snprintf() reports a too small count. */
987 size_t n = length + count;
989 if (n < 2 * allocated)
992 ENSURE_ALLOCATION (n);
998 /* The snprintf() result did fit. */
1000 /* Append the sprintf() result. */
1001 memcpy (result + length, tmp, count);
1013 /* Add the final NUL. */
1014 ENSURE_ALLOCATION (length + 1);
1015 result[length] = '\0';
1017 if (result != resultbuf && length + 1 < allocated) {
1018 /* Shrink the allocated memory if possible. */
1021 memory = (char *) realloc (result, length + 1);