1*05b00f60SXin Li /*
2*05b00f60SXin Li * Copyright (c) 1995-1999 Kungliga Tekniska H�gskolan
3*05b00f60SXin Li * (Royal Institute of Technology, Stockholm, Sweden).
4*05b00f60SXin Li * All rights reserved.
5*05b00f60SXin Li *
6*05b00f60SXin Li * Redistribution and use in source and binary forms, with or without
7*05b00f60SXin Li * modification, are permitted provided that the following conditions
8*05b00f60SXin Li * are met:
9*05b00f60SXin Li *
10*05b00f60SXin Li * 1. Redistributions of source code must retain the above copyright
11*05b00f60SXin Li * notice, this list of conditions and the following disclaimer.
12*05b00f60SXin Li *
13*05b00f60SXin Li * 2. Redistributions in binary form must reproduce the above copyright
14*05b00f60SXin Li * notice, this list of conditions and the following disclaimer in the
15*05b00f60SXin Li * documentation and/or other materials provided with the distribution.
16*05b00f60SXin Li *
17*05b00f60SXin Li * 3. Neither the name of the Institute nor the names of its contributors
18*05b00f60SXin Li * may be used to endorse or promote products derived from this software
19*05b00f60SXin Li * without specific prior written permission.
20*05b00f60SXin Li *
21*05b00f60SXin Li * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22*05b00f60SXin Li * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*05b00f60SXin Li * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*05b00f60SXin Li * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25*05b00f60SXin Li * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*05b00f60SXin Li * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*05b00f60SXin Li * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*05b00f60SXin Li * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*05b00f60SXin Li * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*05b00f60SXin Li * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*05b00f60SXin Li * SUCH DAMAGE.
32*05b00f60SXin Li */
33*05b00f60SXin Li
34*05b00f60SXin Li #ifdef HAVE_CONFIG_H
35*05b00f60SXin Li #include <config.h>
36*05b00f60SXin Li #endif
37*05b00f60SXin Li
38*05b00f60SXin Li #include <stdio.h>
39*05b00f60SXin Li #include <stdarg.h>
40*05b00f60SXin Li #include <stdlib.h>
41*05b00f60SXin Li #include <string.h>
42*05b00f60SXin Li #include <ctype.h>
43*05b00f60SXin Li #include <sys/types.h>
44*05b00f60SXin Li
45*05b00f60SXin Li #include "netdissect.h"
46*05b00f60SXin Li
47*05b00f60SXin Li enum format_flags {
48*05b00f60SXin Li minus_flag = 1,
49*05b00f60SXin Li plus_flag = 2,
50*05b00f60SXin Li space_flag = 4,
51*05b00f60SXin Li alternate_flag = 8,
52*05b00f60SXin Li zero_flag = 16
53*05b00f60SXin Li };
54*05b00f60SXin Li
55*05b00f60SXin Li /*
56*05b00f60SXin Li * Common state
57*05b00f60SXin Li */
58*05b00f60SXin Li
59*05b00f60SXin Li struct state {
60*05b00f60SXin Li unsigned char *str;
61*05b00f60SXin Li unsigned char *s;
62*05b00f60SXin Li unsigned char *theend;
63*05b00f60SXin Li size_t sz;
64*05b00f60SXin Li size_t max_sz;
65*05b00f60SXin Li int (*append_char)(struct state *, unsigned char);
66*05b00f60SXin Li int (*reserve)(struct state *, size_t);
67*05b00f60SXin Li /* XXX - methods */
68*05b00f60SXin Li };
69*05b00f60SXin Li
70*05b00f60SXin Li #if 0
71*05b00f60SXin Li static int
72*05b00f60SXin Li as_reserve (struct state *state, size_t n)
73*05b00f60SXin Li {
74*05b00f60SXin Li if (state->s + n > state->theend) {
75*05b00f60SXin Li int off = state->s - state->str;
76*05b00f60SXin Li unsigned char *tmp;
77*05b00f60SXin Li
78*05b00f60SXin Li if (state->max_sz && state->sz >= state->max_sz)
79*05b00f60SXin Li return 1;
80*05b00f60SXin Li
81*05b00f60SXin Li state->sz = max(state->sz * 2, state->sz + n);
82*05b00f60SXin Li if (state->max_sz)
83*05b00f60SXin Li state->sz = min(state->sz, state->max_sz);
84*05b00f60SXin Li tmp = realloc (state->str, state->sz);
85*05b00f60SXin Li if (tmp == NULL)
86*05b00f60SXin Li return 1;
87*05b00f60SXin Li state->str = tmp;
88*05b00f60SXin Li state->s = state->str + off;
89*05b00f60SXin Li state->theend = state->str + state->sz - 1;
90*05b00f60SXin Li }
91*05b00f60SXin Li return 0;
92*05b00f60SXin Li }
93*05b00f60SXin Li
94*05b00f60SXin Li static int
95*05b00f60SXin Li as_append_char (struct state *state, unsigned char c)
96*05b00f60SXin Li {
97*05b00f60SXin Li if(as_reserve (state, 1))
98*05b00f60SXin Li return 1;
99*05b00f60SXin Li else {
100*05b00f60SXin Li *state->s++ = c;
101*05b00f60SXin Li return 0;
102*05b00f60SXin Li }
103*05b00f60SXin Li }
104*05b00f60SXin Li #endif
105*05b00f60SXin Li
106*05b00f60SXin Li static int
append_number(struct state * state,unsigned long num,unsigned base,char * rep,int width,int prec,int flags,int minusp)107*05b00f60SXin Li append_number(struct state *state,
108*05b00f60SXin Li unsigned long num, unsigned base, char *rep,
109*05b00f60SXin Li int width, int prec, int flags, int minusp)
110*05b00f60SXin Li {
111*05b00f60SXin Li int len = 0;
112*05b00f60SXin Li int i;
113*05b00f60SXin Li
114*05b00f60SXin Li /* given precision, ignore zero flag */
115*05b00f60SXin Li if(prec != -1)
116*05b00f60SXin Li flags &= ~zero_flag;
117*05b00f60SXin Li else
118*05b00f60SXin Li prec = 1;
119*05b00f60SXin Li /* zero value with zero precision -> "" */
120*05b00f60SXin Li if(prec == 0 && num == 0)
121*05b00f60SXin Li return 0;
122*05b00f60SXin Li do{
123*05b00f60SXin Li if((*state->append_char)(state, rep[num % base]))
124*05b00f60SXin Li return 1;
125*05b00f60SXin Li len++;
126*05b00f60SXin Li num /= base;
127*05b00f60SXin Li }while(num);
128*05b00f60SXin Li prec -= len;
129*05b00f60SXin Li /* pad with prec zeros */
130*05b00f60SXin Li while(prec-- > 0){
131*05b00f60SXin Li if((*state->append_char)(state, '0'))
132*05b00f60SXin Li return 1;
133*05b00f60SXin Li len++;
134*05b00f60SXin Li }
135*05b00f60SXin Li /* add length of alternate prefix (added later) to len */
136*05b00f60SXin Li if(flags & alternate_flag && (base == 16 || base == 8))
137*05b00f60SXin Li len += base / 8;
138*05b00f60SXin Li /* pad with zeros */
139*05b00f60SXin Li if(flags & zero_flag){
140*05b00f60SXin Li width -= len;
141*05b00f60SXin Li if(minusp || (flags & space_flag) || (flags & plus_flag))
142*05b00f60SXin Li width--;
143*05b00f60SXin Li while(width-- > 0){
144*05b00f60SXin Li if((*state->append_char)(state, '0'))
145*05b00f60SXin Li return 1;
146*05b00f60SXin Li len++;
147*05b00f60SXin Li }
148*05b00f60SXin Li }
149*05b00f60SXin Li /* add alternate prefix */
150*05b00f60SXin Li if(flags & alternate_flag && (base == 16 || base == 8)){
151*05b00f60SXin Li if(base == 16)
152*05b00f60SXin Li if((*state->append_char)(state, rep[10] + 23)) /* XXX */
153*05b00f60SXin Li return 1;
154*05b00f60SXin Li if((*state->append_char)(state, '0'))
155*05b00f60SXin Li return 1;
156*05b00f60SXin Li }
157*05b00f60SXin Li /* add sign */
158*05b00f60SXin Li if(minusp){
159*05b00f60SXin Li if((*state->append_char)(state, '-'))
160*05b00f60SXin Li return 1;
161*05b00f60SXin Li len++;
162*05b00f60SXin Li } else if(flags & plus_flag) {
163*05b00f60SXin Li if((*state->append_char)(state, '+'))
164*05b00f60SXin Li return 1;
165*05b00f60SXin Li len++;
166*05b00f60SXin Li } else if(flags & space_flag) {
167*05b00f60SXin Li if((*state->append_char)(state, ' '))
168*05b00f60SXin Li return 1;
169*05b00f60SXin Li len++;
170*05b00f60SXin Li }
171*05b00f60SXin Li if(flags & minus_flag)
172*05b00f60SXin Li /* swap before padding with spaces */
173*05b00f60SXin Li for(i = 0; i < len / 2; i++){
174*05b00f60SXin Li char c = state->s[-i-1];
175*05b00f60SXin Li state->s[-i-1] = state->s[-len+i];
176*05b00f60SXin Li state->s[-len+i] = c;
177*05b00f60SXin Li }
178*05b00f60SXin Li width -= len;
179*05b00f60SXin Li while(width-- > 0){
180*05b00f60SXin Li if((*state->append_char)(state, ' '))
181*05b00f60SXin Li return 1;
182*05b00f60SXin Li len++;
183*05b00f60SXin Li }
184*05b00f60SXin Li if(!(flags & minus_flag))
185*05b00f60SXin Li /* swap after padding with spaces */
186*05b00f60SXin Li for(i = 0; i < len / 2; i++){
187*05b00f60SXin Li char c = state->s[-i-1];
188*05b00f60SXin Li state->s[-i-1] = state->s[-len+i];
189*05b00f60SXin Li state->s[-len+i] = c;
190*05b00f60SXin Li }
191*05b00f60SXin Li
192*05b00f60SXin Li return 0;
193*05b00f60SXin Li }
194*05b00f60SXin Li
195*05b00f60SXin Li static int
append_string(struct state * state,unsigned char * arg,int width,int prec,int flags)196*05b00f60SXin Li append_string (struct state *state,
197*05b00f60SXin Li unsigned char *arg,
198*05b00f60SXin Li int width,
199*05b00f60SXin Li int prec,
200*05b00f60SXin Li int flags)
201*05b00f60SXin Li {
202*05b00f60SXin Li if(prec != -1)
203*05b00f60SXin Li width -= prec;
204*05b00f60SXin Li else
205*05b00f60SXin Li width -= strlen((char *)arg);
206*05b00f60SXin Li if(!(flags & minus_flag))
207*05b00f60SXin Li while(width-- > 0)
208*05b00f60SXin Li if((*state->append_char) (state, ' '))
209*05b00f60SXin Li return 1;
210*05b00f60SXin Li if (prec != -1) {
211*05b00f60SXin Li while (*arg && prec--)
212*05b00f60SXin Li if ((*state->append_char) (state, *arg++))
213*05b00f60SXin Li return 1;
214*05b00f60SXin Li } else {
215*05b00f60SXin Li while (*arg)
216*05b00f60SXin Li if ((*state->append_char) (state, *arg++))
217*05b00f60SXin Li return 1;
218*05b00f60SXin Li }
219*05b00f60SXin Li if(flags & minus_flag)
220*05b00f60SXin Li while(width-- > 0)
221*05b00f60SXin Li if((*state->append_char) (state, ' '))
222*05b00f60SXin Li return 1;
223*05b00f60SXin Li return 0;
224*05b00f60SXin Li }
225*05b00f60SXin Li
226*05b00f60SXin Li static int
append_char(struct state * state,unsigned char arg,int width,int flags)227*05b00f60SXin Li append_char(struct state *state,
228*05b00f60SXin Li unsigned char arg,
229*05b00f60SXin Li int width,
230*05b00f60SXin Li int flags)
231*05b00f60SXin Li {
232*05b00f60SXin Li while(!(flags & minus_flag) && --width > 0)
233*05b00f60SXin Li if((*state->append_char) (state, ' '))
234*05b00f60SXin Li return 1;
235*05b00f60SXin Li
236*05b00f60SXin Li if((*state->append_char) (state, arg))
237*05b00f60SXin Li return 1;
238*05b00f60SXin Li while((flags & minus_flag) && --width > 0)
239*05b00f60SXin Li if((*state->append_char) (state, ' '))
240*05b00f60SXin Li return 1;
241*05b00f60SXin Li
242*05b00f60SXin Li return 0;
243*05b00f60SXin Li }
244*05b00f60SXin Li
245*05b00f60SXin Li /*
246*05b00f60SXin Li * This can't be made into a function...
247*05b00f60SXin Li */
248*05b00f60SXin Li
249*05b00f60SXin Li #define PARSE_INT_FORMAT(res, arg, unsig) \
250*05b00f60SXin Li if (long_flag) \
251*05b00f60SXin Li res = (unsig long)va_arg(arg, unsig long); \
252*05b00f60SXin Li else if (short_flag) \
253*05b00f60SXin Li res = (unsig short)va_arg(arg, unsig int); \
254*05b00f60SXin Li else \
255*05b00f60SXin Li res = (unsig int)va_arg(arg, unsig int)
256*05b00f60SXin Li
257*05b00f60SXin Li /*
258*05b00f60SXin Li * zyxprintf - return 0 or -1
259*05b00f60SXin Li */
260*05b00f60SXin Li
261*05b00f60SXin Li static int
xyzprintf(struct state * state,const char * char_format,va_list ap)262*05b00f60SXin Li xyzprintf (struct state *state, const char *char_format, va_list ap)
263*05b00f60SXin Li {
264*05b00f60SXin Li const unsigned char *format = (const unsigned char *)char_format;
265*05b00f60SXin Li unsigned char c;
266*05b00f60SXin Li
267*05b00f60SXin Li while((c = *format++)) {
268*05b00f60SXin Li if (c == '%') {
269*05b00f60SXin Li int flags = 0;
270*05b00f60SXin Li int width = 0;
271*05b00f60SXin Li int prec = -1;
272*05b00f60SXin Li int long_flag = 0;
273*05b00f60SXin Li int short_flag = 0;
274*05b00f60SXin Li
275*05b00f60SXin Li /* flags */
276*05b00f60SXin Li while((c = *format++)){
277*05b00f60SXin Li if(c == '-')
278*05b00f60SXin Li flags |= minus_flag;
279*05b00f60SXin Li else if(c == '+')
280*05b00f60SXin Li flags |= plus_flag;
281*05b00f60SXin Li else if(c == ' ')
282*05b00f60SXin Li flags |= space_flag;
283*05b00f60SXin Li else if(c == '#')
284*05b00f60SXin Li flags |= alternate_flag;
285*05b00f60SXin Li else if(c == '0')
286*05b00f60SXin Li flags |= zero_flag;
287*05b00f60SXin Li else
288*05b00f60SXin Li break;
289*05b00f60SXin Li }
290*05b00f60SXin Li
291*05b00f60SXin Li if((flags & space_flag) && (flags & plus_flag))
292*05b00f60SXin Li flags ^= space_flag;
293*05b00f60SXin Li
294*05b00f60SXin Li if((flags & minus_flag) && (flags & zero_flag))
295*05b00f60SXin Li flags ^= zero_flag;
296*05b00f60SXin Li
297*05b00f60SXin Li /* width */
298*05b00f60SXin Li if (isdigit(c))
299*05b00f60SXin Li do {
300*05b00f60SXin Li width = width * 10 + c - '0';
301*05b00f60SXin Li c = *format++;
302*05b00f60SXin Li } while(isdigit(c));
303*05b00f60SXin Li else if(c == '*') {
304*05b00f60SXin Li width = va_arg(ap, int);
305*05b00f60SXin Li c = *format++;
306*05b00f60SXin Li }
307*05b00f60SXin Li
308*05b00f60SXin Li /* precision */
309*05b00f60SXin Li if (c == '.') {
310*05b00f60SXin Li prec = 0;
311*05b00f60SXin Li c = *format++;
312*05b00f60SXin Li if (isdigit(c))
313*05b00f60SXin Li do {
314*05b00f60SXin Li prec = prec * 10 + c - '0';
315*05b00f60SXin Li c = *format++;
316*05b00f60SXin Li } while(isdigit(c));
317*05b00f60SXin Li else if (c == '*') {
318*05b00f60SXin Li prec = va_arg(ap, int);
319*05b00f60SXin Li c = *format++;
320*05b00f60SXin Li }
321*05b00f60SXin Li }
322*05b00f60SXin Li
323*05b00f60SXin Li /* size */
324*05b00f60SXin Li
325*05b00f60SXin Li if (c == 'h') {
326*05b00f60SXin Li short_flag = 1;
327*05b00f60SXin Li c = *format++;
328*05b00f60SXin Li } else if (c == 'l') {
329*05b00f60SXin Li long_flag = 1;
330*05b00f60SXin Li c = *format++;
331*05b00f60SXin Li }
332*05b00f60SXin Li
333*05b00f60SXin Li switch (c) {
334*05b00f60SXin Li case 'c' :
335*05b00f60SXin Li if(append_char(state, va_arg(ap, int), width, flags))
336*05b00f60SXin Li return -1;
337*05b00f60SXin Li break;
338*05b00f60SXin Li case 's' :
339*05b00f60SXin Li if (append_string(state,
340*05b00f60SXin Li va_arg(ap, unsigned char*),
341*05b00f60SXin Li width,
342*05b00f60SXin Li prec,
343*05b00f60SXin Li flags))
344*05b00f60SXin Li return -1;
345*05b00f60SXin Li break;
346*05b00f60SXin Li case 'd' :
347*05b00f60SXin Li case 'i' : {
348*05b00f60SXin Li long arg;
349*05b00f60SXin Li unsigned long num;
350*05b00f60SXin Li int minusp = 0;
351*05b00f60SXin Li
352*05b00f60SXin Li PARSE_INT_FORMAT(arg, ap, signed);
353*05b00f60SXin Li
354*05b00f60SXin Li if (arg < 0) {
355*05b00f60SXin Li minusp = 1;
356*05b00f60SXin Li num = -arg;
357*05b00f60SXin Li } else
358*05b00f60SXin Li num = arg;
359*05b00f60SXin Li
360*05b00f60SXin Li if (append_number (state, num, 10, "0123456789",
361*05b00f60SXin Li width, prec, flags, minusp))
362*05b00f60SXin Li return -1;
363*05b00f60SXin Li break;
364*05b00f60SXin Li }
365*05b00f60SXin Li case 'u' : {
366*05b00f60SXin Li unsigned long arg;
367*05b00f60SXin Li
368*05b00f60SXin Li PARSE_INT_FORMAT(arg, ap, unsigned);
369*05b00f60SXin Li
370*05b00f60SXin Li if (append_number (state, arg, 10, "0123456789",
371*05b00f60SXin Li width, prec, flags, 0))
372*05b00f60SXin Li return -1;
373*05b00f60SXin Li break;
374*05b00f60SXin Li }
375*05b00f60SXin Li case 'o' : {
376*05b00f60SXin Li unsigned long arg;
377*05b00f60SXin Li
378*05b00f60SXin Li PARSE_INT_FORMAT(arg, ap, unsigned);
379*05b00f60SXin Li
380*05b00f60SXin Li if (append_number (state, arg, 010, "01234567",
381*05b00f60SXin Li width, prec, flags, 0))
382*05b00f60SXin Li return -1;
383*05b00f60SXin Li break;
384*05b00f60SXin Li }
385*05b00f60SXin Li case 'x' : {
386*05b00f60SXin Li unsigned long arg;
387*05b00f60SXin Li
388*05b00f60SXin Li PARSE_INT_FORMAT(arg, ap, unsigned);
389*05b00f60SXin Li
390*05b00f60SXin Li if (append_number (state, arg, 0x10, "0123456789abcdef",
391*05b00f60SXin Li width, prec, flags, 0))
392*05b00f60SXin Li return -1;
393*05b00f60SXin Li break;
394*05b00f60SXin Li }
395*05b00f60SXin Li case 'X' :{
396*05b00f60SXin Li unsigned long arg;
397*05b00f60SXin Li
398*05b00f60SXin Li PARSE_INT_FORMAT(arg, ap, unsigned);
399*05b00f60SXin Li
400*05b00f60SXin Li if (append_number (state, arg, 0x10, "0123456789ABCDEF",
401*05b00f60SXin Li width, prec, flags, 0))
402*05b00f60SXin Li return -1;
403*05b00f60SXin Li break;
404*05b00f60SXin Li }
405*05b00f60SXin Li case 'p' : {
406*05b00f60SXin Li unsigned long arg = (unsigned long)va_arg(ap, void*);
407*05b00f60SXin Li
408*05b00f60SXin Li if (append_number (state, arg, 0x10, "0123456789ABCDEF",
409*05b00f60SXin Li width, prec, flags, 0))
410*05b00f60SXin Li return -1;
411*05b00f60SXin Li break;
412*05b00f60SXin Li }
413*05b00f60SXin Li case 'n' : {
414*05b00f60SXin Li int *arg = va_arg(ap, int *);
415*05b00f60SXin Li *arg = state->s - state->str;
416*05b00f60SXin Li break;
417*05b00f60SXin Li }
418*05b00f60SXin Li case '\0' :
419*05b00f60SXin Li --format;
420*05b00f60SXin Li /* FALLTHROUGH */
421*05b00f60SXin Li case '%' :
422*05b00f60SXin Li if ((*state->append_char)(state, c))
423*05b00f60SXin Li return -1;
424*05b00f60SXin Li break;
425*05b00f60SXin Li default :
426*05b00f60SXin Li if ( (*state->append_char)(state, '%')
427*05b00f60SXin Li || (*state->append_char)(state, c))
428*05b00f60SXin Li return -1;
429*05b00f60SXin Li break;
430*05b00f60SXin Li }
431*05b00f60SXin Li } else
432*05b00f60SXin Li if ((*state->append_char) (state, c))
433*05b00f60SXin Li return -1;
434*05b00f60SXin Li }
435*05b00f60SXin Li return 0;
436*05b00f60SXin Li }
437*05b00f60SXin Li
438*05b00f60SXin Li #if 0
439*05b00f60SXin Li #ifndef HAVE_ASPRINTF
440*05b00f60SXin Li int
441*05b00f60SXin Li asprintf (char **ret, const char *format, ...)
442*05b00f60SXin Li {
443*05b00f60SXin Li va_list args;
444*05b00f60SXin Li int val;
445*05b00f60SXin Li
446*05b00f60SXin Li va_start(args, format);
447*05b00f60SXin Li val = vasprintf (ret, format, args);
448*05b00f60SXin Li
449*05b00f60SXin Li #ifdef PARANOIA
450*05b00f60SXin Li {
451*05b00f60SXin Li int ret2;
452*05b00f60SXin Li char *tmp;
453*05b00f60SXin Li tmp = malloc (val + 1);
454*05b00f60SXin Li if (tmp == NULL)
455*05b00f60SXin Li abort ();
456*05b00f60SXin Li
457*05b00f60SXin Li ret2 = vsprintf (tmp, format, args);
458*05b00f60SXin Li if (val != ret2 || strcmp(*ret, tmp))
459*05b00f60SXin Li abort ();
460*05b00f60SXin Li free (tmp);
461*05b00f60SXin Li }
462*05b00f60SXin Li #endif
463*05b00f60SXin Li
464*05b00f60SXin Li va_end(args);
465*05b00f60SXin Li return val;
466*05b00f60SXin Li }
467*05b00f60SXin Li #endif
468*05b00f60SXin Li
469*05b00f60SXin Li #ifndef HAVE_VASNPRINTF
470*05b00f60SXin Li int
471*05b00f60SXin Li nd_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
472*05b00f60SXin Li {
473*05b00f60SXin Li int st;
474*05b00f60SXin Li size_t len;
475*05b00f60SXin Li struct state state;
476*05b00f60SXin Li
477*05b00f60SXin Li state.max_sz = max_sz;
478*05b00f60SXin Li state.sz = 1;
479*05b00f60SXin Li state.str = malloc(state.sz);
480*05b00f60SXin Li if (state.str == NULL) {
481*05b00f60SXin Li *ret = NULL;
482*05b00f60SXin Li return -1;
483*05b00f60SXin Li }
484*05b00f60SXin Li state.s = state.str;
485*05b00f60SXin Li state.theend = state.s + state.sz - 1;
486*05b00f60SXin Li state.append_char = as_append_char;
487*05b00f60SXin Li state.reserve = as_reserve;
488*05b00f60SXin Li
489*05b00f60SXin Li st = xyzprintf (&state, format, args);
490*05b00f60SXin Li if (st) {
491*05b00f60SXin Li free (state.str);
492*05b00f60SXin Li *ret = NULL;
493*05b00f60SXin Li return -1;
494*05b00f60SXin Li } else {
495*05b00f60SXin Li char *tmp;
496*05b00f60SXin Li
497*05b00f60SXin Li *state.s = '\0';
498*05b00f60SXin Li len = state.s - state.str;
499*05b00f60SXin Li tmp = realloc (state.str, len+1);
500*05b00f60SXin Li if (tmp == NULL) {
501*05b00f60SXin Li free (state.str);
502*05b00f60SXin Li *ret = NULL;
503*05b00f60SXin Li return -1;
504*05b00f60SXin Li }
505*05b00f60SXin Li *ret = tmp;
506*05b00f60SXin Li return len;
507*05b00f60SXin Li }
508*05b00f60SXin Li }
509*05b00f60SXin Li #endif
510*05b00f60SXin Li #endif
511