vasprintf.c revision 1.1 1 1.1 skrll /* Like vsprintf but provides a pointer to malloc'd storage, which must
2 1.1 skrll be freed by the caller.
3 1.1 skrll Copyright (C) 1994, 2003 Free Software Foundation, Inc.
4 1.1 skrll
5 1.1 skrll This file is part of the libiberty library.
6 1.1 skrll Libiberty is free software; you can redistribute it and/or
7 1.1 skrll modify it under the terms of the GNU Library General Public
8 1.1 skrll License as published by the Free Software Foundation; either
9 1.1 skrll version 2 of the License, or (at your option) any later version.
10 1.1 skrll
11 1.1 skrll Libiberty is distributed in the hope that it will be useful,
12 1.1 skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 1.1 skrll Library General Public License for more details.
15 1.1 skrll
16 1.1 skrll You should have received a copy of the GNU Library General Public
17 1.1 skrll License along with libiberty; see the file COPYING.LIB. If
18 1.1 skrll not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19 1.1 skrll Boston, MA 02110-1301, USA. */
20 1.1 skrll
21 1.1 skrll #ifdef HAVE_CONFIG_H
22 1.1 skrll #include "config.h"
23 1.1 skrll #endif
24 1.1 skrll #include <ansidecl.h>
25 1.1 skrll #include <stdarg.h>
26 1.1 skrll #if !defined (va_copy) && defined (__va_copy)
27 1.1 skrll # define va_copy(d,s) __va_copy((d),(s))
28 1.1 skrll #endif
29 1.1 skrll #include <stdio.h>
30 1.1 skrll #ifdef HAVE_STRING_H
31 1.1 skrll #include <string.h>
32 1.1 skrll #endif
33 1.1 skrll #ifdef HAVE_STDLIB_H
34 1.1 skrll #include <stdlib.h>
35 1.1 skrll #else
36 1.1 skrll extern unsigned long strtoul ();
37 1.1 skrll extern PTR malloc ();
38 1.1 skrll #endif
39 1.1 skrll #include "libiberty.h"
40 1.1 skrll
41 1.1 skrll #ifdef TEST
42 1.1 skrll int global_total_width;
43 1.1 skrll #endif
44 1.1 skrll
45 1.1 skrll /*
46 1.1 skrll
47 1.1 skrll @deftypefn Extension int vasprintf (char **@var{resptr}, const char *@var{format}, va_list @var{args})
48 1.1 skrll
49 1.1 skrll Like @code{vsprintf}, but instead of passing a pointer to a buffer,
50 1.1 skrll you pass a pointer to a pointer. This function will compute the size
51 1.1 skrll of the buffer needed, allocate memory with @code{malloc}, and store a
52 1.1 skrll pointer to the allocated memory in @code{*@var{resptr}}. The value
53 1.1 skrll returned is the same as @code{vsprintf} would return. If memory could
54 1.1 skrll not be allocated, minus one is returned and @code{NULL} is stored in
55 1.1 skrll @code{*@var{resptr}}.
56 1.1 skrll
57 1.1 skrll @end deftypefn
58 1.1 skrll
59 1.1 skrll */
60 1.1 skrll
61 1.1 skrll static int int_vasprintf (char **, const char *, va_list);
62 1.1 skrll
63 1.1 skrll static int
64 1.1 skrll int_vasprintf (char **result, const char *format, va_list args)
65 1.1 skrll {
66 1.1 skrll const char *p = format;
67 1.1 skrll /* Add one to make sure that it is never zero, which might cause malloc
68 1.1 skrll to return NULL. */
69 1.1 skrll int total_width = strlen (format) + 1;
70 1.1 skrll va_list ap;
71 1.1 skrll
72 1.1 skrll #ifdef va_copy
73 1.1 skrll va_copy (ap, args);
74 1.1 skrll #else
75 1.1 skrll memcpy ((PTR) &ap, (PTR) &args, sizeof (va_list));
76 1.1 skrll #endif
77 1.1 skrll
78 1.1 skrll while (*p != '\0')
79 1.1 skrll {
80 1.1 skrll if (*p++ == '%')
81 1.1 skrll {
82 1.1 skrll while (strchr ("-+ #0", *p))
83 1.1 skrll ++p;
84 1.1 skrll if (*p == '*')
85 1.1 skrll {
86 1.1 skrll ++p;
87 1.1 skrll total_width += abs (va_arg (ap, int));
88 1.1 skrll }
89 1.1 skrll else
90 1.1 skrll total_width += strtoul (p, (char **) &p, 10);
91 1.1 skrll if (*p == '.')
92 1.1 skrll {
93 1.1 skrll ++p;
94 1.1 skrll if (*p == '*')
95 1.1 skrll {
96 1.1 skrll ++p;
97 1.1 skrll total_width += abs (va_arg (ap, int));
98 1.1 skrll }
99 1.1 skrll else
100 1.1 skrll total_width += strtoul (p, (char **) &p, 10);
101 1.1 skrll }
102 1.1 skrll while (strchr ("hlL", *p))
103 1.1 skrll ++p;
104 1.1 skrll /* Should be big enough for any format specifier except %s and floats. */
105 1.1 skrll total_width += 30;
106 1.1 skrll switch (*p)
107 1.1 skrll {
108 1.1 skrll case 'd':
109 1.1 skrll case 'i':
110 1.1 skrll case 'o':
111 1.1 skrll case 'u':
112 1.1 skrll case 'x':
113 1.1 skrll case 'X':
114 1.1 skrll case 'c':
115 1.1 skrll (void) va_arg (ap, int);
116 1.1 skrll break;
117 1.1 skrll case 'f':
118 1.1 skrll case 'e':
119 1.1 skrll case 'E':
120 1.1 skrll case 'g':
121 1.1 skrll case 'G':
122 1.1 skrll (void) va_arg (ap, double);
123 1.1 skrll /* Since an ieee double can have an exponent of 307, we'll
124 1.1 skrll make the buffer wide enough to cover the gross case. */
125 1.1 skrll total_width += 307;
126 1.1 skrll break;
127 1.1 skrll case 's':
128 1.1 skrll total_width += strlen (va_arg (ap, char *));
129 1.1 skrll break;
130 1.1 skrll case 'p':
131 1.1 skrll case 'n':
132 1.1 skrll (void) va_arg (ap, char *);
133 1.1 skrll break;
134 1.1 skrll }
135 1.1 skrll p++;
136 1.1 skrll }
137 1.1 skrll }
138 1.1 skrll #ifdef va_copy
139 1.1 skrll va_end (ap);
140 1.1 skrll #endif
141 1.1 skrll #ifdef TEST
142 1.1 skrll global_total_width = total_width;
143 1.1 skrll #endif
144 1.1 skrll *result = (char *) malloc (total_width);
145 1.1 skrll if (*result != NULL)
146 1.1 skrll return vsprintf (*result, format, args);
147 1.1 skrll else
148 1.1 skrll return -1;
149 1.1 skrll }
150 1.1 skrll
151 1.1 skrll int
152 1.1 skrll vasprintf (char **result, const char *format,
153 1.1 skrll #if defined (_BSD_VA_LIST_) && defined (__FreeBSD__)
154 1.1 skrll _BSD_VA_LIST_ args)
155 1.1 skrll #else
156 1.1 skrll va_list args)
157 1.1 skrll #endif
158 1.1 skrll {
159 1.1 skrll return int_vasprintf (result, format, args);
160 1.1 skrll }
161 1.1 skrll
162 1.1 skrll #ifdef TEST
163 1.1 skrll static void ATTRIBUTE_PRINTF_1
164 1.1 skrll checkit (const char *format, ...)
165 1.1 skrll {
166 1.1 skrll char *result;
167 1.1 skrll VA_OPEN (args, format);
168 1.1 skrll VA_FIXEDARG (args, const char *, format);
169 1.1 skrll vasprintf (&result, format, args);
170 1.1 skrll VA_CLOSE (args);
171 1.1 skrll
172 1.1 skrll if (strlen (result) < (size_t) global_total_width)
173 1.1 skrll printf ("PASS: ");
174 1.1 skrll else
175 1.1 skrll printf ("FAIL: ");
176 1.1 skrll printf ("%d %s\n", global_total_width, result);
177 1.1 skrll
178 1.1 skrll free (result);
179 1.1 skrll }
180 1.1 skrll
181 1.1 skrll extern int main (void);
182 1.1 skrll
183 1.1 skrll int
184 1.1 skrll main (void)
185 1.1 skrll {
186 1.1 skrll checkit ("%d", 0x12345678);
187 1.1 skrll checkit ("%200d", 5);
188 1.1 skrll checkit ("%.300d", 6);
189 1.1 skrll checkit ("%100.150d", 7);
190 1.1 skrll checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
191 1.1 skrll 777777777777777777333333333333366666666666622222222222777777777777733333");
192 1.1 skrll checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
193 1.1 skrll
194 1.1 skrll return 0;
195 1.1 skrll }
196 1.1 skrll #endif /* TEST */
197