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 34685295f4SBill Fenner #ifdef HAVE_CONFIG_H 35685295f4SBill Fenner #include <config.h> 36685295f4SBill Fenner #endif 37685295f4SBill Fenner 38685295f4SBill Fenner #include <stdio.h> 39685295f4SBill Fenner #include <stdarg.h> 40685295f4SBill Fenner #include <stdlib.h> 41685295f4SBill Fenner #include <string.h> 42685295f4SBill Fenner #include <ctype.h> 43685295f4SBill Fenner #include <sys/types.h> 44685295f4SBill Fenner 453340d773SGleb Smirnoff #include "netdissect.h" 46685295f4SBill Fenner 47685295f4SBill Fenner enum format_flags { 48685295f4SBill Fenner minus_flag = 1, 49685295f4SBill Fenner plus_flag = 2, 50685295f4SBill Fenner space_flag = 4, 51685295f4SBill Fenner alternate_flag = 8, 52685295f4SBill Fenner zero_flag = 16 53685295f4SBill Fenner }; 54685295f4SBill Fenner 55685295f4SBill Fenner /* 56685295f4SBill Fenner * Common state 57685295f4SBill Fenner */ 58685295f4SBill Fenner 59685295f4SBill Fenner struct state { 60685295f4SBill Fenner unsigned char *str; 61685295f4SBill Fenner unsigned char *s; 62685295f4SBill Fenner unsigned char *theend; 63685295f4SBill Fenner size_t sz; 64685295f4SBill Fenner size_t max_sz; 65685295f4SBill Fenner int (*append_char)(struct state *, unsigned char); 66685295f4SBill Fenner int (*reserve)(struct state *, size_t); 67685295f4SBill Fenner /* XXX - methods */ 68685295f4SBill Fenner }; 69685295f4SBill Fenner 70a90e161bSBill Fenner #if 0 71685295f4SBill Fenner static int 72685295f4SBill Fenner as_reserve (struct state *state, size_t n) 73685295f4SBill Fenner { 74685295f4SBill Fenner if (state->s + n > state->theend) { 75685295f4SBill Fenner int off = state->s - state->str; 76685295f4SBill Fenner unsigned char *tmp; 77685295f4SBill Fenner 78685295f4SBill Fenner if (state->max_sz && state->sz >= state->max_sz) 79685295f4SBill Fenner return 1; 80685295f4SBill Fenner 81685295f4SBill Fenner state->sz = max(state->sz * 2, state->sz + n); 82685295f4SBill Fenner if (state->max_sz) 83685295f4SBill Fenner state->sz = min(state->sz, state->max_sz); 84685295f4SBill Fenner tmp = realloc (state->str, state->sz); 85685295f4SBill Fenner if (tmp == NULL) 86685295f4SBill Fenner return 1; 87685295f4SBill Fenner state->str = tmp; 88685295f4SBill Fenner state->s = state->str + off; 89685295f4SBill Fenner state->theend = state->str + state->sz - 1; 90685295f4SBill Fenner } 91685295f4SBill Fenner return 0; 92685295f4SBill Fenner } 93685295f4SBill Fenner 94685295f4SBill Fenner static int 95685295f4SBill Fenner as_append_char (struct state *state, unsigned char c) 96685295f4SBill Fenner { 97685295f4SBill Fenner if(as_reserve (state, 1)) 98685295f4SBill Fenner return 1; 99685295f4SBill Fenner else { 100685295f4SBill Fenner *state->s++ = c; 101685295f4SBill Fenner return 0; 102685295f4SBill Fenner } 103685295f4SBill Fenner } 104a90e161bSBill Fenner #endif 105685295f4SBill Fenner 106685295f4SBill Fenner static int 107685295f4SBill Fenner append_number(struct state *state, 108685295f4SBill Fenner unsigned long num, unsigned base, char *rep, 109685295f4SBill Fenner int width, int prec, int flags, int minusp) 110685295f4SBill Fenner { 111685295f4SBill Fenner int len = 0; 112685295f4SBill Fenner int i; 113685295f4SBill Fenner 114685295f4SBill Fenner /* given precision, ignore zero flag */ 115685295f4SBill Fenner if(prec != -1) 116685295f4SBill Fenner flags &= ~zero_flag; 117685295f4SBill Fenner else 118685295f4SBill Fenner prec = 1; 119685295f4SBill Fenner /* zero value with zero precision -> "" */ 120685295f4SBill Fenner if(prec == 0 && num == 0) 121685295f4SBill Fenner return 0; 122685295f4SBill Fenner do{ 123685295f4SBill Fenner if((*state->append_char)(state, rep[num % base])) 124685295f4SBill Fenner return 1; 125685295f4SBill Fenner len++; 126685295f4SBill Fenner num /= base; 127685295f4SBill Fenner }while(num); 128685295f4SBill Fenner prec -= len; 129685295f4SBill Fenner /* pad with prec zeros */ 130685295f4SBill Fenner while(prec-- > 0){ 131685295f4SBill Fenner if((*state->append_char)(state, '0')) 132685295f4SBill Fenner return 1; 133685295f4SBill Fenner len++; 134685295f4SBill Fenner } 135685295f4SBill Fenner /* add length of alternate prefix (added later) to len */ 136685295f4SBill Fenner if(flags & alternate_flag && (base == 16 || base == 8)) 137685295f4SBill Fenner len += base / 8; 138685295f4SBill Fenner /* pad with zeros */ 139685295f4SBill Fenner if(flags & zero_flag){ 140685295f4SBill Fenner width -= len; 141685295f4SBill Fenner if(minusp || (flags & space_flag) || (flags & plus_flag)) 142685295f4SBill Fenner width--; 143685295f4SBill Fenner while(width-- > 0){ 144685295f4SBill Fenner if((*state->append_char)(state, '0')) 145685295f4SBill Fenner return 1; 146685295f4SBill Fenner len++; 147685295f4SBill Fenner } 148685295f4SBill Fenner } 149685295f4SBill Fenner /* add alternate prefix */ 150685295f4SBill Fenner if(flags & alternate_flag && (base == 16 || base == 8)){ 151685295f4SBill Fenner if(base == 16) 152685295f4SBill Fenner if((*state->append_char)(state, rep[10] + 23)) /* XXX */ 153685295f4SBill Fenner return 1; 154685295f4SBill Fenner if((*state->append_char)(state, '0')) 155685295f4SBill Fenner return 1; 156685295f4SBill Fenner } 157685295f4SBill Fenner /* add sign */ 158685295f4SBill Fenner if(minusp){ 159685295f4SBill Fenner if((*state->append_char)(state, '-')) 160685295f4SBill Fenner return 1; 161685295f4SBill Fenner len++; 162685295f4SBill Fenner } else if(flags & plus_flag) { 163685295f4SBill Fenner if((*state->append_char)(state, '+')) 164685295f4SBill Fenner return 1; 165685295f4SBill Fenner len++; 166685295f4SBill Fenner } else if(flags & space_flag) { 167685295f4SBill Fenner if((*state->append_char)(state, ' ')) 168685295f4SBill Fenner return 1; 169685295f4SBill Fenner len++; 170685295f4SBill Fenner } 171685295f4SBill Fenner if(flags & minus_flag) 172685295f4SBill Fenner /* swap before padding with spaces */ 173685295f4SBill Fenner for(i = 0; i < len / 2; i++){ 174685295f4SBill Fenner char c = state->s[-i-1]; 175685295f4SBill Fenner state->s[-i-1] = state->s[-len+i]; 176685295f4SBill Fenner state->s[-len+i] = c; 177685295f4SBill Fenner } 178685295f4SBill Fenner width -= len; 179685295f4SBill Fenner while(width-- > 0){ 180685295f4SBill Fenner if((*state->append_char)(state, ' ')) 181685295f4SBill Fenner return 1; 182685295f4SBill Fenner len++; 183685295f4SBill Fenner } 184685295f4SBill Fenner if(!(flags & minus_flag)) 185685295f4SBill Fenner /* swap after padding with spaces */ 186685295f4SBill Fenner for(i = 0; i < len / 2; i++){ 187685295f4SBill Fenner char c = state->s[-i-1]; 188685295f4SBill Fenner state->s[-i-1] = state->s[-len+i]; 189685295f4SBill Fenner state->s[-len+i] = c; 190685295f4SBill Fenner } 191685295f4SBill Fenner 192685295f4SBill Fenner return 0; 193685295f4SBill Fenner } 194685295f4SBill Fenner 195685295f4SBill Fenner static int 196685295f4SBill Fenner append_string (struct state *state, 197685295f4SBill Fenner unsigned char *arg, 198685295f4SBill Fenner int width, 199685295f4SBill Fenner int prec, 200685295f4SBill Fenner int flags) 201685295f4SBill Fenner { 202685295f4SBill Fenner if(prec != -1) 203685295f4SBill Fenner width -= prec; 204685295f4SBill Fenner else 205685295f4SBill Fenner width -= strlen((char *)arg); 206685295f4SBill Fenner if(!(flags & minus_flag)) 207685295f4SBill Fenner while(width-- > 0) 208685295f4SBill Fenner if((*state->append_char) (state, ' ')) 209685295f4SBill Fenner return 1; 210685295f4SBill Fenner if (prec != -1) { 211685295f4SBill Fenner while (*arg && prec--) 212685295f4SBill Fenner if ((*state->append_char) (state, *arg++)) 213685295f4SBill Fenner return 1; 214685295f4SBill Fenner } else { 215685295f4SBill Fenner while (*arg) 216685295f4SBill Fenner if ((*state->append_char) (state, *arg++)) 217685295f4SBill Fenner return 1; 218685295f4SBill Fenner } 219685295f4SBill Fenner if(flags & minus_flag) 220685295f4SBill Fenner while(width-- > 0) 221685295f4SBill Fenner if((*state->append_char) (state, ' ')) 222685295f4SBill Fenner return 1; 223685295f4SBill Fenner return 0; 224685295f4SBill Fenner } 225685295f4SBill Fenner 226685295f4SBill Fenner static int 227685295f4SBill Fenner append_char(struct state *state, 228685295f4SBill Fenner unsigned char arg, 229685295f4SBill Fenner int width, 230685295f4SBill Fenner int flags) 231685295f4SBill Fenner { 232685295f4SBill Fenner while(!(flags & minus_flag) && --width > 0) 233685295f4SBill Fenner if((*state->append_char) (state, ' ')) 234685295f4SBill Fenner return 1; 235685295f4SBill Fenner 236685295f4SBill Fenner if((*state->append_char) (state, arg)) 237685295f4SBill Fenner return 1; 238685295f4SBill Fenner while((flags & minus_flag) && --width > 0) 239685295f4SBill Fenner if((*state->append_char) (state, ' ')) 240685295f4SBill Fenner return 1; 241685295f4SBill Fenner 242685295f4SBill Fenner return 0; 243685295f4SBill Fenner } 244685295f4SBill Fenner 245685295f4SBill Fenner /* 246685295f4SBill Fenner * This can't be made into a function... 247685295f4SBill Fenner */ 248685295f4SBill Fenner 249685295f4SBill Fenner #define PARSE_INT_FORMAT(res, arg, unsig) \ 250685295f4SBill Fenner if (long_flag) \ 251685295f4SBill Fenner res = (unsig long)va_arg(arg, unsig long); \ 252685295f4SBill Fenner else if (short_flag) \ 253685295f4SBill Fenner res = (unsig short)va_arg(arg, unsig int); \ 254685295f4SBill Fenner else \ 255685295f4SBill Fenner res = (unsig int)va_arg(arg, unsig int) 256685295f4SBill Fenner 257685295f4SBill Fenner /* 258685295f4SBill Fenner * zyxprintf - return 0 or -1 259685295f4SBill Fenner */ 260685295f4SBill Fenner 261685295f4SBill Fenner static int 262685295f4SBill Fenner xyzprintf (struct state *state, const char *char_format, va_list ap) 263685295f4SBill Fenner { 264685295f4SBill Fenner const unsigned char *format = (const unsigned char *)char_format; 265685295f4SBill Fenner unsigned char c; 266685295f4SBill Fenner 267685295f4SBill Fenner while((c = *format++)) { 268685295f4SBill Fenner if (c == '%') { 269685295f4SBill Fenner int flags = 0; 270685295f4SBill Fenner int width = 0; 271685295f4SBill Fenner int prec = -1; 272685295f4SBill Fenner int long_flag = 0; 273685295f4SBill Fenner int short_flag = 0; 274685295f4SBill Fenner 275685295f4SBill Fenner /* flags */ 276685295f4SBill Fenner while((c = *format++)){ 277685295f4SBill Fenner if(c == '-') 278685295f4SBill Fenner flags |= minus_flag; 279685295f4SBill Fenner else if(c == '+') 280685295f4SBill Fenner flags |= plus_flag; 281685295f4SBill Fenner else if(c == ' ') 282685295f4SBill Fenner flags |= space_flag; 283685295f4SBill Fenner else if(c == '#') 284685295f4SBill Fenner flags |= alternate_flag; 285685295f4SBill Fenner else if(c == '0') 286685295f4SBill Fenner flags |= zero_flag; 287685295f4SBill Fenner else 288685295f4SBill Fenner break; 289685295f4SBill Fenner } 290685295f4SBill Fenner 291685295f4SBill Fenner if((flags & space_flag) && (flags & plus_flag)) 292685295f4SBill Fenner flags ^= space_flag; 293685295f4SBill Fenner 294685295f4SBill Fenner if((flags & minus_flag) && (flags & zero_flag)) 295685295f4SBill Fenner flags ^= zero_flag; 296685295f4SBill Fenner 297685295f4SBill Fenner /* width */ 298685295f4SBill Fenner if (isdigit(c)) 299685295f4SBill Fenner do { 300685295f4SBill Fenner width = width * 10 + c - '0'; 301685295f4SBill Fenner c = *format++; 302685295f4SBill Fenner } while(isdigit(c)); 303685295f4SBill Fenner else if(c == '*') { 304685295f4SBill Fenner width = va_arg(ap, int); 305685295f4SBill Fenner c = *format++; 306685295f4SBill Fenner } 307685295f4SBill Fenner 308685295f4SBill Fenner /* precision */ 309685295f4SBill Fenner if (c == '.') { 310685295f4SBill Fenner prec = 0; 311685295f4SBill Fenner c = *format++; 312685295f4SBill Fenner if (isdigit(c)) 313685295f4SBill Fenner do { 314685295f4SBill Fenner prec = prec * 10 + c - '0'; 315685295f4SBill Fenner c = *format++; 316685295f4SBill Fenner } while(isdigit(c)); 317685295f4SBill Fenner else if (c == '*') { 318685295f4SBill Fenner prec = va_arg(ap, int); 319685295f4SBill Fenner c = *format++; 320685295f4SBill Fenner } 321685295f4SBill Fenner } 322685295f4SBill Fenner 323685295f4SBill Fenner /* size */ 324685295f4SBill Fenner 325685295f4SBill Fenner if (c == 'h') { 326685295f4SBill Fenner short_flag = 1; 327685295f4SBill Fenner c = *format++; 328685295f4SBill Fenner } else if (c == 'l') { 329685295f4SBill Fenner long_flag = 1; 330685295f4SBill Fenner c = *format++; 331685295f4SBill Fenner } 332685295f4SBill Fenner 333685295f4SBill Fenner switch (c) { 334685295f4SBill Fenner case 'c' : 335685295f4SBill Fenner if(append_char(state, va_arg(ap, int), width, flags)) 336685295f4SBill Fenner return -1; 337685295f4SBill Fenner break; 338685295f4SBill Fenner case 's' : 339685295f4SBill Fenner if (append_string(state, 340685295f4SBill Fenner va_arg(ap, unsigned char*), 341685295f4SBill Fenner width, 342685295f4SBill Fenner prec, 343685295f4SBill Fenner flags)) 344685295f4SBill Fenner return -1; 345685295f4SBill Fenner break; 346685295f4SBill Fenner case 'd' : 347685295f4SBill Fenner case 'i' : { 348685295f4SBill Fenner long arg; 349685295f4SBill Fenner unsigned long num; 350685295f4SBill Fenner int minusp = 0; 351685295f4SBill Fenner 352685295f4SBill Fenner PARSE_INT_FORMAT(arg, ap, signed); 353685295f4SBill Fenner 354685295f4SBill Fenner if (arg < 0) { 355685295f4SBill Fenner minusp = 1; 356685295f4SBill Fenner num = -arg; 357685295f4SBill Fenner } else 358685295f4SBill Fenner num = arg; 359685295f4SBill Fenner 360685295f4SBill Fenner if (append_number (state, num, 10, "0123456789", 361685295f4SBill Fenner width, prec, flags, minusp)) 362685295f4SBill Fenner return -1; 363685295f4SBill Fenner break; 364685295f4SBill Fenner } 365685295f4SBill Fenner case 'u' : { 366685295f4SBill Fenner unsigned long arg; 367685295f4SBill Fenner 368685295f4SBill Fenner PARSE_INT_FORMAT(arg, ap, unsigned); 369685295f4SBill Fenner 370685295f4SBill Fenner if (append_number (state, arg, 10, "0123456789", 371685295f4SBill Fenner width, prec, flags, 0)) 372685295f4SBill Fenner return -1; 373685295f4SBill Fenner break; 374685295f4SBill Fenner } 375685295f4SBill Fenner case 'o' : { 376685295f4SBill Fenner unsigned long arg; 377685295f4SBill Fenner 378685295f4SBill Fenner PARSE_INT_FORMAT(arg, ap, unsigned); 379685295f4SBill Fenner 380685295f4SBill Fenner if (append_number (state, arg, 010, "01234567", 381685295f4SBill Fenner width, prec, flags, 0)) 382685295f4SBill Fenner return -1; 383685295f4SBill Fenner break; 384685295f4SBill Fenner } 385685295f4SBill Fenner case 'x' : { 386685295f4SBill Fenner unsigned long arg; 387685295f4SBill Fenner 388685295f4SBill Fenner PARSE_INT_FORMAT(arg, ap, unsigned); 389685295f4SBill Fenner 390685295f4SBill Fenner if (append_number (state, arg, 0x10, "0123456789abcdef", 391685295f4SBill Fenner width, prec, flags, 0)) 392685295f4SBill Fenner return -1; 393685295f4SBill Fenner break; 394685295f4SBill Fenner } 395685295f4SBill Fenner case 'X' :{ 396685295f4SBill Fenner unsigned long arg; 397685295f4SBill Fenner 398685295f4SBill Fenner PARSE_INT_FORMAT(arg, ap, unsigned); 399685295f4SBill Fenner 400685295f4SBill Fenner if (append_number (state, arg, 0x10, "0123456789ABCDEF", 401685295f4SBill Fenner width, prec, flags, 0)) 402685295f4SBill Fenner return -1; 403685295f4SBill Fenner break; 404685295f4SBill Fenner } 405685295f4SBill Fenner case 'p' : { 406685295f4SBill Fenner unsigned long arg = (unsigned long)va_arg(ap, void*); 407685295f4SBill Fenner 408685295f4SBill Fenner if (append_number (state, arg, 0x10, "0123456789ABCDEF", 409685295f4SBill Fenner width, prec, flags, 0)) 410685295f4SBill Fenner return -1; 411685295f4SBill Fenner break; 412685295f4SBill Fenner } 413685295f4SBill Fenner case 'n' : { 414685295f4SBill Fenner int *arg = va_arg(ap, int *); 415685295f4SBill Fenner *arg = state->s - state->str; 416685295f4SBill Fenner break; 417685295f4SBill Fenner } 418685295f4SBill Fenner case '\0' : 419685295f4SBill Fenner --format; 420685295f4SBill Fenner /* FALLTHROUGH */ 421685295f4SBill Fenner case '%' : 422685295f4SBill Fenner if ((*state->append_char)(state, c)) 423685295f4SBill Fenner return -1; 424685295f4SBill Fenner break; 425685295f4SBill Fenner default : 426685295f4SBill Fenner if ( (*state->append_char)(state, '%') 427685295f4SBill Fenner || (*state->append_char)(state, c)) 428685295f4SBill Fenner return -1; 429685295f4SBill Fenner break; 430685295f4SBill Fenner } 431685295f4SBill Fenner } else 432685295f4SBill Fenner if ((*state->append_char) (state, c)) 433685295f4SBill Fenner return -1; 434685295f4SBill Fenner } 435685295f4SBill Fenner return 0; 436685295f4SBill Fenner } 437685295f4SBill Fenner 438a90e161bSBill Fenner #if 0 439685295f4SBill Fenner #ifndef HAVE_ASPRINTF 440685295f4SBill Fenner int 441685295f4SBill Fenner asprintf (char **ret, const char *format, ...) 442685295f4SBill Fenner { 443685295f4SBill Fenner va_list args; 444685295f4SBill Fenner int val; 445685295f4SBill Fenner 446685295f4SBill Fenner va_start(args, format); 447685295f4SBill Fenner val = vasprintf (ret, format, args); 448685295f4SBill Fenner 449685295f4SBill Fenner #ifdef PARANOIA 450685295f4SBill Fenner { 451685295f4SBill Fenner int ret2; 452685295f4SBill Fenner char *tmp; 453685295f4SBill Fenner tmp = malloc (val + 1); 454685295f4SBill Fenner if (tmp == NULL) 455685295f4SBill Fenner abort (); 456685295f4SBill Fenner 457685295f4SBill Fenner ret2 = vsprintf (tmp, format, args); 458685295f4SBill Fenner if (val != ret2 || strcmp(*ret, tmp)) 459685295f4SBill Fenner abort (); 460685295f4SBill Fenner free (tmp); 461685295f4SBill Fenner } 462685295f4SBill Fenner #endif 463685295f4SBill Fenner 464685295f4SBill Fenner va_end(args); 465685295f4SBill Fenner return val; 466685295f4SBill Fenner } 467685295f4SBill Fenner #endif 468685295f4SBill Fenner 469685295f4SBill Fenner #ifndef HAVE_VASNPRINTF 470685295f4SBill Fenner int 471*ee67461eSJoseph Mingrone nd_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args) 472685295f4SBill Fenner { 473685295f4SBill Fenner int st; 474685295f4SBill Fenner size_t len; 475685295f4SBill Fenner struct state state; 476685295f4SBill Fenner 477685295f4SBill Fenner state.max_sz = max_sz; 478685295f4SBill Fenner state.sz = 1; 479685295f4SBill Fenner state.str = malloc(state.sz); 480685295f4SBill Fenner if (state.str == NULL) { 481685295f4SBill Fenner *ret = NULL; 482685295f4SBill Fenner return -1; 483685295f4SBill Fenner } 484685295f4SBill Fenner state.s = state.str; 485685295f4SBill Fenner state.theend = state.s + state.sz - 1; 486685295f4SBill Fenner state.append_char = as_append_char; 487685295f4SBill Fenner state.reserve = as_reserve; 488685295f4SBill Fenner 489685295f4SBill Fenner st = xyzprintf (&state, format, args); 490685295f4SBill Fenner if (st) { 491685295f4SBill Fenner free (state.str); 492685295f4SBill Fenner *ret = NULL; 493685295f4SBill Fenner return -1; 494685295f4SBill Fenner } else { 495685295f4SBill Fenner char *tmp; 496685295f4SBill Fenner 497685295f4SBill Fenner *state.s = '\0'; 498685295f4SBill Fenner len = state.s - state.str; 499685295f4SBill Fenner tmp = realloc (state.str, len+1); 500685295f4SBill Fenner if (tmp == NULL) { 501685295f4SBill Fenner free (state.str); 502685295f4SBill Fenner *ret = NULL; 503685295f4SBill Fenner return -1; 504685295f4SBill Fenner } 505685295f4SBill Fenner *ret = tmp; 506685295f4SBill Fenner return len; 507685295f4SBill Fenner } 508685295f4SBill Fenner } 509685295f4SBill Fenner #endif 510a90e161bSBill Fenner #endif 511