Commit 2f13ebfe 2f13ebfeddc73927f65ea8477049b4160d69101d by Alain Magloire

Replace for loosing platforms.

1 parent fdd1855d
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 program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <string.h>
25
26 #if __STDC__
27 # include <stdarg.h>
28 #else
29 # include <varargs.h>
30 #endif
31
32 #ifdef TEST
33 int global_total_width;
34 #endif
35
36 unsigned long strtoul ();
37 char *malloc ();
38
39 static int
40 int_vasprintf (result, format, args)
41 char **result;
42 const char *format;
43 va_list *args;
44 {
45 const char *p = format;
46 /* Add one to make sure that it is never zero, which might cause malloc
47 to return NULL. */
48 int total_width = strlen (format) + 1;
49 va_list ap;
50
51 memcpy (&ap, args, sizeof (va_list));
52
53 while (*p != '\0')
54 {
55 if (*p++ == '%')
56 {
57 while (strchr ("-+ #0", *p))
58 ++p;
59 if (*p == '*')
60 {
61 ++p;
62 total_width += abs (va_arg (ap, int));
63 }
64 else
65 total_width += strtoul (p, &p, 10);
66 if (*p == '.')
67 {
68 ++p;
69 if (*p == '*')
70 {
71 ++p;
72 total_width += abs (va_arg (ap, int));
73 }
74 else
75 total_width += strtoul (p, &p, 10);
76 }
77 while (strchr ("hlL", *p))
78 ++p;
79 /* Should be big enough for any format specifier except %s. */
80 total_width += 30;
81 switch (*p)
82 {
83 case 'd':
84 case 'i':
85 case 'o':
86 case 'u':
87 case 'x':
88 case 'X':
89 case 'c':
90 (void) va_arg (ap, int);
91 break;
92 case 'f':
93 case 'e':
94 case 'E':
95 case 'g':
96 case 'G':
97 (void) va_arg (ap, double);
98 break;
99 case 's':
100 total_width += strlen (va_arg (ap, char *));
101 break;
102 case 'p':
103 case 'n':
104 (void) va_arg (ap, char *);
105 break;
106 }
107 }
108 }
109 #ifdef TEST
110 global_total_width = total_width;
111 #endif
112 *result = malloc (total_width);
113 if (*result != NULL)
114 return vsprintf (*result, format, *args);
115 else
116 return 0;
117 }
118
119 int
120 vasprintf (result, format, args)
121 char **result;
122 const char *format;
123 va_list args;
124 {
125 return int_vasprintf (result, format, &args);
126 }
127
128 int
129 asprintf
130 #if __STDC__
131 (char **result, const char *format, ...)
132 #else
133 (result, va_alist)
134 char **result;
135 va_dcl
136 #endif
137 {
138 va_list args;
139 int done;
140
141 #if __STDC__
142 va_start (args, format);
143 #else
144 char *format;
145 va_start (args);
146 format = va_arg (args, char *);
147 #endif
148 done = vasprintf (result, format, args);
149 va_end (args);
150
151 return done;
152 }
153
154 #ifdef TEST
155 void
156 checkit
157 #if __STDC__
158 (const char* format, ...)
159 #else
160 (va_alist)
161 va_dcl
162 #endif
163 {
164 va_list args;
165 char *result;
166
167 #if __STDC__
168 va_start (args, format);
169 #else
170 char *format;
171 va_start (args);
172 format = va_arg (args, char *);
173 #endif
174 vasprintf (&result, format, args);
175 if (strlen (result) < global_total_width)
176 printf ("PASS: ");
177 else
178 printf ("FAIL: ");
179 printf ("%d %s\n", global_total_width, result);
180 }
181
182 int
183 main ()
184 {
185 checkit ("%d", 0x12345678);
186 checkit ("%200d", 5);
187 checkit ("%.300d", 6);
188 checkit ("%100.150d", 7);
189 checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
190 777777777777777777333333333333366666666666622222222222777777777777733333");
191 checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
192 }
193 #endif /* TEST */