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