1 /* Like vsprintf but provides a pointer to malloc'd storage, which must
2 be freed by the caller.
3 Copyright (c) 1994 Free Software Foundation, Inc.
4
5 This file is part of the libiberty library.
6 Libiberty is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 Libiberty is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with libiberty; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301 USA. */
20
21 #include <config.h>
22
23 #ifndef HAVE_VASPRINTF
24
25 #include <unistd.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
int_vasprintf(char ** result,char * format,va_list args)31 static int int_vasprintf(char **result, char *format, va_list args) {
32 char *p = format;
33 /*
34 ** Add one to make sure that it is never zero, which might cause malloc
35 ** to return NULL.
36 */
37 int total_width = strlen(format) + 1;
38 va_list ap;
39
40 memcpy(&ap, args, sizeof(va_list));
41
42 while (*p != '\0') {
43 if (*p++ == '%') {
44 while (strchr("-+ #0", *p))
45 ++p;
46 if (*p == '*') {
47 ++p;
48 total_width += abs(va_arg(ap, int));
49 } else
50 total_width += strtoul(p, &p, 10);
51
52 if (*p == '.') {
53 ++p;
54 if (*p == '*') {
55 ++p;
56 total_width += abs(va_arg(ap, int));
57 } else
58 total_width += strtoul(p, &p, 10);
59 }
60
61 while (strchr("hlL", *p))
62 ++p;
63 /*
64 ** Should be big enough for any format
65 ** specifier except %s and floats.
66 */
67 total_width += 30;
68
69 switch (*p) {
70 case 'd':
71 case 'i':
72 case 'o':
73 case 'u':
74 case 'x':
75 case 'X':
76 case 'c':
77 (void) va_arg(ap, int);
78 break;
79
80 case 'f':
81 case 'e':
82 case 'E':
83 case 'g':
84 case 'G':
85 (void) va_arg(ap, double);
86 /*
87 ** Since an ieee double can have an exponent of 307,
88 ** we'll make the buffer wide enough to cover
89 ** the gross case.
90 */
91 total_width += 307;
92 break;
93
94 case 's':
95 total_width += strlen(va_arg(ap, char *));
96 break;
97
98 case 'p':
99 case 'n':
100 (void) va_arg(ap, char *);
101 break;
102 }
103 }
104 }
105
106 *result = malloc(total_width);
107 if (*result != NULL)
108 return (vsprintf(*result, format, args));
109 else
110 return (0);
111 }
112
vasprintf(char ** strp,const char * fmt,va_list ap)113 int vasprintf(char **strp, const char *fmt, va_list ap) {
114 return (int_vasprintf(strp, (char *) fmt, ap));
115 }
116
117 #endif
118