This source file includes following definitions.
- guess_strlen
- opal_asprintf
- opal_vasprintf
- opal_snprintf
- opal_vsnprintf
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include "opal_config.h"
26
27 #include "opal/util/printf.h"
28 #include "opal/util/output.h"
29
30 #include <errno.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35
36 #ifndef HAVE_VASPRINTF
37
38
39
40
41
42
43 static int guess_strlen(const char *fmt, va_list ap)
44 {
45 #if HAVE_VSNPRINTF
46 char dummy[1];
47
48
49
50 return 1 + vsnprintf(dummy, sizeof(dummy), fmt, ap);
51 #else
52 char *sarg, carg;
53 double darg;
54 float farg;
55 size_t i;
56 int iarg;
57 int len;
58 long larg;
59
60
61
62
63 len = (int)strlen(fmt) + 128;
64 for (i = 0; i < strlen(fmt); ++i) {
65 if ('%' == fmt[i] && i + 1 < strlen(fmt)
66 && '%' != fmt[i + 1]) {
67 ++i;
68 switch (fmt[i]) {
69 case 'c':
70 carg = va_arg(ap, int);
71 len += 1;
72 (void)carg;
73 break;
74 case 's':
75 sarg = va_arg(ap, char *);
76
77
78
79
80 if (NULL != sarg) {
81 len += (int)strlen(sarg);
82 } else {
83 #if OPAL_ENABLE_DEBUG
84 opal_output(0, "OPAL DEBUG WARNING: Got a NULL argument to opal_vasprintf!\n");
85 #endif
86 len += 5;
87 }
88 break;
89
90 case 'd':
91 case 'i':
92 iarg = va_arg(ap, int);
93
94 if (iarg < 0)
95 ++len;
96
97 do {
98 ++len;
99 iarg /= 10;
100 } while (0 != iarg);
101 break;
102
103 case 'x':
104 case 'X':
105 iarg = va_arg(ap, int);
106
107 do {
108 ++len;
109 iarg /= 16;
110 } while (0 != iarg);
111 break;
112
113 case 'f':
114 farg = (float)va_arg(ap, int);
115
116 if (farg < 0) {
117 ++len;
118 farg = -farg;
119 }
120
121 len += 4;
122
123 do {
124 ++len;
125 farg /= 10.0;
126 } while (0 != farg);
127 break;
128
129 case 'g':
130 darg = va_arg(ap, int);
131
132 if (darg < 0) {
133 ++len;
134 darg = -darg;
135 }
136
137 len += 4;
138
139 do {
140 ++len;
141 darg /= 10.0;
142 } while (0 != darg);
143 break;
144
145 case 'l':
146
147 if (i + 1 < strlen(fmt)) {
148 ++i;
149 switch (fmt[i]) {
150 case 'x':
151 case 'X':
152 larg = va_arg(ap, int);
153
154 do {
155 ++len;
156 larg /= 16;
157 } while (0 != larg);
158 break;
159
160 case 'f':
161 darg = va_arg(ap, int);
162
163 if (darg < 0) {
164 ++len;
165 darg = -darg;
166 }
167
168 len += 4;
169
170 do {
171 ++len;
172 darg /= 10.0;
173 } while (0 != darg);
174 break;
175
176 case 'd':
177 default:
178 larg = va_arg(ap, int);
179
180 do {
181 ++len;
182 larg /= 10;
183 } while (0 != larg);
184 break;
185 }
186 }
187
188 default:
189 break;
190 }
191 }
192 }
193
194 return len;
195 #endif
196 }
197 #endif
198
199 int opal_asprintf(char **ptr, const char *fmt, ...)
200 {
201 int length;
202 va_list ap;
203
204 va_start(ap, fmt);
205
206 length = opal_vasprintf(ptr, fmt, ap);
207 va_end(ap);
208
209 return length;
210 }
211
212
213 int opal_vasprintf(char **ptr, const char *fmt, va_list ap)
214 {
215 #ifdef HAVE_VASPRINTF
216 int length;
217
218 length = vasprintf(ptr, fmt, ap);
219 if (length < 0) {
220 *ptr = NULL;
221 }
222
223 return length;
224 #else
225 int length;
226 va_list ap2;
227
228
229
230
231 #if OPAL_HAVE_VA_COPY
232 va_copy(ap2, ap);
233 #elif OPAL_HAVE_UNDERSCORE_VA_COPY
234 __va_copy(ap2, ap);
235 #else
236 memcpy (&ap2, &ap, sizeof(va_list));
237 #endif
238
239
240 length = guess_strlen(fmt, ap);
241
242
243 *ptr = (char *) malloc((size_t) length + 1);
244 if (NULL == *ptr) {
245 errno = ENOMEM;
246 va_end(ap2);
247 return -1;
248 }
249
250
251 length = vsprintf(*ptr, fmt, ap2);
252 #if OPAL_HAVE_VA_COPY || OPAL_HAVE_UNDERSCORE_VA_COPY
253 va_end(ap2);
254 #endif
255
256
257 *ptr = (char*) realloc(*ptr, (size_t) length + 1);
258 if (NULL == *ptr) {
259 errno = ENOMEM;
260 return -1;
261 }
262
263 return length;
264 #endif
265 }
266
267
268 int opal_snprintf(char *str, size_t size, const char *fmt, ...)
269 {
270 int length;
271 va_list ap;
272
273 va_start(ap, fmt);
274 length = opal_vsnprintf(str, size, fmt, ap);
275 va_end(ap);
276
277 return length;
278 }
279
280
281 int opal_vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
282 {
283 int length;
284 char *buf;
285
286 length = opal_vasprintf(&buf, fmt, ap);
287 if (length < 0) {
288 return length;
289 }
290
291
292 if (str) {
293 if ((size_t) length < size) {
294 strcpy(str, buf);
295 } else {
296 memcpy(str, buf, size - 1);
297 str[size] = '\0';
298 }
299 }
300
301
302 free(buf);
303
304 return length;
305 }
306
307
308 #ifdef TEST
309
310 int main(int argc, char *argv[])
311 {
312 char a[10];
313 char b[173];
314 char *s;
315 int length;
316
317 puts("test for NULL buffer in snprintf:");
318 length = opal_snprintf(NULL, 0, "this is a string %d", 1004);
319 printf("length = %d\n", length);
320
321 puts("test of snprintf to an undersize buffer:");
322 length = opal_snprintf(a, sizeof(a), "this is a string %d", 1004);
323 printf("string = %s\n", a);
324 printf("length = %d\n", length);
325 printf("strlen = %d\n", (int) strlen(a));
326
327 puts("test of snprintf to an oversize buffer:");
328 length = opal_snprintf(b, sizeof(b), "this is a string %d", 1004);
329 printf("string = %s\n", b);
330 printf("length = %d\n", length);
331 printf("strlen = %d\n", (int) strlen(b));
332
333 puts("test of asprintf:");
334 length = opal_asprintf(&s, "this is a string %d", 1004);
335 printf("string = %s\n", s);
336 printf("length = %d\n", length);
337 printf("strlen = %d\n", (int) strlen(s));
338
339 free(s);
340
341 return 0;
342 }
343
344 #endif