source: branches/libc-0.6/src/binutils/libiberty/vasprintf.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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