xref: /freebsd/contrib/tcpdump/missing/snprintf.c (revision a90e161be323456b08b7fe13acb201536809510f)
1685295f4SBill Fenner /*
2685295f4SBill Fenner  * Copyright (c) 1995-1999 Kungliga Tekniska H�gskolan
3685295f4SBill Fenner  * (Royal Institute of Technology, Stockholm, Sweden).
4685295f4SBill Fenner  * All rights reserved.
5685295f4SBill Fenner  *
6685295f4SBill Fenner  * Redistribution and use in source and binary forms, with or without
7685295f4SBill Fenner  * modification, are permitted provided that the following conditions
8685295f4SBill Fenner  * are met:
9685295f4SBill Fenner  *
10685295f4SBill Fenner  * 1. Redistributions of source code must retain the above copyright
11685295f4SBill Fenner  *    notice, this list of conditions and the following disclaimer.
12685295f4SBill Fenner  *
13685295f4SBill Fenner  * 2. Redistributions in binary form must reproduce the above copyright
14685295f4SBill Fenner  *    notice, this list of conditions and the following disclaimer in the
15685295f4SBill Fenner  *    documentation and/or other materials provided with the distribution.
16685295f4SBill Fenner  *
17685295f4SBill Fenner  * 3. Neither the name of the Institute nor the names of its contributors
18685295f4SBill Fenner  *    may be used to endorse or promote products derived from this software
19685295f4SBill Fenner  *    without specific prior written permission.
20685295f4SBill Fenner  *
21685295f4SBill Fenner  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22685295f4SBill Fenner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23685295f4SBill Fenner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24685295f4SBill Fenner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25685295f4SBill Fenner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26685295f4SBill Fenner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27685295f4SBill Fenner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28685295f4SBill Fenner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29685295f4SBill Fenner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30685295f4SBill Fenner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31685295f4SBill Fenner  * SUCH DAMAGE.
32685295f4SBill Fenner  */
33685295f4SBill Fenner 
34a90e161bSBill Fenner /* $Id: snprintf.c,v 1.5 2001/01/12 10:14:40 guy Exp $ */
35685295f4SBill Fenner 
36685295f4SBill Fenner #ifdef HAVE_CONFIG_H
37685295f4SBill Fenner #include <config.h>
38685295f4SBill Fenner #endif
39685295f4SBill Fenner 
40685295f4SBill Fenner #ifndef lint
41685295f4SBill Fenner static const char rcsid[] =
42a90e161bSBill Fenner      "@(#) $Header: /tcpdump/master/tcpdump/missing/snprintf.c,v 1.5 2001/01/12 10:14:40 guy Exp $";
43685295f4SBill Fenner #endif
44685295f4SBill Fenner 
45685295f4SBill Fenner #include <stdio.h>
46685295f4SBill Fenner #include <stdarg.h>
47685295f4SBill Fenner #include <stdlib.h>
48685295f4SBill Fenner #include <string.h>
49685295f4SBill Fenner #include <ctype.h>
50685295f4SBill Fenner #include <sys/types.h>
51685295f4SBill Fenner 
52685295f4SBill Fenner #include <interface.h>
53685295f4SBill Fenner 
54685295f4SBill Fenner enum format_flags {
55685295f4SBill Fenner     minus_flag     =  1,
56685295f4SBill Fenner     plus_flag      =  2,
57685295f4SBill Fenner     space_flag     =  4,
58685295f4SBill Fenner     alternate_flag =  8,
59685295f4SBill Fenner     zero_flag      = 16
60685295f4SBill Fenner };
61685295f4SBill Fenner 
62685295f4SBill Fenner /*
63685295f4SBill Fenner  * Common state
64685295f4SBill Fenner  */
65685295f4SBill Fenner 
66685295f4SBill Fenner struct state {
67685295f4SBill Fenner   unsigned char *str;
68685295f4SBill Fenner   unsigned char *s;
69685295f4SBill Fenner   unsigned char *theend;
70685295f4SBill Fenner   size_t sz;
71685295f4SBill Fenner   size_t max_sz;
72685295f4SBill Fenner   int (*append_char)(struct state *, unsigned char);
73685295f4SBill Fenner   int (*reserve)(struct state *, size_t);
74685295f4SBill Fenner   /* XXX - methods */
75685295f4SBill Fenner };
76685295f4SBill Fenner 
77685295f4SBill Fenner #ifndef HAVE_VSNPRINTF
78685295f4SBill Fenner static int
79685295f4SBill Fenner sn_reserve (struct state *state, size_t n)
80685295f4SBill Fenner {
81685295f4SBill Fenner   return state->s + n > state->theend;
82685295f4SBill Fenner }
83685295f4SBill Fenner 
84685295f4SBill Fenner static int
85685295f4SBill Fenner sn_append_char (struct state *state, unsigned char c)
86685295f4SBill Fenner {
87685295f4SBill Fenner   if (sn_reserve (state, 1)) {
88685295f4SBill Fenner     return 1;
89685295f4SBill Fenner   } else {
90685295f4SBill Fenner     *state->s++ = c;
91685295f4SBill Fenner     return 0;
92685295f4SBill Fenner   }
93685295f4SBill Fenner }
94685295f4SBill Fenner #endif
95685295f4SBill Fenner 
96a90e161bSBill Fenner #if 0
97685295f4SBill Fenner static int
98685295f4SBill Fenner as_reserve (struct state *state, size_t n)
99685295f4SBill Fenner {
100685295f4SBill Fenner   if (state->s + n > state->theend) {
101685295f4SBill Fenner     int off = state->s - state->str;
102685295f4SBill Fenner     unsigned char *tmp;
103685295f4SBill Fenner 
104685295f4SBill Fenner     if (state->max_sz && state->sz >= state->max_sz)
105685295f4SBill Fenner       return 1;
106685295f4SBill Fenner 
107685295f4SBill Fenner     state->sz = max(state->sz * 2, state->sz + n);
108685295f4SBill Fenner     if (state->max_sz)
109685295f4SBill Fenner       state->sz = min(state->sz, state->max_sz);
110685295f4SBill Fenner     tmp = realloc (state->str, state->sz);
111685295f4SBill Fenner     if (tmp == NULL)
112685295f4SBill Fenner       return 1;
113685295f4SBill Fenner     state->str = tmp;
114685295f4SBill Fenner     state->s = state->str + off;
115685295f4SBill Fenner     state->theend = state->str + state->sz - 1;
116685295f4SBill Fenner   }
117685295f4SBill Fenner   return 0;
118685295f4SBill Fenner }
119685295f4SBill Fenner 
120685295f4SBill Fenner static int
121685295f4SBill Fenner as_append_char (struct state *state, unsigned char c)
122685295f4SBill Fenner {
123685295f4SBill Fenner   if(as_reserve (state, 1))
124685295f4SBill Fenner     return 1;
125685295f4SBill Fenner   else {
126685295f4SBill Fenner     *state->s++ = c;
127685295f4SBill Fenner     return 0;
128685295f4SBill Fenner   }
129685295f4SBill Fenner }
130a90e161bSBill Fenner #endif
131685295f4SBill Fenner 
132685295f4SBill Fenner static int
133685295f4SBill Fenner append_number(struct state *state,
134685295f4SBill Fenner 	      unsigned long num, unsigned base, char *rep,
135685295f4SBill Fenner 	      int width, int prec, int flags, int minusp)
136685295f4SBill Fenner {
137685295f4SBill Fenner   int len = 0;
138685295f4SBill Fenner   int i;
139685295f4SBill Fenner 
140685295f4SBill Fenner   /* given precision, ignore zero flag */
141685295f4SBill Fenner   if(prec != -1)
142685295f4SBill Fenner     flags &= ~zero_flag;
143685295f4SBill Fenner   else
144685295f4SBill Fenner     prec = 1;
145685295f4SBill Fenner   /* zero value with zero precision -> "" */
146685295f4SBill Fenner   if(prec == 0 && num == 0)
147685295f4SBill Fenner     return 0;
148685295f4SBill Fenner   do{
149685295f4SBill Fenner     if((*state->append_char)(state, rep[num % base]))
150685295f4SBill Fenner       return 1;
151685295f4SBill Fenner     len++;
152685295f4SBill Fenner     num /= base;
153685295f4SBill Fenner   }while(num);
154685295f4SBill Fenner   prec -= len;
155685295f4SBill Fenner   /* pad with prec zeros */
156685295f4SBill Fenner   while(prec-- > 0){
157685295f4SBill Fenner     if((*state->append_char)(state, '0'))
158685295f4SBill Fenner       return 1;
159685295f4SBill Fenner     len++;
160685295f4SBill Fenner   }
161685295f4SBill Fenner   /* add length of alternate prefix (added later) to len */
162685295f4SBill Fenner   if(flags & alternate_flag && (base == 16 || base == 8))
163685295f4SBill Fenner     len += base / 8;
164685295f4SBill Fenner   /* pad with zeros */
165685295f4SBill Fenner   if(flags & zero_flag){
166685295f4SBill Fenner     width -= len;
167685295f4SBill Fenner     if(minusp || (flags & space_flag) || (flags & plus_flag))
168685295f4SBill Fenner       width--;
169685295f4SBill Fenner     while(width-- > 0){
170685295f4SBill Fenner       if((*state->append_char)(state, '0'))
171685295f4SBill Fenner 	return 1;
172685295f4SBill Fenner       len++;
173685295f4SBill Fenner     }
174685295f4SBill Fenner   }
175685295f4SBill Fenner   /* add alternate prefix */
176685295f4SBill Fenner   if(flags & alternate_flag && (base == 16 || base == 8)){
177685295f4SBill Fenner     if(base == 16)
178685295f4SBill Fenner       if((*state->append_char)(state, rep[10] + 23)) /* XXX */
179685295f4SBill Fenner 	return 1;
180685295f4SBill Fenner     if((*state->append_char)(state, '0'))
181685295f4SBill Fenner       return 1;
182685295f4SBill Fenner   }
183685295f4SBill Fenner   /* add sign */
184685295f4SBill Fenner   if(minusp){
185685295f4SBill Fenner     if((*state->append_char)(state, '-'))
186685295f4SBill Fenner       return 1;
187685295f4SBill Fenner     len++;
188685295f4SBill Fenner   } else if(flags & plus_flag) {
189685295f4SBill Fenner     if((*state->append_char)(state, '+'))
190685295f4SBill Fenner       return 1;
191685295f4SBill Fenner     len++;
192685295f4SBill Fenner   } else if(flags & space_flag) {
193685295f4SBill Fenner     if((*state->append_char)(state, ' '))
194685295f4SBill Fenner       return 1;
195685295f4SBill Fenner     len++;
196685295f4SBill Fenner   }
197685295f4SBill Fenner   if(flags & minus_flag)
198685295f4SBill Fenner     /* swap before padding with spaces */
199685295f4SBill Fenner     for(i = 0; i < len / 2; i++){
200685295f4SBill Fenner       char c = state->s[-i-1];
201685295f4SBill Fenner       state->s[-i-1] = state->s[-len+i];
202685295f4SBill Fenner       state->s[-len+i] = c;
203685295f4SBill Fenner     }
204685295f4SBill Fenner   width -= len;
205685295f4SBill Fenner   while(width-- > 0){
206685295f4SBill Fenner     if((*state->append_char)(state,  ' '))
207685295f4SBill Fenner       return 1;
208685295f4SBill Fenner     len++;
209685295f4SBill Fenner   }
210685295f4SBill Fenner   if(!(flags & minus_flag))
211685295f4SBill Fenner     /* swap after padding with spaces */
212685295f4SBill Fenner     for(i = 0; i < len / 2; i++){
213685295f4SBill Fenner       char c = state->s[-i-1];
214685295f4SBill Fenner       state->s[-i-1] = state->s[-len+i];
215685295f4SBill Fenner       state->s[-len+i] = c;
216685295f4SBill Fenner     }
217685295f4SBill Fenner 
218685295f4SBill Fenner   return 0;
219685295f4SBill Fenner }
220685295f4SBill Fenner 
221685295f4SBill Fenner static int
222685295f4SBill Fenner append_string (struct state *state,
223685295f4SBill Fenner 	       unsigned char *arg,
224685295f4SBill Fenner 	       int width,
225685295f4SBill Fenner 	       int prec,
226685295f4SBill Fenner 	       int flags)
227685295f4SBill Fenner {
228685295f4SBill Fenner   if(prec != -1)
229685295f4SBill Fenner     width -= prec;
230685295f4SBill Fenner   else
231685295f4SBill Fenner     width -= strlen((char *)arg);
232685295f4SBill Fenner   if(!(flags & minus_flag))
233685295f4SBill Fenner     while(width-- > 0)
234685295f4SBill Fenner       if((*state->append_char) (state, ' '))
235685295f4SBill Fenner 	return 1;
236685295f4SBill Fenner   if (prec != -1) {
237685295f4SBill Fenner     while (*arg && prec--)
238685295f4SBill Fenner       if ((*state->append_char) (state, *arg++))
239685295f4SBill Fenner 	return 1;
240685295f4SBill Fenner   } else {
241685295f4SBill Fenner     while (*arg)
242685295f4SBill Fenner       if ((*state->append_char) (state, *arg++))
243685295f4SBill Fenner 	return 1;
244685295f4SBill Fenner   }
245685295f4SBill Fenner   if(flags & minus_flag)
246685295f4SBill Fenner     while(width-- > 0)
247685295f4SBill Fenner       if((*state->append_char) (state, ' '))
248685295f4SBill Fenner 	return 1;
249685295f4SBill Fenner   return 0;
250685295f4SBill Fenner }
251685295f4SBill Fenner 
252685295f4SBill Fenner static int
253685295f4SBill Fenner append_char(struct state *state,
254685295f4SBill Fenner 	    unsigned char arg,
255685295f4SBill Fenner 	    int width,
256685295f4SBill Fenner 	    int flags)
257685295f4SBill Fenner {
258685295f4SBill Fenner   while(!(flags & minus_flag) && --width > 0)
259685295f4SBill Fenner     if((*state->append_char) (state, ' '))
260685295f4SBill Fenner       return 1;
261685295f4SBill Fenner 
262685295f4SBill Fenner   if((*state->append_char) (state, arg))
263685295f4SBill Fenner     return 1;
264685295f4SBill Fenner   while((flags & minus_flag) && --width > 0)
265685295f4SBill Fenner     if((*state->append_char) (state, ' '))
266685295f4SBill Fenner       return 1;
267685295f4SBill Fenner 
268685295f4SBill Fenner   return 0;
269685295f4SBill Fenner }
270685295f4SBill Fenner 
271685295f4SBill Fenner /*
272685295f4SBill Fenner  * This can't be made into a function...
273685295f4SBill Fenner  */
274685295f4SBill Fenner 
275685295f4SBill Fenner #define PARSE_INT_FORMAT(res, arg, unsig) \
276685295f4SBill Fenner if (long_flag) \
277685295f4SBill Fenner      res = (unsig long)va_arg(arg, unsig long); \
278685295f4SBill Fenner else if (short_flag) \
279685295f4SBill Fenner      res = (unsig short)va_arg(arg, unsig int); \
280685295f4SBill Fenner else \
281685295f4SBill Fenner      res = (unsig int)va_arg(arg, unsig int)
282685295f4SBill Fenner 
283685295f4SBill Fenner /*
284685295f4SBill Fenner  * zyxprintf - return 0 or -1
285685295f4SBill Fenner  */
286685295f4SBill Fenner 
287685295f4SBill Fenner static int
288685295f4SBill Fenner xyzprintf (struct state *state, const char *char_format, va_list ap)
289685295f4SBill Fenner {
290685295f4SBill Fenner   const unsigned char *format = (const unsigned char *)char_format;
291685295f4SBill Fenner   unsigned char c;
292685295f4SBill Fenner 
293685295f4SBill Fenner   while((c = *format++)) {
294685295f4SBill Fenner     if (c == '%') {
295685295f4SBill Fenner       int flags      = 0;
296685295f4SBill Fenner       int width      = 0;
297685295f4SBill Fenner       int prec       = -1;
298685295f4SBill Fenner       int long_flag  = 0;
299685295f4SBill Fenner       int short_flag = 0;
300685295f4SBill Fenner 
301685295f4SBill Fenner       /* flags */
302685295f4SBill Fenner       while((c = *format++)){
303685295f4SBill Fenner 	if(c == '-')
304685295f4SBill Fenner 	  flags |= minus_flag;
305685295f4SBill Fenner 	else if(c == '+')
306685295f4SBill Fenner 	  flags |= plus_flag;
307685295f4SBill Fenner 	else if(c == ' ')
308685295f4SBill Fenner 	  flags |= space_flag;
309685295f4SBill Fenner 	else if(c == '#')
310685295f4SBill Fenner 	  flags |= alternate_flag;
311685295f4SBill Fenner 	else if(c == '0')
312685295f4SBill Fenner 	  flags |= zero_flag;
313685295f4SBill Fenner 	else
314685295f4SBill Fenner 	  break;
315685295f4SBill Fenner       }
316685295f4SBill Fenner 
317685295f4SBill Fenner       if((flags & space_flag) && (flags & plus_flag))
318685295f4SBill Fenner 	flags ^= space_flag;
319685295f4SBill Fenner 
320685295f4SBill Fenner       if((flags & minus_flag) && (flags & zero_flag))
321685295f4SBill Fenner 	flags ^= zero_flag;
322685295f4SBill Fenner 
323685295f4SBill Fenner       /* width */
324685295f4SBill Fenner       if (isdigit(c))
325685295f4SBill Fenner 	do {
326685295f4SBill Fenner 	  width = width * 10 + c - '0';
327685295f4SBill Fenner 	  c = *format++;
328685295f4SBill Fenner 	} while(isdigit(c));
329685295f4SBill Fenner       else if(c == '*') {
330685295f4SBill Fenner 	width = va_arg(ap, int);
331685295f4SBill Fenner 	c = *format++;
332685295f4SBill Fenner       }
333685295f4SBill Fenner 
334685295f4SBill Fenner       /* precision */
335685295f4SBill Fenner       if (c == '.') {
336685295f4SBill Fenner 	prec = 0;
337685295f4SBill Fenner 	c = *format++;
338685295f4SBill Fenner 	if (isdigit(c))
339685295f4SBill Fenner 	  do {
340685295f4SBill Fenner 	    prec = prec * 10 + c - '0';
341685295f4SBill Fenner 	    c = *format++;
342685295f4SBill Fenner 	  } while(isdigit(c));
343685295f4SBill Fenner 	else if (c == '*') {
344685295f4SBill Fenner 	  prec = va_arg(ap, int);
345685295f4SBill Fenner 	  c = *format++;
346685295f4SBill Fenner 	}
347685295f4SBill Fenner       }
348685295f4SBill Fenner 
349685295f4SBill Fenner       /* size */
350685295f4SBill Fenner 
351685295f4SBill Fenner       if (c == 'h') {
352685295f4SBill Fenner 	short_flag = 1;
353685295f4SBill Fenner 	c = *format++;
354685295f4SBill Fenner       } else if (c == 'l') {
355685295f4SBill Fenner 	long_flag = 1;
356685295f4SBill Fenner 	c = *format++;
357685295f4SBill Fenner       }
358685295f4SBill Fenner 
359685295f4SBill Fenner       switch (c) {
360685295f4SBill Fenner       case 'c' :
361685295f4SBill Fenner 	if(append_char(state, va_arg(ap, int), width, flags))
362685295f4SBill Fenner 	  return -1;
363685295f4SBill Fenner 	break;
364685295f4SBill Fenner       case 's' :
365685295f4SBill Fenner 	if (append_string(state,
366685295f4SBill Fenner 			  va_arg(ap, unsigned char*),
367685295f4SBill Fenner 			  width,
368685295f4SBill Fenner 			  prec,
369685295f4SBill Fenner 			  flags))
370685295f4SBill Fenner 	  return -1;
371685295f4SBill Fenner 	break;
372685295f4SBill Fenner       case 'd' :
373685295f4SBill Fenner       case 'i' : {
374685295f4SBill Fenner 	long arg;
375685295f4SBill Fenner 	unsigned long num;
376685295f4SBill Fenner 	int minusp = 0;
377685295f4SBill Fenner 
378685295f4SBill Fenner 	PARSE_INT_FORMAT(arg, ap, signed);
379685295f4SBill Fenner 
380685295f4SBill Fenner 	if (arg < 0) {
381685295f4SBill Fenner 	  minusp = 1;
382685295f4SBill Fenner 	  num = -arg;
383685295f4SBill Fenner 	} else
384685295f4SBill Fenner 	  num = arg;
385685295f4SBill Fenner 
386685295f4SBill Fenner 	if (append_number (state, num, 10, "0123456789",
387685295f4SBill Fenner 			   width, prec, flags, minusp))
388685295f4SBill Fenner 	  return -1;
389685295f4SBill Fenner 	break;
390685295f4SBill Fenner       }
391685295f4SBill Fenner       case 'u' : {
392685295f4SBill Fenner 	unsigned long arg;
393685295f4SBill Fenner 
394685295f4SBill Fenner 	PARSE_INT_FORMAT(arg, ap, unsigned);
395685295f4SBill Fenner 
396685295f4SBill Fenner 	if (append_number (state, arg, 10, "0123456789",
397685295f4SBill Fenner 			   width, prec, flags, 0))
398685295f4SBill Fenner 	  return -1;
399685295f4SBill Fenner 	break;
400685295f4SBill Fenner       }
401685295f4SBill Fenner       case 'o' : {
402685295f4SBill Fenner 	unsigned long arg;
403685295f4SBill Fenner 
404685295f4SBill Fenner 	PARSE_INT_FORMAT(arg, ap, unsigned);
405685295f4SBill Fenner 
406685295f4SBill Fenner 	if (append_number (state, arg, 010, "01234567",
407685295f4SBill Fenner 			   width, prec, flags, 0))
408685295f4SBill Fenner 	  return -1;
409685295f4SBill Fenner 	break;
410685295f4SBill Fenner       }
411685295f4SBill Fenner       case 'x' : {
412685295f4SBill Fenner 	unsigned long arg;
413685295f4SBill Fenner 
414685295f4SBill Fenner 	PARSE_INT_FORMAT(arg, ap, unsigned);
415685295f4SBill Fenner 
416685295f4SBill Fenner 	if (append_number (state, arg, 0x10, "0123456789abcdef",
417685295f4SBill Fenner 			   width, prec, flags, 0))
418685295f4SBill Fenner 	  return -1;
419685295f4SBill Fenner 	break;
420685295f4SBill Fenner       }
421685295f4SBill Fenner       case 'X' :{
422685295f4SBill Fenner 	unsigned long arg;
423685295f4SBill Fenner 
424685295f4SBill Fenner 	PARSE_INT_FORMAT(arg, ap, unsigned);
425685295f4SBill Fenner 
426685295f4SBill Fenner 	if (append_number (state, arg, 0x10, "0123456789ABCDEF",
427685295f4SBill Fenner 			   width, prec, flags, 0))
428685295f4SBill Fenner 	  return -1;
429685295f4SBill Fenner 	break;
430685295f4SBill Fenner       }
431685295f4SBill Fenner       case 'p' : {
432685295f4SBill Fenner 	unsigned long arg = (unsigned long)va_arg(ap, void*);
433685295f4SBill Fenner 
434685295f4SBill Fenner 	if (append_number (state, arg, 0x10, "0123456789ABCDEF",
435685295f4SBill Fenner 			   width, prec, flags, 0))
436685295f4SBill Fenner 	  return -1;
437685295f4SBill Fenner 	break;
438685295f4SBill Fenner       }
439685295f4SBill Fenner       case 'n' : {
440685295f4SBill Fenner 	int *arg = va_arg(ap, int*);
441685295f4SBill Fenner 	*arg = state->s - state->str;
442685295f4SBill Fenner 	break;
443685295f4SBill Fenner       }
444685295f4SBill Fenner       case '\0' :
445685295f4SBill Fenner 	  --format;
446685295f4SBill Fenner 	  /* FALLTHROUGH */
447685295f4SBill Fenner       case '%' :
448685295f4SBill Fenner 	if ((*state->append_char)(state, c))
449685295f4SBill Fenner 	  return -1;
450685295f4SBill Fenner 	break;
451685295f4SBill Fenner       default :
452685295f4SBill Fenner 	if (   (*state->append_char)(state, '%')
453685295f4SBill Fenner 	    || (*state->append_char)(state, c))
454685295f4SBill Fenner 	  return -1;
455685295f4SBill Fenner 	break;
456685295f4SBill Fenner       }
457685295f4SBill Fenner     } else
458685295f4SBill Fenner       if ((*state->append_char) (state, c))
459685295f4SBill Fenner 	return -1;
460685295f4SBill Fenner   }
461685295f4SBill Fenner   return 0;
462685295f4SBill Fenner }
463685295f4SBill Fenner 
464685295f4SBill Fenner #ifndef HAVE_SNPRINTF
465685295f4SBill Fenner int
466685295f4SBill Fenner snprintf (char *str, size_t sz, const char *format, ...)
467685295f4SBill Fenner {
468685295f4SBill Fenner   va_list args;
469685295f4SBill Fenner   int ret;
470685295f4SBill Fenner 
471685295f4SBill Fenner   va_start(args, format);
472685295f4SBill Fenner   ret = vsnprintf (str, sz, format, args);
473685295f4SBill Fenner 
474685295f4SBill Fenner #ifdef PARANOIA
475685295f4SBill Fenner   {
476685295f4SBill Fenner     int ret2;
477685295f4SBill Fenner     char *tmp;
478685295f4SBill Fenner 
479685295f4SBill Fenner     tmp = malloc (sz);
480685295f4SBill Fenner     if (tmp == NULL)
481685295f4SBill Fenner       abort ();
482685295f4SBill Fenner 
483685295f4SBill Fenner     ret2 = vsprintf (tmp, format, args);
484685295f4SBill Fenner     if (ret != ret2 || strcmp(str, tmp))
485685295f4SBill Fenner       abort ();
486685295f4SBill Fenner     free (tmp);
487685295f4SBill Fenner   }
488685295f4SBill Fenner #endif
489685295f4SBill Fenner 
490685295f4SBill Fenner   va_end(args);
491685295f4SBill Fenner   return ret;
492685295f4SBill Fenner }
493685295f4SBill Fenner #endif
494685295f4SBill Fenner 
495a90e161bSBill Fenner #if 0
496685295f4SBill Fenner #ifndef HAVE_ASPRINTF
497685295f4SBill Fenner int
498685295f4SBill Fenner asprintf (char **ret, const char *format, ...)
499685295f4SBill Fenner {
500685295f4SBill Fenner   va_list args;
501685295f4SBill Fenner   int val;
502685295f4SBill Fenner 
503685295f4SBill Fenner   va_start(args, format);
504685295f4SBill Fenner   val = vasprintf (ret, format, args);
505685295f4SBill Fenner 
506685295f4SBill Fenner #ifdef PARANOIA
507685295f4SBill Fenner   {
508685295f4SBill Fenner     int ret2;
509685295f4SBill Fenner     char *tmp;
510685295f4SBill Fenner     tmp = malloc (val + 1);
511685295f4SBill Fenner     if (tmp == NULL)
512685295f4SBill Fenner       abort ();
513685295f4SBill Fenner 
514685295f4SBill Fenner     ret2 = vsprintf (tmp, format, args);
515685295f4SBill Fenner     if (val != ret2 || strcmp(*ret, tmp))
516685295f4SBill Fenner       abort ();
517685295f4SBill Fenner     free (tmp);
518685295f4SBill Fenner   }
519685295f4SBill Fenner #endif
520685295f4SBill Fenner 
521685295f4SBill Fenner   va_end(args);
522685295f4SBill Fenner   return val;
523685295f4SBill Fenner }
524685295f4SBill Fenner #endif
525685295f4SBill Fenner 
526685295f4SBill Fenner #ifndef HAVE_ASNPRINTF
527685295f4SBill Fenner int
528685295f4SBill Fenner asnprintf (char **ret, size_t max_sz, const char *format, ...)
529685295f4SBill Fenner {
530685295f4SBill Fenner   va_list args;
531685295f4SBill Fenner   int val;
532685295f4SBill Fenner 
533685295f4SBill Fenner   va_start(args, format);
534685295f4SBill Fenner   val = vasnprintf (ret, max_sz, format, args);
535685295f4SBill Fenner 
536685295f4SBill Fenner #ifdef PARANOIA
537685295f4SBill Fenner   {
538685295f4SBill Fenner     int ret2;
539685295f4SBill Fenner     char *tmp;
540685295f4SBill Fenner     tmp = malloc (val + 1);
541685295f4SBill Fenner     if (tmp == NULL)
542685295f4SBill Fenner       abort ();
543685295f4SBill Fenner 
544685295f4SBill Fenner     ret2 = vsprintf (tmp, format, args);
545685295f4SBill Fenner     if (val != ret2 || strcmp(*ret, tmp))
546685295f4SBill Fenner       abort ();
547685295f4SBill Fenner     free (tmp);
548685295f4SBill Fenner   }
549685295f4SBill Fenner #endif
550685295f4SBill Fenner 
551685295f4SBill Fenner   va_end(args);
552685295f4SBill Fenner   return val;
553685295f4SBill Fenner }
554685295f4SBill Fenner #endif
555685295f4SBill Fenner 
556685295f4SBill Fenner #ifndef HAVE_VASPRINTF
557685295f4SBill Fenner int
558685295f4SBill Fenner vasprintf (char **ret, const char *format, va_list args)
559685295f4SBill Fenner {
560685295f4SBill Fenner   return vasnprintf (ret, 0, format, args);
561685295f4SBill Fenner }
562685295f4SBill Fenner #endif
563685295f4SBill Fenner 
564685295f4SBill Fenner 
565685295f4SBill Fenner #ifndef HAVE_VASNPRINTF
566685295f4SBill Fenner int
567685295f4SBill Fenner vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
568685295f4SBill Fenner {
569685295f4SBill Fenner   int st;
570685295f4SBill Fenner   size_t len;
571685295f4SBill Fenner   struct state state;
572685295f4SBill Fenner 
573685295f4SBill Fenner   state.max_sz = max_sz;
574685295f4SBill Fenner   state.sz     = 1;
575685295f4SBill Fenner   state.str    = malloc(state.sz);
576685295f4SBill Fenner   if (state.str == NULL) {
577685295f4SBill Fenner     *ret = NULL;
578685295f4SBill Fenner     return -1;
579685295f4SBill Fenner   }
580685295f4SBill Fenner   state.s = state.str;
581685295f4SBill Fenner   state.theend = state.s + state.sz - 1;
582685295f4SBill Fenner   state.append_char = as_append_char;
583685295f4SBill Fenner   state.reserve     = as_reserve;
584685295f4SBill Fenner 
585685295f4SBill Fenner   st = xyzprintf (&state, format, args);
586685295f4SBill Fenner   if (st) {
587685295f4SBill Fenner     free (state.str);
588685295f4SBill Fenner     *ret = NULL;
589685295f4SBill Fenner     return -1;
590685295f4SBill Fenner   } else {
591685295f4SBill Fenner     char *tmp;
592685295f4SBill Fenner 
593685295f4SBill Fenner     *state.s = '\0';
594685295f4SBill Fenner     len = state.s - state.str;
595685295f4SBill Fenner     tmp = realloc (state.str, len+1);
596685295f4SBill Fenner     if (tmp == NULL) {
597685295f4SBill Fenner       free (state.str);
598685295f4SBill Fenner       *ret = NULL;
599685295f4SBill Fenner       return -1;
600685295f4SBill Fenner     }
601685295f4SBill Fenner     *ret = tmp;
602685295f4SBill Fenner     return len;
603685295f4SBill Fenner   }
604685295f4SBill Fenner }
605685295f4SBill Fenner #endif
606a90e161bSBill Fenner #endif
607685295f4SBill Fenner 
608685295f4SBill Fenner #ifndef HAVE_VSNPRINTF
609685295f4SBill Fenner int
610685295f4SBill Fenner vsnprintf (char *str, size_t sz, const char *format, va_list args)
611685295f4SBill Fenner {
612685295f4SBill Fenner   struct state state;
613685295f4SBill Fenner   int ret;
614685295f4SBill Fenner   unsigned char *ustr = (unsigned char *)str;
615685295f4SBill Fenner 
616685295f4SBill Fenner   state.max_sz = 0;
617685295f4SBill Fenner   state.sz     = sz;
618685295f4SBill Fenner   state.str    = ustr;
619685295f4SBill Fenner   state.s      = ustr;
620685295f4SBill Fenner   state.theend = ustr + sz - 1;
621685295f4SBill Fenner   state.append_char = sn_append_char;
622685295f4SBill Fenner   state.reserve     = sn_reserve;
623685295f4SBill Fenner 
624685295f4SBill Fenner   ret = xyzprintf (&state, format, args);
625685295f4SBill Fenner   *state.s = '\0';
626685295f4SBill Fenner   if (ret)
627685295f4SBill Fenner     return sz;
628685295f4SBill Fenner   else
629685295f4SBill Fenner     return state.s - state.str;
630685295f4SBill Fenner }
631685295f4SBill Fenner #endif
632685295f4SBill Fenner 
633