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