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
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
31
#include "vasnprintf.h"
33
#include <stdio.h> /* snprintf(), sprintf() */
34
#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
35
#include <string.h> /* memcpy(), strlen() */
36
#include <errno.h> /* errno */
37
#include <limits.h> /* CHAR_BIT */
38
#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
39
#include "printf-parse.h"
41
/* For those losing systems which don't have 'alloca' we have to add
42
some additional code emulating it. */
44
# define freea(p) /* nothing */
46
# define alloca(n) malloc (n)
47
# define freea(p) free (p)
52
# define local_wcslen wcslen
54
/* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
55
a dependency towards this library, here is a local substitute. */
57
local_wcslen (const wchar_t *s)
61
for (ptr = s; *ptr != (wchar_t) 0; ptr++)
69
vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
74
if (printf_parse (format, &d, &a) < 0)
85
if (printf_fetchargs (args, &a) < 0)
94
(char *) alloca (7 + d.max_width_length + d.max_precision_length + 6);
98
/* Output string accumulator. */
103
if (resultbuf != NULL)
106
allocated = *lengthp;
115
result is either == resultbuf or == NULL or malloc-allocated.
116
If length > 0, then result != NULL. */
118
#define ENSURE_ALLOCATION(needed) \
119
if ((needed) > allocated) \
123
allocated = (allocated > 0 ? 2 * allocated : 12); \
124
if ((needed) > allocated) \
125
allocated = (needed); \
126
if (result == resultbuf || result == NULL) \
127
memory = (char *) malloc (allocated); \
129
memory = (char *) realloc (result, allocated); \
131
if (memory == NULL) \
133
if (!(result == resultbuf || result == NULL)) \
140
if (result == resultbuf && length > 0) \
141
memcpy (memory, result, length); \
145
for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
147
if (cp != dp->dir_start)
149
size_t n = dp->dir_start - cp;
151
ENSURE_ALLOCATION (length + n);
152
memcpy (result + length, cp, n);
158
/* Execute a single directive. */
159
if (dp->conversion == '%')
161
if (!(dp->arg_index < 0))
163
ENSURE_ALLOCATION (length + 1);
164
result[length] = '%';
169
if (!(dp->arg_index >= 0))
172
if (dp->conversion == 'n')
174
switch (a.arg[dp->arg_index].type)
176
case TYPE_COUNT_SCHAR_POINTER:
177
*a.arg[dp->arg_index].a.a_count_schar_pointer = length;
179
case TYPE_COUNT_SHORT_POINTER:
180
*a.arg[dp->arg_index].a.a_count_short_pointer = length;
182
case TYPE_COUNT_INT_POINTER:
183
*a.arg[dp->arg_index].a.a_count_int_pointer = length;
185
case TYPE_COUNT_LONGINT_POINTER:
186
*a.arg[dp->arg_index].a.a_count_longint_pointer = length;
188
#ifdef HAVE_LONG_LONG
189
case TYPE_COUNT_LONGLONGINT_POINTER:
190
*a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
199
arg_type type = a.arg[dp->arg_index].type;
201
unsigned int prefix_count;
204
unsigned int tmp_length;
208
/* Allocate a temporary buffer of sufficient size for calling
212
unsigned int precision;
215
if (dp->width_start != dp->width_end)
217
if (dp->width_arg_index >= 0)
221
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
223
arg = a.arg[dp->width_arg_index].a.a_int;
224
width = (arg < 0 ? -arg : arg);
228
const char *digitp = dp->width_start;
231
width = width * 10 + (*digitp++ - '0');
232
while (digitp != dp->width_end);
237
if (dp->precision_start != dp->precision_end)
239
if (dp->precision_arg_index >= 0)
243
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
245
arg = a.arg[dp->precision_arg_index].a.a_int;
246
precision = (arg < 0 ? 0 : arg);
250
const char *digitp = dp->precision_start + 1;
254
precision = precision * 10 + (*digitp++ - '0');
255
while (digitp != dp->precision_end);
259
switch (dp->conversion)
262
case 'd': case 'i': case 'u':
263
# ifdef HAVE_LONG_LONG
264
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
266
(unsigned int) (sizeof (unsigned long long) * CHAR_BIT
267
* 0.30103 /* binary -> decimal */
268
* 2 /* estimate for FLAG_GROUP */
270
+ 1 /* turn floor into ceil */
271
+ 1; /* account for leading sign */
274
if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
276
(unsigned int) (sizeof (unsigned long) * CHAR_BIT
277
* 0.30103 /* binary -> decimal */
278
* 2 /* estimate for FLAG_GROUP */
280
+ 1 /* turn floor into ceil */
281
+ 1; /* account for leading sign */
284
(unsigned int) (sizeof (unsigned int) * CHAR_BIT
285
* 0.30103 /* binary -> decimal */
286
* 2 /* estimate for FLAG_GROUP */
288
+ 1 /* turn floor into ceil */
289
+ 1; /* account for leading sign */
293
# ifdef HAVE_LONG_LONG
294
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
296
(unsigned int) (sizeof (unsigned long long) * CHAR_BIT
297
* 0.333334 /* binary -> octal */
299
+ 1 /* turn floor into ceil */
300
+ 1; /* account for leading sign */
303
if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
305
(unsigned int) (sizeof (unsigned long) * CHAR_BIT
306
* 0.333334 /* binary -> octal */
308
+ 1 /* turn floor into ceil */
309
+ 1; /* account for leading sign */
312
(unsigned int) (sizeof (unsigned int) * CHAR_BIT
313
* 0.333334 /* binary -> octal */
315
+ 1 /* turn floor into ceil */
316
+ 1; /* account for leading sign */
320
# ifdef HAVE_LONG_LONG
321
if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
323
(unsigned int) (sizeof (unsigned long long) * CHAR_BIT
324
* 0.25 /* binary -> hexadecimal */
326
+ 1 /* turn floor into ceil */
327
+ 2; /* account for leading sign or alternate form */
330
if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
332
(unsigned int) (sizeof (unsigned long) * CHAR_BIT
333
* 0.25 /* binary -> hexadecimal */
335
+ 1 /* turn floor into ceil */
336
+ 2; /* account for leading sign or alternate form */
339
(unsigned int) (sizeof (unsigned int) * CHAR_BIT
340
* 0.25 /* binary -> hexadecimal */
342
+ 1 /* turn floor into ceil */
343
+ 2; /* account for leading sign or alternate form */
347
# ifdef HAVE_LONG_DOUBLE
348
if (type == TYPE_LONGDOUBLE)
350
(unsigned int) (LDBL_MAX_EXP
351
* 0.30103 /* binary -> decimal */
352
* 2 /* estimate for FLAG_GROUP */
354
+ 1 /* turn floor into ceil */
356
+ 10; /* sign, decimal point etc. */
360
(unsigned int) (DBL_MAX_EXP
361
* 0.30103 /* binary -> decimal */
362
* 2 /* estimate for FLAG_GROUP */
364
+ 1 /* turn floor into ceil */
366
+ 10; /* sign, decimal point etc. */
369
case 'e': case 'E': case 'g': case 'G':
373
+ 12; /* sign, decimal point, exponent etc. */
378
if (type == TYPE_WIDE_CHAR)
379
tmp_length = MB_CUR_MAX;
387
if (type == TYPE_WIDE_STRING)
389
local_wcslen (a.arg[dp->arg_index].a.a_wide_string)
393
tmp_length = strlen (a.arg[dp->arg_index].a.a_string);
398
(unsigned int) (sizeof (void *) * CHAR_BIT
399
* 0.25 /* binary -> hexadecimal */
401
+ 1 /* turn floor into ceil */
402
+ 2; /* account for leading 0x */
409
if (tmp_length < width)
412
tmp_length++; /* account for trailing NUL */
415
if (tmp_length <= sizeof (tmpbuf))
419
tmp = (char *) malloc (tmp_length);
423
if (!(result == resultbuf || result == NULL))
433
/* Construct the format string for calling snprintf or
437
if (dp->flags & FLAG_GROUP)
439
if (dp->flags & FLAG_LEFT)
441
if (dp->flags & FLAG_SHOWSIGN)
443
if (dp->flags & FLAG_SPACE)
445
if (dp->flags & FLAG_ALT)
447
if (dp->flags & FLAG_ZERO)
449
if (dp->width_start != dp->width_end)
451
size_t n = dp->width_end - dp->width_start;
452
memcpy (p, dp->width_start, n);
455
if (dp->precision_start != dp->precision_end)
457
size_t n = dp->precision_end - dp->precision_start;
458
memcpy (p, dp->precision_start, n);
464
#ifdef HAVE_LONG_LONG
465
case TYPE_LONGLONGINT:
466
case TYPE_ULONGLONGINT:
476
case TYPE_WIDE_STRING:
480
#ifdef HAVE_LONG_DOUBLE
481
case TYPE_LONGDOUBLE:
497
/* Construct the arguments for calling snprintf or sprintf. */
499
if (dp->width_arg_index >= 0)
501
if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
503
prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
505
if (dp->precision_arg_index >= 0)
507
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
509
prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
513
/* Prepare checking whether snprintf returns the count
515
ENSURE_ALLOCATION (length + 1);
516
result[length] = '\0';
525
maxlen = allocated - length;
530
# define SNPRINTF_BUF(arg) \
531
switch (prefix_count) \
534
retcount = snprintf (result + length, maxlen, buf, \
538
retcount = snprintf (result + length, maxlen, buf, \
539
prefixes[0], arg, &count); \
542
retcount = snprintf (result + length, maxlen, buf, \
543
prefixes[0], prefixes[1], arg, \
550
# define SNPRINTF_BUF(arg) \
551
switch (prefix_count) \
554
count = sprintf (tmp, buf, arg); \
557
count = sprintf (tmp, buf, prefixes[0], arg); \
560
count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
572
int arg = a.arg[dp->arg_index].a.a_schar;
578
unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
584
int arg = a.arg[dp->arg_index].a.a_short;
590
unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
596
int arg = a.arg[dp->arg_index].a.a_int;
602
unsigned int arg = a.arg[dp->arg_index].a.a_uint;
608
long int arg = a.arg[dp->arg_index].a.a_longint;
614
unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
618
#ifdef HAVE_LONG_LONG
619
case TYPE_LONGLONGINT:
621
long long int arg = a.arg[dp->arg_index].a.a_longlongint;
625
case TYPE_ULONGLONGINT:
627
unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
634
double arg = a.arg[dp->arg_index].a.a_double;
638
#ifdef HAVE_LONG_DOUBLE
639
case TYPE_LONGDOUBLE:
641
long double arg = a.arg[dp->arg_index].a.a_longdouble;
648
int arg = a.arg[dp->arg_index].a.a_char;
655
wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
662
const char *arg = a.arg[dp->arg_index].a.a_string;
667
case TYPE_WIDE_STRING:
669
const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
676
void *arg = a.arg[dp->arg_index].a.a_pointer;
685
/* Portability: Not all implementations of snprintf()
686
are ISO C 99 compliant. Determine the number of
687
bytes that snprintf() has produced or would have
691
/* Verify that snprintf() has NUL-terminated its
693
if (count < maxlen && result[length + count] != '\0')
695
/* Portability hack. */
696
if (retcount > count)
701
/* snprintf() doesn't understand the '%n'
705
/* Don't use the '%n' directive; instead, look
706
at the snprintf() return value. */
714
/* Attempt to handle failure. */
717
if (!(result == resultbuf || result == NULL))
726
if (count >= tmp_length)
727
/* tmp_length was incorrectly calculated - fix the
732
/* Make room for the result. */
735
/* Need at least count bytes. But allocate
736
proportionally, to avoid looping eternally if
737
snprintf() reports a too small count. */
738
size_t n = length + count;
740
if (n < 2 * allocated)
743
ENSURE_ALLOCATION (n);
750
/* The snprintf() result did fit. */
752
/* Append the sprintf() result. */
753
memcpy (result + length, tmp, count);
765
/* Add the final NUL. */
766
ENSURE_ALLOCATION (length + 1);
767
result[length] = '\0';
769
if (result != resultbuf && length + 1 < allocated)
771
/* Shrink the allocated memory if possible. */
774
memory = (char *) realloc (result, length + 1);