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