| |
1 /* Like vsprintf but provides a pointer to malloc'd storage, which must |
| |
2 be freed by the caller. |
| |
3 Copyright (C) 1994, 2003 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 |
| |
18 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| |
19 Boston, MA 02111-1307, USA. */ |
| |
20 |
| |
21 #include <stdarg.h> |
| |
22 #include <stdio.h> |
| |
23 #include <stdlib.h> |
| |
24 #include <string.h> |
| |
25 #include "vasprintf.h" |
| |
26 |
| |
27 /* |
| |
28 |
| |
29 @deftypefn Extension int vasprintf (char **@var{resptr}, const char *@var{format}, va_list @var{args}) |
| |
30 |
| |
31 Like @code{vsprintf}, but instead of passing a pointer to a buffer, |
| |
32 you pass a pointer to a pointer. This function will compute the size |
| |
33 of the buffer needed, allocate memory with @code{malloc}, and store a |
| |
34 pointer to the allocated memory in @code{*@var{resptr}}. The value |
| |
35 returned is the same as @code{vsprintf} would return. If memory could |
| |
36 not be allocated, minus one is returned and @code{NULL} is stored in |
| |
37 @code{*@var{resptr}}. |
| |
38 |
| |
39 @end deftypefn |
| |
40 |
| |
41 */ |
| |
42 |
| |
43 static int int_vasprintf(char **, const char *, va_list); |
| |
44 |
| |
45 static int |
| |
46 int_vasprintf (result, format, args) |
| |
47 char **result; |
| |
48 const char *format; |
| |
49 va_list args; |
| |
50 { |
| |
51 const char *p = format; |
| |
52 /* Add one to make sure that it is never zero, which might cause malloc |
| |
53 to return NULL. */ |
| |
54 int total_width = strlen (format) + 1; |
| |
55 va_list ap; |
| |
56 |
| |
57 memcpy ((void *) &ap, (const void *) &args, sizeof (va_list)); |
| |
58 |
| |
59 while (*p != '\0') |
| |
60 { |
| |
61 if (*p++ == '%') |
| |
62 { |
| |
63 while (strchr ("-+ #0", *p)) |
| |
64 ++p; |
| |
65 if (*p == '*') |
| |
66 { |
| |
67 ++p; |
| |
68 total_width += abs (va_arg (ap, int)); |
| |
69 } |
| |
70 else |
| |
71 total_width += strtoul (p, (char **) &p, 10); |
| |
72 if (*p == '.') |
| |
73 { |
| |
74 ++p; |
| |
75 if (*p == '*') |
| |
76 { |
| |
77 ++p; |
| |
78 total_width += abs (va_arg (ap, int)); |
| |
79 } |
| |
80 else |
| |
81 total_width += strtoul (p, (char **) &p, 10); |
| |
82 } |
| |
83 while (strchr ("hlL", *p)) |
| |
84 ++p; |
| |
85 /* Should be big enough for any format specifier except %s and floats. */ |
| |
86 total_width += 30; |
| |
87 switch (*p) |
| |
88 { |
| |
89 case 'd': |
| |
90 case 'i': |
| |
91 case 'o': |
| |
92 case 'u': |
| |
93 case 'x': |
| |
94 case 'X': |
| |
95 case 'c': |
| |
96 (void) va_arg (ap, int); |
| |
97 break; |
| |
98 case 'f': |
| |
99 case 'e': |
| |
100 case 'E': |
| |
101 case 'g': |
| |
102 case 'G': |
| |
103 (void) va_arg (ap, double); |
| |
104 /* Since an ieee double can have an exponent of 307, we'll |
| |
105 make the buffer wide enough to cover the gross case. */ |
| |
106 total_width += 307; |
| |
107 break; |
| |
108 case 's': |
| |
109 total_width += strlen (va_arg (ap, char *)); |
| |
110 break; |
| |
111 case 'p': |
| |
112 case 'n': |
| |
113 (void) va_arg (ap, char *); |
| |
114 break; |
| |
115 } |
| |
116 p++; |
| |
117 } |
| |
118 } |
| |
119 *result = (char *) malloc (total_width); |
| |
120 if (*result != NULL) |
| |
121 return vsprintf (*result, format, args); |
| |
122 else |
| |
123 return -1; |
| |
124 } |
| |
125 |
| |
126 int |
| |
127 vasprintf (result, format, args) |
| |
128 char **result; |
| |
129 const char *format; |
| |
130 va_list args; |
| |
131 { |
| |
132 return int_vasprintf (result, format, args); |
| |
133 } |