1 /* vsprintf with automatic memory allocation.
2 Copyright (C) 1999, 2002-2007 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 General Public License as published by
6 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
12 GNU General Public License for more details.
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. */
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. */
22 # define _GNU_SOURCE 1
32 # include "vasnwprintf.h"
34 # include "vasnprintf.h"
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 */
45 # include <langinfo.h>
48 # include "wprintf-parse.h"
50 # include "printf-parse.h"
53 /* Checked size_t computations. */
56 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
59 # include "printf-frexp.h"
60 # include "isnanl-nolibm.h"
61 # include "printf-frexpl.h"
65 /* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
67 # define EOVERFLOW E2BIG
72 # define local_wcslen wcslen
74 /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
75 a dependency towards this library, here is a local substitute.
76 Define this substitute only once, even if this file is included
77 twice in the same compilation unit. */
78 # ifndef local_wcslen_defined
79 # define local_wcslen_defined 1
81 local_wcslen (const wchar_t *s
)
85 for (ptr
= s
; *ptr
!= (wchar_t) 0; ptr
++)
94 # define VASNPRINTF vasnwprintf
95 # define CHAR_T wchar_t
96 # define DIRECTIVE wchar_t_directive
97 # define DIRECTIVES wchar_t_directives
98 # define PRINTF_PARSE wprintf_parse
99 # define USE_SNPRINTF 1
100 # if HAVE_DECL__SNWPRINTF
101 /* On Windows, the function swprintf() has a different signature than
102 on Unix; we use the _snwprintf() function instead. */
103 # define SNPRINTF _snwprintf
106 # define SNPRINTF swprintf
109 # define VASNPRINTF vasnprintf
111 # define DIRECTIVE char_directive
112 # define DIRECTIVES char_directives
113 # define PRINTF_PARSE printf_parse
114 # define USE_SNPRINTF (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF)
115 # if HAVE_DECL__SNPRINTF
117 # define SNPRINTF _snprintf
120 # define SNPRINTF snprintf
121 /* Here we need to call the native snprintf, not rpl_snprintf. */
125 /* Here we need to call the native sprintf, not rpl_sprintf. */
128 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
129 /* Determine the decimal-point character according to the current locale. */
130 # ifndef decimal_point_char_defined
131 # define decimal_point_char_defined 1
133 decimal_point_char ()
136 /* Determine it in a multithread-safe way. We know nl_langinfo is
137 multithread-safe on glibc systems, but is not required to be multithread-
138 safe by POSIX. sprintf(), however, is multithread-safe. localeconv()
139 is rarely multithread-safe. */
140 # if HAVE_NL_LANGINFO && __GLIBC__
141 point
= nl_langinfo (RADIXCHAR
);
144 sprintf (pointbuf
, "%#.0f", 1.0);
145 point
= &pointbuf
[1];
147 point
= localeconv () -> decimal_point
;
149 /* The decimal point is always a single byte: either '.' or ','. */
150 return (point
[0] != '\0' ? point
[0] : '.');
156 VASNPRINTF (CHAR_T
*resultbuf
, size_t *lengthp
, const CHAR_T
*format
, va_list args
)
161 if (PRINTF_PARSE (format
, &d
, &a
) < 0)
172 if (printf_fetchargs (args
, &a
) < 0)
180 size_t buf_neededlength
;
182 CHAR_T
*buf_malloced
;
186 /* Output string accumulator. */
191 /* Allocate a small buffer that will hold a directive passed to
192 sprintf or snprintf. */
194 xsum4 (7, d
.max_width_length
, d
.max_precision_length
, 6);
196 if (buf_neededlength
< 4000 / sizeof (CHAR_T
))
198 buf
= (CHAR_T
*) alloca (buf_neededlength
* sizeof (CHAR_T
));
204 size_t buf_memsize
= xtimes (buf_neededlength
, sizeof (CHAR_T
));
205 if (size_overflow_p (buf_memsize
))
206 goto out_of_memory_1
;
207 buf
= (CHAR_T
*) malloc (buf_memsize
);
209 goto out_of_memory_1
;
213 if (resultbuf
!= NULL
)
216 allocated
= *lengthp
;
225 result is either == resultbuf or == NULL or malloc-allocated.
226 If length > 0, then result != NULL. */
228 /* Ensures that allocated >= needed. Aborts through a jump to
229 out_of_memory if needed is SIZE_MAX or otherwise too big. */
230 #define ENSURE_ALLOCATION(needed) \
231 if ((needed) > allocated) \
233 size_t memory_size; \
236 allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
237 if ((needed) > allocated) \
238 allocated = (needed); \
239 memory_size = xtimes (allocated, sizeof (CHAR_T)); \
240 if (size_overflow_p (memory_size)) \
241 goto out_of_memory; \
242 if (result == resultbuf || result == NULL) \
243 memory = (CHAR_T *) malloc (memory_size); \
245 memory = (CHAR_T *) realloc (result, memory_size); \
246 if (memory == NULL) \
247 goto out_of_memory; \
248 if (result == resultbuf && length > 0) \
249 memcpy (memory, result, length * sizeof (CHAR_T)); \
253 for (cp
= format
, i
= 0, dp
= &d
.dir
[0]; ; cp
= dp
->dir_end
, i
++, dp
++)
255 if (cp
!= dp
->dir_start
)
257 size_t n
= dp
->dir_start
- cp
;
258 size_t augmented_length
= xsum (length
, n
);
260 ENSURE_ALLOCATION (augmented_length
);
261 memcpy (result
+ length
, cp
, n
* sizeof (CHAR_T
));
262 length
= augmented_length
;
267 /* Execute a single directive. */
268 if (dp
->conversion
== '%')
270 size_t augmented_length
;
272 if (!(dp
->arg_index
== ARG_NONE
))
274 augmented_length
= xsum (length
, 1);
275 ENSURE_ALLOCATION (augmented_length
);
276 result
[length
] = '%';
277 length
= augmented_length
;
281 if (!(dp
->arg_index
!= ARG_NONE
))
284 if (dp
->conversion
== 'n')
286 switch (a
.arg
[dp
->arg_index
].type
)
288 case TYPE_COUNT_SCHAR_POINTER
:
289 *a
.arg
[dp
->arg_index
].a
.a_count_schar_pointer
= length
;
291 case TYPE_COUNT_SHORT_POINTER
:
292 *a
.arg
[dp
->arg_index
].a
.a_count_short_pointer
= length
;
294 case TYPE_COUNT_INT_POINTER
:
295 *a
.arg
[dp
->arg_index
].a
.a_count_int_pointer
= length
;
297 case TYPE_COUNT_LONGINT_POINTER
:
298 *a
.arg
[dp
->arg_index
].a
.a_count_longint_pointer
= length
;
300 #if HAVE_LONG_LONG_INT
301 case TYPE_COUNT_LONGLONGINT_POINTER
:
302 *a
.arg
[dp
->arg_index
].a
.a_count_longlongint_pointer
= length
;
309 #if NEED_PRINTF_DIRECTIVE_A && !defined IN_LIBINTL
310 else if (dp
->conversion
== 'a' || dp
->conversion
== 'A')
312 arg_type type
= a
.arg
[dp
->arg_index
].type
;
313 int flags
= dp
->flags
;
326 if (dp
->width_start
!= dp
->width_end
)
328 if (dp
->width_arg_index
!= ARG_NONE
)
332 if (!(a
.arg
[dp
->width_arg_index
].type
== TYPE_INT
))
334 arg
= a
.arg
[dp
->width_arg_index
].a
.a_int
;
337 /* "A negative field width is taken as a '-' flag
338 followed by a positive field width." */
340 width
= (unsigned int) (-arg
);
347 const CHAR_T
*digitp
= dp
->width_start
;
350 width
= xsum (xtimes (width
, 10), *digitp
++ - '0');
351 while (digitp
!= dp
->width_end
);
358 if (dp
->precision_start
!= dp
->precision_end
)
360 if (dp
->precision_arg_index
!= ARG_NONE
)
364 if (!(a
.arg
[dp
->precision_arg_index
].type
== TYPE_INT
))
366 arg
= a
.arg
[dp
->precision_arg_index
].a
.a_int
;
367 /* "A negative precision is taken as if the precision
377 const CHAR_T
*digitp
= dp
->precision_start
+ 1;
380 while (digitp
!= dp
->precision_end
)
381 precision
= xsum (xtimes (precision
, 10), *digitp
++ - '0');
386 /* Allocate a temporary buffer of sufficient size. */
387 if (type
== TYPE_LONGDOUBLE
)
389 (unsigned int) ((LDBL_DIG
+ 1)
390 * 0.831 /* decimal -> hexadecimal */
392 + 1; /* turn floor into ceil */
395 (unsigned int) ((DBL_DIG
+ 1)
396 * 0.831 /* decimal -> hexadecimal */
398 + 1; /* turn floor into ceil */
399 if (tmp_length
< precision
)
400 tmp_length
= precision
;
401 /* Account for sign, decimal point etc. */
402 tmp_length
= xsum (tmp_length
, 12);
404 if (tmp_length
< width
)
407 tmp_length
= xsum (tmp_length
, 1); /* account for trailing NUL */
409 if (tmp_length
<= sizeof (tmpbuf
) / sizeof (CHAR_T
))
413 size_t tmp_memsize
= xtimes (tmp_length
, sizeof (CHAR_T
));
415 if (size_overflow_p (tmp_memsize
))
416 /* Overflow, would lead to out of memory. */
418 tmp
= (CHAR_T
*) malloc (tmp_memsize
);
426 if (type
== TYPE_LONGDOUBLE
)
428 long double arg
= a
.arg
[dp
->arg_index
].a
.a_longdouble
;
432 if (dp
->conversion
== 'A')
434 *p
++ = 'N'; *p
++ = 'A'; *p
++ = 'N';
438 *p
++ = 'n'; *p
++ = 'a'; *p
++ = 'n';
444 DECL_LONG_DOUBLE_ROUNDING
446 BEGIN_LONG_DOUBLE_ROUNDING ();
448 if (signbit (arg
)) /* arg < 0.0L or negative zero */
456 else if (flags
& FLAG_SHOWSIGN
)
458 else if (flags
& FLAG_SPACE
)
461 if (arg
> 0.0L && arg
+ arg
== arg
)
463 if (dp
->conversion
== 'A')
465 *p
++ = 'I'; *p
++ = 'N'; *p
++ = 'F';
469 *p
++ = 'i'; *p
++ = 'n'; *p
++ = 'f';
475 long double mantissa
;
478 mantissa
= printf_frexpl (arg
, &exponent
);
486 && precision
< (unsigned int) ((LDBL_DIG
+ 1) * 0.831) + 1)
488 /* Round the mantissa. */
489 long double tail
= mantissa
;
492 for (q
= precision
; ; q
--)
494 int digit
= (int) tail
;
498 if (digit
& 1 ? tail
>= 0.5L : tail
> 0.5L)
507 for (q
= precision
; q
> 0; q
--)
513 *p
++ = dp
->conversion
- 'A' + 'X';
518 digit
= (int) mantissa
;
521 if ((flags
& FLAG_ALT
)
522 || mantissa
> 0.0L || precision
> 0)
524 *p
++ = decimal_point_char ();
525 /* This loop terminates because we assume
526 that FLT_RADIX is a power of 2. */
527 while (mantissa
> 0.0L)
530 digit
= (int) mantissa
;
535 : dp
->conversion
- 10);
539 while (precision
> 0)
546 *p
++ = dp
->conversion
- 'A' + 'P';
547 # if WIDE_CHAR_VERSION
549 static const wchar_t decimal_format
[] =
550 { '%', '+', 'd', '\0' };
551 SNPRINTF (p
, 6 + 1, decimal_format
, exponent
);
554 sprintf (p
, "%+d", exponent
);
560 END_LONG_DOUBLE_ROUNDING ();
565 double arg
= a
.arg
[dp
->arg_index
].a
.a_double
;
569 if (dp
->conversion
== 'A')
571 *p
++ = 'N'; *p
++ = 'A'; *p
++ = 'N';
575 *p
++ = 'n'; *p
++ = 'a'; *p
++ = 'n';
582 if (signbit (arg
)) /* arg < 0.0 or negative zero */
590 else if (flags
& FLAG_SHOWSIGN
)
592 else if (flags
& FLAG_SPACE
)
595 if (arg
> 0.0 && arg
+ arg
== arg
)
597 if (dp
->conversion
== 'A')
599 *p
++ = 'I'; *p
++ = 'N'; *p
++ = 'F';
603 *p
++ = 'i'; *p
++ = 'n'; *p
++ = 'f';
612 mantissa
= printf_frexp (arg
, &exponent
);
620 && precision
< (unsigned int) ((DBL_DIG
+ 1) * 0.831) + 1)
622 /* Round the mantissa. */
623 double tail
= mantissa
;
626 for (q
= precision
; ; q
--)
628 int digit
= (int) tail
;
632 if (digit
& 1 ? tail
>= 0.5 : tail
> 0.5)
641 for (q
= precision
; q
> 0; q
--)
647 *p
++ = dp
->conversion
- 'A' + 'X';
652 digit
= (int) mantissa
;
655 if ((flags
& FLAG_ALT
)
656 || mantissa
> 0.0 || precision
> 0)
658 *p
++ = decimal_point_char ();
659 /* This loop terminates because we assume
660 that FLT_RADIX is a power of 2. */
661 while (mantissa
> 0.0)
664 digit
= (int) mantissa
;
669 : dp
->conversion
- 10);
673 while (precision
> 0)
680 *p
++ = dp
->conversion
- 'A' + 'P';
681 # if WIDE_CHAR_VERSION
683 static const wchar_t decimal_format
[] =
684 { '%', '+', 'd', '\0' };
685 SNPRINTF (p
, 6 + 1, decimal_format
, exponent
);
688 sprintf (p
, "%+d", exponent
);
695 /* The generated string now extends from tmp to p, with the
696 zero padding insertion point being at pad_ptr. */
697 if (has_width
&& p
- tmp
< width
)
699 size_t pad
= width
- (p
- tmp
);
700 CHAR_T
*end
= p
+ pad
;
702 if (flags
& FLAG_LEFT
)
704 /* Pad with spaces on the right. */
705 for (; pad
> 0; pad
--)
708 else if ((flags
& FLAG_ZERO
) && pad_ptr
!= NULL
)
710 /* Pad with zeroes. */
715 for (; pad
> 0; pad
--)
720 /* Pad with spaces on the left. */
725 for (; pad
> 0; pad
--)
733 size_t count
= p
- tmp
;
735 if (count
>= tmp_length
)
736 /* tmp_length was incorrectly calculated - fix the
740 /* Make room for the result. */
741 if (count
>= allocated
- length
)
743 size_t n
= xsum (length
, count
);
745 ENSURE_ALLOCATION (n
);
748 /* Append the result. */
749 memcpy (result
+ length
, tmp
, count
* sizeof (CHAR_T
));
758 arg_type type
= a
.arg
[dp
->arg_index
].type
;
760 unsigned int prefix_count
;
767 /* Allocate a temporary buffer of sufficient size for calling
774 if (dp
->width_start
!= dp
->width_end
)
776 if (dp
->width_arg_index
!= ARG_NONE
)
780 if (!(a
.arg
[dp
->width_arg_index
].type
== TYPE_INT
))
782 arg
= a
.arg
[dp
->width_arg_index
].a
.a_int
;
783 width
= (arg
< 0 ? (unsigned int) (-arg
) : arg
);
787 const CHAR_T
*digitp
= dp
->width_start
;
790 width
= xsum (xtimes (width
, 10), *digitp
++ - '0');
791 while (digitp
!= dp
->width_end
);
796 if (dp
->precision_start
!= dp
->precision_end
)
798 if (dp
->precision_arg_index
!= ARG_NONE
)
802 if (!(a
.arg
[dp
->precision_arg_index
].type
== TYPE_INT
))
804 arg
= a
.arg
[dp
->precision_arg_index
].a
.a_int
;
805 precision
= (arg
< 0 ? 0 : arg
);
809 const CHAR_T
*digitp
= dp
->precision_start
+ 1;
812 while (digitp
!= dp
->precision_end
)
813 precision
= xsum (xtimes (precision
, 10), *digitp
++ - '0');
817 switch (dp
->conversion
)
820 case 'd': case 'i': case 'u':
821 # if HAVE_LONG_LONG_INT
822 if (type
== TYPE_LONGLONGINT
|| type
== TYPE_ULONGLONGINT
)
824 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
825 * 0.30103 /* binary -> decimal */
827 + 1; /* turn floor into ceil */
830 if (type
== TYPE_LONGINT
|| type
== TYPE_ULONGINT
)
832 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
833 * 0.30103 /* binary -> decimal */
835 + 1; /* turn floor into ceil */
838 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
839 * 0.30103 /* binary -> decimal */
841 + 1; /* turn floor into ceil */
842 if (tmp_length
< precision
)
843 tmp_length
= precision
;
844 /* Multiply by 2, as an estimate for FLAG_GROUP. */
845 tmp_length
= xsum (tmp_length
, tmp_length
);
846 /* Add 1, to account for a leading sign. */
847 tmp_length
= xsum (tmp_length
, 1);
851 # if HAVE_LONG_LONG_INT
852 if (type
== TYPE_LONGLONGINT
|| type
== TYPE_ULONGLONGINT
)
854 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
855 * 0.333334 /* binary -> octal */
857 + 1; /* turn floor into ceil */
860 if (type
== TYPE_LONGINT
|| type
== TYPE_ULONGINT
)
862 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
863 * 0.333334 /* binary -> octal */
865 + 1; /* turn floor into ceil */
868 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
869 * 0.333334 /* binary -> octal */
871 + 1; /* turn floor into ceil */
872 if (tmp_length
< precision
)
873 tmp_length
= precision
;
874 /* Add 1, to account for a leading sign. */
875 tmp_length
= xsum (tmp_length
, 1);
879 # if HAVE_LONG_LONG_INT
880 if (type
== TYPE_LONGLONGINT
|| type
== TYPE_ULONGLONGINT
)
882 (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
883 * 0.25 /* binary -> hexadecimal */
885 + 1; /* turn floor into ceil */
888 if (type
== TYPE_LONGINT
|| type
== TYPE_ULONGINT
)
890 (unsigned int) (sizeof (unsigned long) * CHAR_BIT
891 * 0.25 /* binary -> hexadecimal */
893 + 1; /* turn floor into ceil */
896 (unsigned int) (sizeof (unsigned int) * CHAR_BIT
897 * 0.25 /* binary -> hexadecimal */
899 + 1; /* turn floor into ceil */
900 if (tmp_length
< precision
)
901 tmp_length
= precision
;
902 /* Add 2, to account for a leading sign or alternate form. */
903 tmp_length
= xsum (tmp_length
, 2);
907 if (type
== TYPE_LONGDOUBLE
)
909 (unsigned int) (LDBL_MAX_EXP
910 * 0.30103 /* binary -> decimal */
911 * 2 /* estimate for FLAG_GROUP */
913 + 1 /* turn floor into ceil */
914 + 10; /* sign, decimal point etc. */
917 (unsigned int) (DBL_MAX_EXP
918 * 0.30103 /* binary -> decimal */
919 * 2 /* estimate for FLAG_GROUP */
921 + 1 /* turn floor into ceil */
922 + 10; /* sign, decimal point etc. */
923 tmp_length
= xsum (tmp_length
, precision
);
926 case 'e': case 'E': case 'g': case 'G':
928 12; /* sign, decimal point, exponent etc. */
929 tmp_length
= xsum (tmp_length
, precision
);
933 if (type
== TYPE_LONGDOUBLE
)
935 (unsigned int) (LDBL_DIG
936 * 0.831 /* decimal -> hexadecimal */
938 + 1; /* turn floor into ceil */
941 (unsigned int) (DBL_DIG
942 * 0.831 /* decimal -> hexadecimal */
944 + 1; /* turn floor into ceil */
945 if (tmp_length
< precision
)
946 tmp_length
= precision
;
947 /* Account for sign, decimal point etc. */
948 tmp_length
= xsum (tmp_length
, 12);
952 # if HAVE_WINT_T && !WIDE_CHAR_VERSION
953 if (type
== TYPE_WIDE_CHAR
)
954 tmp_length
= MB_CUR_MAX
;
962 if (type
== TYPE_WIDE_STRING
)
965 local_wcslen (a
.arg
[dp
->arg_index
].a
.a_wide_string
);
967 # if !WIDE_CHAR_VERSION
968 tmp_length
= xtimes (tmp_length
, MB_CUR_MAX
);
973 tmp_length
= strlen (a
.arg
[dp
->arg_index
].a
.a_string
);
978 (unsigned int) (sizeof (void *) * CHAR_BIT
979 * 0.25 /* binary -> hexadecimal */
981 + 1 /* turn floor into ceil */
982 + 2; /* account for leading 0x */
989 if (tmp_length
< width
)
992 tmp_length
= xsum (tmp_length
, 1); /* account for trailing NUL */
995 if (tmp_length
<= sizeof (tmpbuf
) / sizeof (CHAR_T
))
999 size_t tmp_memsize
= xtimes (tmp_length
, sizeof (CHAR_T
));
1001 if (size_overflow_p (tmp_memsize
))
1002 /* Overflow, would lead to out of memory. */
1004 tmp
= (CHAR_T
*) malloc (tmp_memsize
);
1006 /* Out of memory. */
1011 /* Construct the format string for calling snprintf or
1015 if (dp
->flags
& FLAG_GROUP
)
1017 if (dp
->flags
& FLAG_LEFT
)
1019 if (dp
->flags
& FLAG_SHOWSIGN
)
1021 if (dp
->flags
& FLAG_SPACE
)
1023 if (dp
->flags
& FLAG_ALT
)
1025 if (dp
->flags
& FLAG_ZERO
)
1027 if (dp
->width_start
!= dp
->width_end
)
1029 size_t n
= dp
->width_end
- dp
->width_start
;
1030 memcpy (p
, dp
->width_start
, n
* sizeof (CHAR_T
));
1033 if (dp
->precision_start
!= dp
->precision_end
)
1035 size_t n
= dp
->precision_end
- dp
->precision_start
;
1036 memcpy (p
, dp
->precision_start
, n
* sizeof (CHAR_T
));
1042 #if HAVE_LONG_LONG_INT
1043 case TYPE_LONGLONGINT
:
1044 case TYPE_ULONGLONGINT
:
1051 case TYPE_WIDE_CHAR
:
1054 case TYPE_WIDE_STRING
:
1058 case TYPE_LONGDOUBLE
:
1064 #if NEED_PRINTF_DIRECTIVE_F
1065 if (dp
->conversion
== 'F')
1069 *p
= dp
->conversion
;
1078 /* Construct the arguments for calling snprintf or sprintf. */
1080 if (dp
->width_arg_index
!= ARG_NONE
)
1082 if (!(a
.arg
[dp
->width_arg_index
].type
== TYPE_INT
))
1084 prefixes
[prefix_count
++] = a
.arg
[dp
->width_arg_index
].a
.a_int
;
1086 if (dp
->precision_arg_index
!= ARG_NONE
)
1088 if (!(a
.arg
[dp
->precision_arg_index
].type
== TYPE_INT
))
1090 prefixes
[prefix_count
++] = a
.arg
[dp
->precision_arg_index
].a
.a_int
;
1094 /* Prepare checking whether snprintf returns the count
1096 ENSURE_ALLOCATION (xsum (length
, 1));
1097 result
[length
] = '\0';
1106 maxlen
= allocated
- length
;
1111 /* SNPRINTF can fail if maxlen > INT_MAX. */
1112 if (maxlen
> INT_MAX
)
1114 # define SNPRINTF_BUF(arg) \
1115 switch (prefix_count) \
1118 retcount = SNPRINTF (result + length, maxlen, buf, \
1122 retcount = SNPRINTF (result + length, maxlen, buf, \
1123 prefixes[0], arg, &count); \
1126 retcount = SNPRINTF (result + length, maxlen, buf, \
1127 prefixes[0], prefixes[1], arg, \
1134 # define SNPRINTF_BUF(arg) \
1135 switch (prefix_count) \
1138 count = sprintf (tmp, buf, arg); \
1141 count = sprintf (tmp, buf, prefixes[0], arg); \
1144 count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
1156 int arg
= a
.arg
[dp
->arg_index
].a
.a_schar
;
1162 unsigned int arg
= a
.arg
[dp
->arg_index
].a
.a_uchar
;
1168 int arg
= a
.arg
[dp
->arg_index
].a
.a_short
;
1174 unsigned int arg
= a
.arg
[dp
->arg_index
].a
.a_ushort
;
1180 int arg
= a
.arg
[dp
->arg_index
].a
.a_int
;
1186 unsigned int arg
= a
.arg
[dp
->arg_index
].a
.a_uint
;
1192 long int arg
= a
.arg
[dp
->arg_index
].a
.a_longint
;
1198 unsigned long int arg
= a
.arg
[dp
->arg_index
].a
.a_ulongint
;
1202 #if HAVE_LONG_LONG_INT
1203 case TYPE_LONGLONGINT
:
1205 long long int arg
= a
.arg
[dp
->arg_index
].a
.a_longlongint
;
1209 case TYPE_ULONGLONGINT
:
1211 unsigned long long int arg
= a
.arg
[dp
->arg_index
].a
.a_ulonglongint
;
1218 double arg
= a
.arg
[dp
->arg_index
].a
.a_double
;
1222 case TYPE_LONGDOUBLE
:
1224 long double arg
= a
.arg
[dp
->arg_index
].a
.a_longdouble
;
1230 int arg
= a
.arg
[dp
->arg_index
].a
.a_char
;
1235 case TYPE_WIDE_CHAR
:
1237 wint_t arg
= a
.arg
[dp
->arg_index
].a
.a_wide_char
;
1244 const char *arg
= a
.arg
[dp
->arg_index
].a
.a_string
;
1249 case TYPE_WIDE_STRING
:
1251 const wchar_t *arg
= a
.arg
[dp
->arg_index
].a
.a_wide_string
;
1258 void *arg
= a
.arg
[dp
->arg_index
].a
.a_pointer
;
1267 /* Portability: Not all implementations of snprintf()
1268 are ISO C 99 compliant. Determine the number of
1269 bytes that snprintf() has produced or would have
1273 /* Verify that snprintf() has NUL-terminated its
1275 if (count
< maxlen
&& result
[length
+ count
] != '\0')
1277 /* Portability hack. */
1278 if (retcount
> count
)
1283 /* snprintf() doesn't understand the '%n'
1287 /* Don't use the '%n' directive; instead, look
1288 at the snprintf() return value. */
1294 /* Look at the snprintf() return value. */
1297 /* HP-UX 10.20 snprintf() is doubly deficient:
1298 It doesn't understand the '%n' directive,
1299 *and* it returns -1 (rather than the length
1300 that would have been required) when the
1301 buffer is too small. */
1302 size_t bigger_need
=
1303 xsum (xtimes (allocated
, 2), 12);
1304 ENSURE_ALLOCATION (bigger_need
);
1313 /* Attempt to handle failure. */
1316 if (!(result
== resultbuf
|| result
== NULL
))
1318 if (buf_malloced
!= NULL
)
1319 free (buf_malloced
);
1326 if (count
>= tmp_length
)
1327 /* tmp_length was incorrectly calculated - fix the
1332 /* Make room for the result. */
1333 if (count
>= maxlen
)
1335 /* Need at least count bytes. But allocate
1336 proportionally, to avoid looping eternally if
1337 snprintf() reports a too small count. */
1339 xmax (xsum (length
, count
), xtimes (allocated
, 2));
1341 ENSURE_ALLOCATION (n
);
1348 /* The snprintf() result did fit. */
1350 /* Append the sprintf() result. */
1351 memcpy (result
+ length
, tmp
, count
* sizeof (CHAR_T
));
1356 #if NEED_PRINTF_DIRECTIVE_F
1357 if (dp
->conversion
== 'F')
1359 /* Convert the %f result to upper case for %F. */
1360 CHAR_T
*rp
= result
+ length
;
1362 for (rc
= count
; rc
> 0; rc
--, rp
++)
1363 if (*rp
>= 'a' && *rp
<= 'z')
1364 *rp
= *rp
- 'a' + 'A';
1375 /* Add the final NUL. */
1376 ENSURE_ALLOCATION (xsum (length
, 1));
1377 result
[length
] = '\0';
1379 if (result
!= resultbuf
&& length
+ 1 < allocated
)
1381 /* Shrink the allocated memory if possible. */
1384 memory
= (CHAR_T
*) realloc (result
, (length
+ 1) * sizeof (CHAR_T
));
1389 if (buf_malloced
!= NULL
)
1390 free (buf_malloced
);
1393 /* Note that we can produce a big string of a length > INT_MAX. POSIX
1394 says that snprintf() fails with errno = EOVERFLOW in this case, but
1395 that's only because snprintf() returns an 'int'. This function does
1396 not have this limitation. */
1400 if (!(result
== resultbuf
|| result
== NULL
))
1402 if (buf_malloced
!= NULL
)
1403 free (buf_malloced
);
1409 if (!(result
== resultbuf
|| result
== NULL
))
1411 if (buf_malloced
!= NULL
)
1412 free (buf_malloced
);