2 * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 /* $Id: snprintf.c,v 1.1 2004-04-05 22:43:51 guy Exp $ */
41 static const char rcsid[] _U_ =
42 "@(#) $Header: /tcpdump/master/libpcap/missing/snprintf.c,v 1.1 2004-04-05 22:43:51 guy Exp $";
50 #include <sys/types.h>
69 unsigned char *theend;
72 int (*append_char)(struct state *, unsigned char);
73 int (*reserve)(struct state *, size_t);
77 #ifndef HAVE_VSNPRINTF
79 sn_reserve (struct state *state, size_t n)
81 return state->s + n > state->theend;
85 sn_append_char (struct state *state, unsigned char c)
87 if (sn_reserve (state, 1)) {
98 as_reserve (struct state *state, size_t n)
100 if (state->s + n > state->theend) {
101 int off = state->s - state->str;
104 if (state->max_sz && state->sz >= state->max_sz)
107 state->sz = max(state->sz * 2, state->sz + n);
109 state->sz = min(state->sz, state->max_sz);
110 tmp = realloc (state->str, state->sz);
114 state->s = state->str + off;
115 state->theend = state->str + state->sz - 1;
121 as_append_char (struct state *state, unsigned char c)
123 if(as_reserve (state, 1))
133 append_number(struct state *state,
134 unsigned long num, unsigned base, char *rep,
135 int width, int prec, int flags, int minusp)
140 /* given precision, ignore zero flag */
145 /* zero value with zero precision -> "" */
146 if(prec == 0 && num == 0)
149 if((*state->append_char)(state, rep[num % base]))
155 /* pad with prec zeros */
157 if((*state->append_char)(state, '0'))
161 /* add length of alternate prefix (added later) to len */
162 if(flags & alternate_flag && (base == 16 || base == 8))
165 if(flags & zero_flag){
167 if(minusp || (flags & space_flag) || (flags & plus_flag))
170 if((*state->append_char)(state, '0'))
175 /* add alternate prefix */
176 if(flags & alternate_flag && (base == 16 || base == 8)){
178 if((*state->append_char)(state, rep[10] + 23)) /* XXX */
180 if((*state->append_char)(state, '0'))
185 if((*state->append_char)(state, '-'))
188 } else if(flags & plus_flag) {
189 if((*state->append_char)(state, '+'))
192 } else if(flags & space_flag) {
193 if((*state->append_char)(state, ' '))
197 if(flags & minus_flag)
198 /* swap before padding with spaces */
199 for(i = 0; i < len / 2; i++){
200 char c = state->s[-i-1];
201 state->s[-i-1] = state->s[-len+i];
202 state->s[-len+i] = c;
206 if((*state->append_char)(state, ' '))
210 if(!(flags & minus_flag))
211 /* swap after padding with spaces */
212 for(i = 0; i < len / 2; i++){
213 char c = state->s[-i-1];
214 state->s[-i-1] = state->s[-len+i];
215 state->s[-len+i] = c;
222 append_string (struct state *state,
231 width -= strlen((char *)arg);
232 if(!(flags & minus_flag))
234 if((*state->append_char) (state, ' '))
237 while (*arg && prec--)
238 if ((*state->append_char) (state, *arg++))
242 if ((*state->append_char) (state, *arg++))
245 if(flags & minus_flag)
247 if((*state->append_char) (state, ' '))
253 append_char(struct state *state,
258 while(!(flags & minus_flag) && --width > 0)
259 if((*state->append_char) (state, ' '))
262 if((*state->append_char) (state, arg))
264 while((flags & minus_flag) && --width > 0)
265 if((*state->append_char) (state, ' '))
272 * This can't be made into a function...
275 #define PARSE_INT_FORMAT(res, arg, unsig) \
277 res = (unsig long)va_arg(arg, unsig long); \
278 else if (short_flag) \
279 res = (unsig short)va_arg(arg, unsig int); \
281 res = (unsig int)va_arg(arg, unsig int)
284 * zyxprintf - return 0 or -1
288 xyzprintf (struct state *state, const char *char_format, va_list ap)
290 const unsigned char *format = (const unsigned char *)char_format;
293 while((c = *format++)) {
302 while((c = *format++)){
310 flags |= alternate_flag;
317 if((flags & space_flag) && (flags & plus_flag))
320 if((flags & minus_flag) && (flags & zero_flag))
326 width = width * 10 + c - '0';
330 width = va_arg(ap, int);
340 prec = prec * 10 + c - '0';
344 prec = va_arg(ap, int);
354 } else if (c == 'l') {
361 if(append_char(state, va_arg(ap, int), width, flags))
365 if (append_string(state,
366 va_arg(ap, unsigned char*),
378 PARSE_INT_FORMAT(arg, ap, signed);
386 if (append_number (state, num, 10, "0123456789",
387 width, prec, flags, minusp))
394 PARSE_INT_FORMAT(arg, ap, unsigned);
396 if (append_number (state, arg, 10, "0123456789",
397 width, prec, flags, 0))
404 PARSE_INT_FORMAT(arg, ap, unsigned);
406 if (append_number (state, arg, 010, "01234567",
407 width, prec, flags, 0))
414 PARSE_INT_FORMAT(arg, ap, unsigned);
416 if (append_number (state, arg, 0x10, "0123456789abcdef",
417 width, prec, flags, 0))
424 PARSE_INT_FORMAT(arg, ap, unsigned);
426 if (append_number (state, arg, 0x10, "0123456789ABCDEF",
427 width, prec, flags, 0))
432 unsigned long arg = (unsigned long)va_arg(ap, void*);
434 if (append_number (state, arg, 0x10, "0123456789ABCDEF",
435 width, prec, flags, 0))
440 int *arg = va_arg(ap, int*);
441 *arg = state->s - state->str;
448 if ((*state->append_char)(state, c))
452 if ( (*state->append_char)(state, '%')
453 || (*state->append_char)(state, c))
458 if ((*state->append_char) (state, c))
464 #ifndef HAVE_SNPRINTF
466 snprintf (char *str, size_t sz, const char *format, ...)
471 va_start(args, format);
472 ret = vsnprintf (str, sz, format, args);
483 ret2 = vsprintf (tmp, format, args);
484 if (ret != ret2 || strcmp(str, tmp))
496 #ifndef HAVE_ASPRINTF
498 asprintf (char **ret, const char *format, ...)
503 va_start(args, format);
504 val = vasprintf (ret, format, args);
510 tmp = malloc (val + 1);
514 ret2 = vsprintf (tmp, format, args);
515 if (val != ret2 || strcmp(*ret, tmp))
526 #ifndef HAVE_ASNPRINTF
528 asnprintf (char **ret, size_t max_sz, const char *format, ...)
533 va_start(args, format);
534 val = vasnprintf (ret, max_sz, format, args);
540 tmp = malloc (val + 1);
544 ret2 = vsprintf (tmp, format, args);
545 if (val != ret2 || strcmp(*ret, tmp))
556 #ifndef HAVE_VASPRINTF
558 vasprintf (char **ret, const char *format, va_list args)
560 return vasnprintf (ret, 0, format, args);
565 #ifndef HAVE_VASNPRINTF
567 vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
573 state.max_sz = max_sz;
575 state.str = malloc(state.sz);
576 if (state.str == NULL) {
581 state.theend = state.s + state.sz - 1;
582 state.append_char = as_append_char;
583 state.reserve = as_reserve;
585 st = xyzprintf (&state, format, args);
594 len = state.s - state.str;
595 tmp = realloc (state.str, len+1);
608 #ifndef HAVE_VSNPRINTF
610 vsnprintf (char *str, size_t sz, const char *format, va_list args)
614 unsigned char *ustr = (unsigned char *)str;
620 state.theend = ustr + sz - 1;
621 state.append_char = sn_append_char;
622 state.reserve = sn_reserve;
624 ret = xyzprintf (&state, format, args);
629 return state.s - state.str;