snprintf.c revision 2949f58a438f6fd85f66a8b7ed4708042cde4b37
19189445c0a66d074dcded77b9c7322ef45422727George Mount/* 29189445c0a66d074dcded77b9c7322ef45422727George Mount * Copyright (c) 1995-1999 Kungliga Tekniska H�gskolan 39189445c0a66d074dcded77b9c7322ef45422727George Mount * (Royal Institute of Technology, Stockholm, Sweden). 49189445c0a66d074dcded77b9c7322ef45422727George Mount * All rights reserved. 59189445c0a66d074dcded77b9c7322ef45422727George Mount * 69189445c0a66d074dcded77b9c7322ef45422727George Mount * Redistribution and use in source and binary forms, with or without 79189445c0a66d074dcded77b9c7322ef45422727George Mount * modification, are permitted provided that the following conditions 89189445c0a66d074dcded77b9c7322ef45422727George Mount * are met: 99189445c0a66d074dcded77b9c7322ef45422727George Mount * 109189445c0a66d074dcded77b9c7322ef45422727George Mount * 1. Redistributions of source code must retain the above copyright 119189445c0a66d074dcded77b9c7322ef45422727George Mount * notice, this list of conditions and the following disclaimer. 129189445c0a66d074dcded77b9c7322ef45422727George Mount * 139189445c0a66d074dcded77b9c7322ef45422727George Mount * 2. Redistributions in binary form must reproduce the above copyright 149189445c0a66d074dcded77b9c7322ef45422727George Mount * notice, this list of conditions and the following disclaimer in the 159189445c0a66d074dcded77b9c7322ef45422727George Mount * documentation and/or other materials provided with the distribution. 169189445c0a66d074dcded77b9c7322ef45422727George Mount * 179189445c0a66d074dcded77b9c7322ef45422727George Mount * 3. Neither the name of the Institute nor the names of its contributors 189189445c0a66d074dcded77b9c7322ef45422727George Mount * may be used to endorse or promote products derived from this software 199189445c0a66d074dcded77b9c7322ef45422727George Mount * without specific prior written permission. 209189445c0a66d074dcded77b9c7322ef45422727George Mount * 219189445c0a66d074dcded77b9c7322ef45422727George Mount * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 229189445c0a66d074dcded77b9c7322ef45422727George Mount * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239189445c0a66d074dcded77b9c7322ef45422727George Mount * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249189445c0a66d074dcded77b9c7322ef45422727George Mount * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 259189445c0a66d074dcded77b9c7322ef45422727George Mount * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269189445c0a66d074dcded77b9c7322ef45422727George Mount * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279189445c0a66d074dcded77b9c7322ef45422727George Mount * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289189445c0a66d074dcded77b9c7322ef45422727George Mount * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299189445c0a66d074dcded77b9c7322ef45422727George Mount * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309189445c0a66d074dcded77b9c7322ef45422727George Mount * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319189445c0a66d074dcded77b9c7322ef45422727George Mount * SUCH DAMAGE. 329189445c0a66d074dcded77b9c7322ef45422727George Mount */ 339189445c0a66d074dcded77b9c7322ef45422727George Mount 349189445c0a66d074dcded77b9c7322ef45422727George Mount/* $Id: snprintf.c,v 1.8 2003/11/16 09:36:51 guy Exp $ */ 359189445c0a66d074dcded77b9c7322ef45422727George Mount 369189445c0a66d074dcded77b9c7322ef45422727George Mount#ifdef HAVE_CONFIG_H 379189445c0a66d074dcded77b9c7322ef45422727George Mount#include <config.h> 389189445c0a66d074dcded77b9c7322ef45422727George Mount#endif 399189445c0a66d074dcded77b9c7322ef45422727George Mount 409189445c0a66d074dcded77b9c7322ef45422727George Mount#ifndef lint 419189445c0a66d074dcded77b9c7322ef45422727George Mountstatic const char rcsid[] _U_ = 429189445c0a66d074dcded77b9c7322ef45422727George Mount "@(#) $Header: /tcpdump/master/tcpdump/missing/snprintf.c,v 1.8 2003/11/16 09:36:51 guy Exp $"; 439189445c0a66d074dcded77b9c7322ef45422727George Mount#endif 449189445c0a66d074dcded77b9c7322ef45422727George Mount 459189445c0a66d074dcded77b9c7322ef45422727George Mount#include <stdio.h> 469189445c0a66d074dcded77b9c7322ef45422727George Mount#include <stdarg.h> 479189445c0a66d074dcded77b9c7322ef45422727George Mount#include <stdlib.h> 489189445c0a66d074dcded77b9c7322ef45422727George Mount#include <string.h> 499189445c0a66d074dcded77b9c7322ef45422727George Mount#include <ctype.h> 509189445c0a66d074dcded77b9c7322ef45422727George Mount#include <sys/types.h> 519189445c0a66d074dcded77b9c7322ef45422727George Mount 529189445c0a66d074dcded77b9c7322ef45422727George Mount#include <interface.h> 539189445c0a66d074dcded77b9c7322ef45422727George Mount 549189445c0a66d074dcded77b9c7322ef45422727George Mountenum format_flags { 559189445c0a66d074dcded77b9c7322ef45422727George Mount minus_flag = 1, 569189445c0a66d074dcded77b9c7322ef45422727George Mount plus_flag = 2, 579189445c0a66d074dcded77b9c7322ef45422727George Mount space_flag = 4, 589189445c0a66d074dcded77b9c7322ef45422727George Mount alternate_flag = 8, 599189445c0a66d074dcded77b9c7322ef45422727George Mount zero_flag = 16 609189445c0a66d074dcded77b9c7322ef45422727George Mount}; 619189445c0a66d074dcded77b9c7322ef45422727George Mount 629189445c0a66d074dcded77b9c7322ef45422727George Mount/* 639189445c0a66d074dcded77b9c7322ef45422727George Mount * Common state 649189445c0a66d074dcded77b9c7322ef45422727George Mount */ 659189445c0a66d074dcded77b9c7322ef45422727George Mount 669189445c0a66d074dcded77b9c7322ef45422727George Mountstruct state { 679189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned char *str; 689189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned char *s; 699189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned char *theend; 709189445c0a66d074dcded77b9c7322ef45422727George Mount size_t sz; 719189445c0a66d074dcded77b9c7322ef45422727George Mount size_t max_sz; 729189445c0a66d074dcded77b9c7322ef45422727George Mount int (*append_char)(struct state *, unsigned char); 739189445c0a66d074dcded77b9c7322ef45422727George Mount int (*reserve)(struct state *, size_t); 749189445c0a66d074dcded77b9c7322ef45422727George Mount /* XXX - methods */ 759189445c0a66d074dcded77b9c7322ef45422727George Mount}; 769189445c0a66d074dcded77b9c7322ef45422727George Mount 779189445c0a66d074dcded77b9c7322ef45422727George Mount#ifndef HAVE_VSNPRINTF 789189445c0a66d074dcded77b9c7322ef45422727George Mountstatic int 799189445c0a66d074dcded77b9c7322ef45422727George Mountsn_reserve (struct state *state, size_t n) 809189445c0a66d074dcded77b9c7322ef45422727George Mount{ 819189445c0a66d074dcded77b9c7322ef45422727George Mount return state->s + n > state->theend; 829189445c0a66d074dcded77b9c7322ef45422727George Mount} 839189445c0a66d074dcded77b9c7322ef45422727George Mount 849189445c0a66d074dcded77b9c7322ef45422727George Mountstatic int 859189445c0a66d074dcded77b9c7322ef45422727George Mountsn_append_char (struct state *state, unsigned char c) 869189445c0a66d074dcded77b9c7322ef45422727George Mount{ 879189445c0a66d074dcded77b9c7322ef45422727George Mount if (sn_reserve (state, 1)) { 889189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 899189445c0a66d074dcded77b9c7322ef45422727George Mount } else { 909189445c0a66d074dcded77b9c7322ef45422727George Mount *state->s++ = c; 919189445c0a66d074dcded77b9c7322ef45422727George Mount return 0; 929189445c0a66d074dcded77b9c7322ef45422727George Mount } 939189445c0a66d074dcded77b9c7322ef45422727George Mount} 949189445c0a66d074dcded77b9c7322ef45422727George Mount#endif 959189445c0a66d074dcded77b9c7322ef45422727George Mount 969189445c0a66d074dcded77b9c7322ef45422727George Mount#if 0 979189445c0a66d074dcded77b9c7322ef45422727George Mountstatic int 989189445c0a66d074dcded77b9c7322ef45422727George Mountas_reserve (struct state *state, size_t n) 999189445c0a66d074dcded77b9c7322ef45422727George Mount{ 1009189445c0a66d074dcded77b9c7322ef45422727George Mount if (state->s + n > state->theend) { 1019189445c0a66d074dcded77b9c7322ef45422727George Mount int off = state->s - state->str; 1029189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned char *tmp; 1039189445c0a66d074dcded77b9c7322ef45422727George Mount 1049189445c0a66d074dcded77b9c7322ef45422727George Mount if (state->max_sz && state->sz >= state->max_sz) 1059189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1069189445c0a66d074dcded77b9c7322ef45422727George Mount 1079189445c0a66d074dcded77b9c7322ef45422727George Mount state->sz = max(state->sz * 2, state->sz + n); 1089189445c0a66d074dcded77b9c7322ef45422727George Mount if (state->max_sz) 1099189445c0a66d074dcded77b9c7322ef45422727George Mount state->sz = min(state->sz, state->max_sz); 1109189445c0a66d074dcded77b9c7322ef45422727George Mount tmp = realloc (state->str, state->sz); 1119189445c0a66d074dcded77b9c7322ef45422727George Mount if (tmp == NULL) 1129189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1139189445c0a66d074dcded77b9c7322ef45422727George Mount state->str = tmp; 1149189445c0a66d074dcded77b9c7322ef45422727George Mount state->s = state->str + off; 1159189445c0a66d074dcded77b9c7322ef45422727George Mount state->theend = state->str + state->sz - 1; 1169189445c0a66d074dcded77b9c7322ef45422727George Mount } 1179189445c0a66d074dcded77b9c7322ef45422727George Mount return 0; 1189189445c0a66d074dcded77b9c7322ef45422727George Mount} 1199189445c0a66d074dcded77b9c7322ef45422727George Mount 1209189445c0a66d074dcded77b9c7322ef45422727George Mountstatic int 1219189445c0a66d074dcded77b9c7322ef45422727George Mountas_append_char (struct state *state, unsigned char c) 1229189445c0a66d074dcded77b9c7322ef45422727George Mount{ 1239189445c0a66d074dcded77b9c7322ef45422727George Mount if(as_reserve (state, 1)) 1249189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1259189445c0a66d074dcded77b9c7322ef45422727George Mount else { 1269189445c0a66d074dcded77b9c7322ef45422727George Mount *state->s++ = c; 1279189445c0a66d074dcded77b9c7322ef45422727George Mount return 0; 1289189445c0a66d074dcded77b9c7322ef45422727George Mount } 1299189445c0a66d074dcded77b9c7322ef45422727George Mount} 1309189445c0a66d074dcded77b9c7322ef45422727George Mount#endif 1319189445c0a66d074dcded77b9c7322ef45422727George Mount 1329189445c0a66d074dcded77b9c7322ef45422727George Mountstatic int 1339189445c0a66d074dcded77b9c7322ef45422727George Mountappend_number(struct state *state, 1349189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned long num, unsigned base, char *rep, 1359189445c0a66d074dcded77b9c7322ef45422727George Mount int width, int prec, int flags, int minusp) 1369189445c0a66d074dcded77b9c7322ef45422727George Mount{ 1379189445c0a66d074dcded77b9c7322ef45422727George Mount int len = 0; 1389189445c0a66d074dcded77b9c7322ef45422727George Mount int i; 1399189445c0a66d074dcded77b9c7322ef45422727George Mount 1409189445c0a66d074dcded77b9c7322ef45422727George Mount /* given precision, ignore zero flag */ 1419189445c0a66d074dcded77b9c7322ef45422727George Mount if(prec != -1) 1429189445c0a66d074dcded77b9c7322ef45422727George Mount flags &= ~zero_flag; 1439189445c0a66d074dcded77b9c7322ef45422727George Mount else 1449189445c0a66d074dcded77b9c7322ef45422727George Mount prec = 1; 1459189445c0a66d074dcded77b9c7322ef45422727George Mount /* zero value with zero precision -> "" */ 1469189445c0a66d074dcded77b9c7322ef45422727George Mount if(prec == 0 && num == 0) 1479189445c0a66d074dcded77b9c7322ef45422727George Mount return 0; 1489189445c0a66d074dcded77b9c7322ef45422727George Mount do{ 1499189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char)(state, rep[num % base])) 1509189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1519189445c0a66d074dcded77b9c7322ef45422727George Mount len++; 1529189445c0a66d074dcded77b9c7322ef45422727George Mount num /= base; 1539189445c0a66d074dcded77b9c7322ef45422727George Mount }while(num); 1549189445c0a66d074dcded77b9c7322ef45422727George Mount prec -= len; 1559189445c0a66d074dcded77b9c7322ef45422727George Mount /* pad with prec zeros */ 1569189445c0a66d074dcded77b9c7322ef45422727George Mount while(prec-- > 0){ 1579189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char)(state, '0')) 1589189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1599189445c0a66d074dcded77b9c7322ef45422727George Mount len++; 1609189445c0a66d074dcded77b9c7322ef45422727George Mount } 1619189445c0a66d074dcded77b9c7322ef45422727George Mount /* add length of alternate prefix (added later) to len */ 1629189445c0a66d074dcded77b9c7322ef45422727George Mount if(flags & alternate_flag && (base == 16 || base == 8)) 1639189445c0a66d074dcded77b9c7322ef45422727George Mount len += base / 8; 1649189445c0a66d074dcded77b9c7322ef45422727George Mount /* pad with zeros */ 1659189445c0a66d074dcded77b9c7322ef45422727George Mount if(flags & zero_flag){ 1669189445c0a66d074dcded77b9c7322ef45422727George Mount width -= len; 1679189445c0a66d074dcded77b9c7322ef45422727George Mount if(minusp || (flags & space_flag) || (flags & plus_flag)) 1689189445c0a66d074dcded77b9c7322ef45422727George Mount width--; 1699189445c0a66d074dcded77b9c7322ef45422727George Mount while(width-- > 0){ 1709189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char)(state, '0')) 1719189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1729189445c0a66d074dcded77b9c7322ef45422727George Mount len++; 1739189445c0a66d074dcded77b9c7322ef45422727George Mount } 1749189445c0a66d074dcded77b9c7322ef45422727George Mount } 1759189445c0a66d074dcded77b9c7322ef45422727George Mount /* add alternate prefix */ 1769189445c0a66d074dcded77b9c7322ef45422727George Mount if(flags & alternate_flag && (base == 16 || base == 8)){ 1779189445c0a66d074dcded77b9c7322ef45422727George Mount if(base == 16) 1789189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char)(state, rep[10] + 23)) /* XXX */ 1799189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1809189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char)(state, '0')) 1819189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1829189445c0a66d074dcded77b9c7322ef45422727George Mount } 1839189445c0a66d074dcded77b9c7322ef45422727George Mount /* add sign */ 1849189445c0a66d074dcded77b9c7322ef45422727George Mount if(minusp){ 1859189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char)(state, '-')) 1869189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1879189445c0a66d074dcded77b9c7322ef45422727George Mount len++; 1889189445c0a66d074dcded77b9c7322ef45422727George Mount } else if(flags & plus_flag) { 1899189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char)(state, '+')) 1909189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1919189445c0a66d074dcded77b9c7322ef45422727George Mount len++; 1929189445c0a66d074dcded77b9c7322ef45422727George Mount } else if(flags & space_flag) { 1939189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char)(state, ' ')) 1949189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 1959189445c0a66d074dcded77b9c7322ef45422727George Mount len++; 1969189445c0a66d074dcded77b9c7322ef45422727George Mount } 1979189445c0a66d074dcded77b9c7322ef45422727George Mount if(flags & minus_flag) 1989189445c0a66d074dcded77b9c7322ef45422727George Mount /* swap before padding with spaces */ 1999189445c0a66d074dcded77b9c7322ef45422727George Mount for(i = 0; i < len / 2; i++){ 2009189445c0a66d074dcded77b9c7322ef45422727George Mount char c = state->s[-i-1]; 2019189445c0a66d074dcded77b9c7322ef45422727George Mount state->s[-i-1] = state->s[-len+i]; 2029189445c0a66d074dcded77b9c7322ef45422727George Mount state->s[-len+i] = c; 2039189445c0a66d074dcded77b9c7322ef45422727George Mount } 2049189445c0a66d074dcded77b9c7322ef45422727George Mount width -= len; 2059189445c0a66d074dcded77b9c7322ef45422727George Mount while(width-- > 0){ 2069189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char)(state, ' ')) 2079189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 2089189445c0a66d074dcded77b9c7322ef45422727George Mount len++; 2099189445c0a66d074dcded77b9c7322ef45422727George Mount } 2109189445c0a66d074dcded77b9c7322ef45422727George Mount if(!(flags & minus_flag)) 2119189445c0a66d074dcded77b9c7322ef45422727George Mount /* swap after padding with spaces */ 2129189445c0a66d074dcded77b9c7322ef45422727George Mount for(i = 0; i < len / 2; i++){ 2139189445c0a66d074dcded77b9c7322ef45422727George Mount char c = state->s[-i-1]; 2149189445c0a66d074dcded77b9c7322ef45422727George Mount state->s[-i-1] = state->s[-len+i]; 2159189445c0a66d074dcded77b9c7322ef45422727George Mount state->s[-len+i] = c; 2169189445c0a66d074dcded77b9c7322ef45422727George Mount } 2179189445c0a66d074dcded77b9c7322ef45422727George Mount 2189189445c0a66d074dcded77b9c7322ef45422727George Mount return 0; 2199189445c0a66d074dcded77b9c7322ef45422727George Mount} 2209189445c0a66d074dcded77b9c7322ef45422727George Mount 2219189445c0a66d074dcded77b9c7322ef45422727George Mountstatic int 2229189445c0a66d074dcded77b9c7322ef45422727George Mountappend_string (struct state *state, 2239189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned char *arg, 2249189445c0a66d074dcded77b9c7322ef45422727George Mount int width, 2259189445c0a66d074dcded77b9c7322ef45422727George Mount int prec, 2269189445c0a66d074dcded77b9c7322ef45422727George Mount int flags) 2279189445c0a66d074dcded77b9c7322ef45422727George Mount{ 2289189445c0a66d074dcded77b9c7322ef45422727George Mount if(prec != -1) 2299189445c0a66d074dcded77b9c7322ef45422727George Mount width -= prec; 2309189445c0a66d074dcded77b9c7322ef45422727George Mount else 2319189445c0a66d074dcded77b9c7322ef45422727George Mount width -= strlen((char *)arg); 2329189445c0a66d074dcded77b9c7322ef45422727George Mount if(!(flags & minus_flag)) 2339189445c0a66d074dcded77b9c7322ef45422727George Mount while(width-- > 0) 2349189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char) (state, ' ')) 2359189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 2369189445c0a66d074dcded77b9c7322ef45422727George Mount if (prec != -1) { 2379189445c0a66d074dcded77b9c7322ef45422727George Mount while (*arg && prec--) 2389189445c0a66d074dcded77b9c7322ef45422727George Mount if ((*state->append_char) (state, *arg++)) 2399189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 2409189445c0a66d074dcded77b9c7322ef45422727George Mount } else { 2419189445c0a66d074dcded77b9c7322ef45422727George Mount while (*arg) 2429189445c0a66d074dcded77b9c7322ef45422727George Mount if ((*state->append_char) (state, *arg++)) 2439189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 2449189445c0a66d074dcded77b9c7322ef45422727George Mount } 2459189445c0a66d074dcded77b9c7322ef45422727George Mount if(flags & minus_flag) 2469189445c0a66d074dcded77b9c7322ef45422727George Mount while(width-- > 0) 2479189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char) (state, ' ')) 2489189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 2499189445c0a66d074dcded77b9c7322ef45422727George Mount return 0; 2509189445c0a66d074dcded77b9c7322ef45422727George Mount} 2519189445c0a66d074dcded77b9c7322ef45422727George Mount 2529189445c0a66d074dcded77b9c7322ef45422727George Mountstatic int 2539189445c0a66d074dcded77b9c7322ef45422727George Mountappend_char(struct state *state, 2549189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned char arg, 2559189445c0a66d074dcded77b9c7322ef45422727George Mount int width, 2569189445c0a66d074dcded77b9c7322ef45422727George Mount int flags) 2579189445c0a66d074dcded77b9c7322ef45422727George Mount{ 2589189445c0a66d074dcded77b9c7322ef45422727George Mount while(!(flags & minus_flag) && --width > 0) 2599189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char) (state, ' ')) 2609189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 2619189445c0a66d074dcded77b9c7322ef45422727George Mount 2629189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char) (state, arg)) 2639189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 2649189445c0a66d074dcded77b9c7322ef45422727George Mount while((flags & minus_flag) && --width > 0) 2659189445c0a66d074dcded77b9c7322ef45422727George Mount if((*state->append_char) (state, ' ')) 2669189445c0a66d074dcded77b9c7322ef45422727George Mount return 1; 2679189445c0a66d074dcded77b9c7322ef45422727George Mount 2689189445c0a66d074dcded77b9c7322ef45422727George Mount return 0; 2699189445c0a66d074dcded77b9c7322ef45422727George Mount} 2709189445c0a66d074dcded77b9c7322ef45422727George Mount 2719189445c0a66d074dcded77b9c7322ef45422727George Mount/* 2729189445c0a66d074dcded77b9c7322ef45422727George Mount * This can't be made into a function... 2739189445c0a66d074dcded77b9c7322ef45422727George Mount */ 2749189445c0a66d074dcded77b9c7322ef45422727George Mount 2759189445c0a66d074dcded77b9c7322ef45422727George Mount#define PARSE_INT_FORMAT(res, arg, unsig) \ 2769189445c0a66d074dcded77b9c7322ef45422727George Mountif (long_flag) \ 2779189445c0a66d074dcded77b9c7322ef45422727George Mount res = (unsig long)va_arg(arg, unsig long); \ 2789189445c0a66d074dcded77b9c7322ef45422727George Mountelse if (short_flag) \ 2799189445c0a66d074dcded77b9c7322ef45422727George Mount res = (unsig short)va_arg(arg, unsig int); \ 2809189445c0a66d074dcded77b9c7322ef45422727George Mountelse \ 2819189445c0a66d074dcded77b9c7322ef45422727George Mount res = (unsig int)va_arg(arg, unsig int) 2829189445c0a66d074dcded77b9c7322ef45422727George Mount 2839189445c0a66d074dcded77b9c7322ef45422727George Mount/* 2849189445c0a66d074dcded77b9c7322ef45422727George Mount * zyxprintf - return 0 or -1 2859189445c0a66d074dcded77b9c7322ef45422727George Mount */ 2869189445c0a66d074dcded77b9c7322ef45422727George Mount 2879189445c0a66d074dcded77b9c7322ef45422727George Mountstatic int 2889189445c0a66d074dcded77b9c7322ef45422727George Mountxyzprintf (struct state *state, const char *char_format, va_list ap) 2899189445c0a66d074dcded77b9c7322ef45422727George Mount{ 2909189445c0a66d074dcded77b9c7322ef45422727George Mount const unsigned char *format = (const unsigned char *)char_format; 2919189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned char c; 2929189445c0a66d074dcded77b9c7322ef45422727George Mount 2939189445c0a66d074dcded77b9c7322ef45422727George Mount while((c = *format++)) { 2949189445c0a66d074dcded77b9c7322ef45422727George Mount if (c == '%') { 2959189445c0a66d074dcded77b9c7322ef45422727George Mount int flags = 0; 2969189445c0a66d074dcded77b9c7322ef45422727George Mount int width = 0; 2979189445c0a66d074dcded77b9c7322ef45422727George Mount int prec = -1; 2989189445c0a66d074dcded77b9c7322ef45422727George Mount int long_flag = 0; 2999189445c0a66d074dcded77b9c7322ef45422727George Mount int short_flag = 0; 3009189445c0a66d074dcded77b9c7322ef45422727George Mount 3019189445c0a66d074dcded77b9c7322ef45422727George Mount /* flags */ 3029189445c0a66d074dcded77b9c7322ef45422727George Mount while((c = *format++)){ 3039189445c0a66d074dcded77b9c7322ef45422727George Mount if(c == '-') 3049189445c0a66d074dcded77b9c7322ef45422727George Mount flags |= minus_flag; 3059189445c0a66d074dcded77b9c7322ef45422727George Mount else if(c == '+') 3069189445c0a66d074dcded77b9c7322ef45422727George Mount flags |= plus_flag; 3079189445c0a66d074dcded77b9c7322ef45422727George Mount else if(c == ' ') 3089189445c0a66d074dcded77b9c7322ef45422727George Mount flags |= space_flag; 3099189445c0a66d074dcded77b9c7322ef45422727George Mount else if(c == '#') 3109189445c0a66d074dcded77b9c7322ef45422727George Mount flags |= alternate_flag; 3119189445c0a66d074dcded77b9c7322ef45422727George Mount else if(c == '0') 3129189445c0a66d074dcded77b9c7322ef45422727George Mount flags |= zero_flag; 3139189445c0a66d074dcded77b9c7322ef45422727George Mount else 3149189445c0a66d074dcded77b9c7322ef45422727George Mount break; 3159189445c0a66d074dcded77b9c7322ef45422727George Mount } 3169189445c0a66d074dcded77b9c7322ef45422727George Mount 3179189445c0a66d074dcded77b9c7322ef45422727George Mount if((flags & space_flag) && (flags & plus_flag)) 3189189445c0a66d074dcded77b9c7322ef45422727George Mount flags ^= space_flag; 3199189445c0a66d074dcded77b9c7322ef45422727George Mount 3209189445c0a66d074dcded77b9c7322ef45422727George Mount if((flags & minus_flag) && (flags & zero_flag)) 3219189445c0a66d074dcded77b9c7322ef45422727George Mount flags ^= zero_flag; 3229189445c0a66d074dcded77b9c7322ef45422727George Mount 3239189445c0a66d074dcded77b9c7322ef45422727George Mount /* width */ 3249189445c0a66d074dcded77b9c7322ef45422727George Mount if (isdigit(c)) 3259189445c0a66d074dcded77b9c7322ef45422727George Mount do { 3269189445c0a66d074dcded77b9c7322ef45422727George Mount width = width * 10 + c - '0'; 3279189445c0a66d074dcded77b9c7322ef45422727George Mount c = *format++; 3289189445c0a66d074dcded77b9c7322ef45422727George Mount } while(isdigit(c)); 3299189445c0a66d074dcded77b9c7322ef45422727George Mount else if(c == '*') { 3309189445c0a66d074dcded77b9c7322ef45422727George Mount width = va_arg(ap, int); 3319189445c0a66d074dcded77b9c7322ef45422727George Mount c = *format++; 3329189445c0a66d074dcded77b9c7322ef45422727George Mount } 3339189445c0a66d074dcded77b9c7322ef45422727George Mount 3349189445c0a66d074dcded77b9c7322ef45422727George Mount /* precision */ 3359189445c0a66d074dcded77b9c7322ef45422727George Mount if (c == '.') { 3369189445c0a66d074dcded77b9c7322ef45422727George Mount prec = 0; 3379189445c0a66d074dcded77b9c7322ef45422727George Mount c = *format++; 3389189445c0a66d074dcded77b9c7322ef45422727George Mount if (isdigit(c)) 3399189445c0a66d074dcded77b9c7322ef45422727George Mount do { 3409189445c0a66d074dcded77b9c7322ef45422727George Mount prec = prec * 10 + c - '0'; 3419189445c0a66d074dcded77b9c7322ef45422727George Mount c = *format++; 3429189445c0a66d074dcded77b9c7322ef45422727George Mount } while(isdigit(c)); 3439189445c0a66d074dcded77b9c7322ef45422727George Mount else if (c == '*') { 3449189445c0a66d074dcded77b9c7322ef45422727George Mount prec = va_arg(ap, int); 3459189445c0a66d074dcded77b9c7322ef45422727George Mount c = *format++; 3469189445c0a66d074dcded77b9c7322ef45422727George Mount } 3479189445c0a66d074dcded77b9c7322ef45422727George Mount } 3489189445c0a66d074dcded77b9c7322ef45422727George Mount 3499189445c0a66d074dcded77b9c7322ef45422727George Mount /* size */ 3509189445c0a66d074dcded77b9c7322ef45422727George Mount 3519189445c0a66d074dcded77b9c7322ef45422727George Mount if (c == 'h') { 3529189445c0a66d074dcded77b9c7322ef45422727George Mount short_flag = 1; 3539189445c0a66d074dcded77b9c7322ef45422727George Mount c = *format++; 3549189445c0a66d074dcded77b9c7322ef45422727George Mount } else if (c == 'l') { 3559189445c0a66d074dcded77b9c7322ef45422727George Mount long_flag = 1; 3569189445c0a66d074dcded77b9c7322ef45422727George Mount c = *format++; 3579189445c0a66d074dcded77b9c7322ef45422727George Mount } 3589189445c0a66d074dcded77b9c7322ef45422727George Mount 3599189445c0a66d074dcded77b9c7322ef45422727George Mount switch (c) { 3609189445c0a66d074dcded77b9c7322ef45422727George Mount case 'c' : 3619189445c0a66d074dcded77b9c7322ef45422727George Mount if(append_char(state, va_arg(ap, int), width, flags)) 3629189445c0a66d074dcded77b9c7322ef45422727George Mount return -1; 3639189445c0a66d074dcded77b9c7322ef45422727George Mount break; 3649189445c0a66d074dcded77b9c7322ef45422727George Mount case 's' : 3659189445c0a66d074dcded77b9c7322ef45422727George Mount if (append_string(state, 3669189445c0a66d074dcded77b9c7322ef45422727George Mount va_arg(ap, unsigned char*), 3679189445c0a66d074dcded77b9c7322ef45422727George Mount width, 3689189445c0a66d074dcded77b9c7322ef45422727George Mount prec, 3699189445c0a66d074dcded77b9c7322ef45422727George Mount flags)) 3709189445c0a66d074dcded77b9c7322ef45422727George Mount return -1; 3719189445c0a66d074dcded77b9c7322ef45422727George Mount break; 3729189445c0a66d074dcded77b9c7322ef45422727George Mount case 'd' : 3739189445c0a66d074dcded77b9c7322ef45422727George Mount case 'i' : { 3749189445c0a66d074dcded77b9c7322ef45422727George Mount long arg; 3759189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned long num; 3769189445c0a66d074dcded77b9c7322ef45422727George Mount int minusp = 0; 3779189445c0a66d074dcded77b9c7322ef45422727George Mount 3789189445c0a66d074dcded77b9c7322ef45422727George Mount PARSE_INT_FORMAT(arg, ap, signed); 3799189445c0a66d074dcded77b9c7322ef45422727George Mount 3809189445c0a66d074dcded77b9c7322ef45422727George Mount if (arg < 0) { 3819189445c0a66d074dcded77b9c7322ef45422727George Mount minusp = 1; 3829189445c0a66d074dcded77b9c7322ef45422727George Mount num = -arg; 3839189445c0a66d074dcded77b9c7322ef45422727George Mount } else 3849189445c0a66d074dcded77b9c7322ef45422727George Mount num = arg; 3859189445c0a66d074dcded77b9c7322ef45422727George Mount 3869189445c0a66d074dcded77b9c7322ef45422727George Mount if (append_number (state, num, 10, "0123456789", 3879189445c0a66d074dcded77b9c7322ef45422727George Mount width, prec, flags, minusp)) 3889189445c0a66d074dcded77b9c7322ef45422727George Mount return -1; 3899189445c0a66d074dcded77b9c7322ef45422727George Mount break; 3909189445c0a66d074dcded77b9c7322ef45422727George Mount } 3919189445c0a66d074dcded77b9c7322ef45422727George Mount case 'u' : { 3929189445c0a66d074dcded77b9c7322ef45422727George Mount unsigned long arg; 3939189445c0a66d074dcded77b9c7322ef45422727George Mount 3949189445c0a66d074dcded77b9c7322ef45422727George Mount PARSE_INT_FORMAT(arg, ap, unsigned); 3959189445c0a66d074dcded77b9c7322ef45422727George Mount 396 if (append_number (state, arg, 10, "0123456789", 397 width, prec, flags, 0)) 398 return -1; 399 break; 400 } 401 case 'o' : { 402 unsigned long arg; 403 404 PARSE_INT_FORMAT(arg, ap, unsigned); 405 406 if (append_number (state, arg, 010, "01234567", 407 width, prec, flags, 0)) 408 return -1; 409 break; 410 } 411 case 'x' : { 412 unsigned long arg; 413 414 PARSE_INT_FORMAT(arg, ap, unsigned); 415 416 if (append_number (state, arg, 0x10, "0123456789abcdef", 417 width, prec, flags, 0)) 418 return -1; 419 break; 420 } 421 case 'X' :{ 422 unsigned long arg; 423 424 PARSE_INT_FORMAT(arg, ap, unsigned); 425 426 if (append_number (state, arg, 0x10, "0123456789ABCDEF", 427 width, prec, flags, 0)) 428 return -1; 429 break; 430 } 431 case 'p' : { 432 unsigned long arg = (unsigned long)va_arg(ap, void*); 433 434 if (append_number (state, arg, 0x10, "0123456789ABCDEF", 435 width, prec, flags, 0)) 436 return -1; 437 break; 438 } 439 case 'n' : { 440 int *arg = va_arg(ap, int*); 441 *arg = state->s - state->str; 442 break; 443 } 444 case '\0' : 445 --format; 446 /* FALLTHROUGH */ 447 case '%' : 448 if ((*state->append_char)(state, c)) 449 return -1; 450 break; 451 default : 452 if ( (*state->append_char)(state, '%') 453 || (*state->append_char)(state, c)) 454 return -1; 455 break; 456 } 457 } else 458 if ((*state->append_char) (state, c)) 459 return -1; 460 } 461 return 0; 462} 463 464#ifndef HAVE_SNPRINTF 465int 466snprintf (char *str, size_t sz, const char *format, ...) 467{ 468 va_list args; 469 int ret; 470 471 va_start(args, format); 472 ret = vsnprintf (str, sz, format, args); 473 474#ifdef PARANOIA 475 { 476 int ret2; 477 char *tmp; 478 479 tmp = malloc (sz); 480 if (tmp == NULL) 481 abort (); 482 483 ret2 = vsprintf (tmp, format, args); 484 if (ret != ret2 || strcmp(str, tmp)) 485 abort (); 486 free (tmp); 487 } 488#endif 489 490 va_end(args); 491 return ret; 492} 493#endif 494 495#if 0 496#ifndef HAVE_ASPRINTF 497int 498asprintf (char **ret, const char *format, ...) 499{ 500 va_list args; 501 int val; 502 503 va_start(args, format); 504 val = vasprintf (ret, format, args); 505 506#ifdef PARANOIA 507 { 508 int ret2; 509 char *tmp; 510 tmp = malloc (val + 1); 511 if (tmp == NULL) 512 abort (); 513 514 ret2 = vsprintf (tmp, format, args); 515 if (val != ret2 || strcmp(*ret, tmp)) 516 abort (); 517 free (tmp); 518 } 519#endif 520 521 va_end(args); 522 return val; 523} 524#endif 525 526#ifndef HAVE_ASNPRINTF 527int 528asnprintf (char **ret, size_t max_sz, const char *format, ...) 529{ 530 va_list args; 531 int val; 532 533 va_start(args, format); 534 val = vasnprintf (ret, max_sz, format, args); 535 536#ifdef PARANOIA 537 { 538 int ret2; 539 char *tmp; 540 tmp = malloc (val + 1); 541 if (tmp == NULL) 542 abort (); 543 544 ret2 = vsprintf (tmp, format, args); 545 if (val != ret2 || strcmp(*ret, tmp)) 546 abort (); 547 free (tmp); 548 } 549#endif 550 551 va_end(args); 552 return val; 553} 554#endif 555 556#ifndef HAVE_VASPRINTF 557int 558vasprintf (char **ret, const char *format, va_list args) 559{ 560 return vasnprintf (ret, 0, format, args); 561} 562#endif 563 564 565#ifndef HAVE_VASNPRINTF 566int 567vasnprintf (char **ret, size_t max_sz, const char *format, va_list args) 568{ 569 int st; 570 size_t len; 571 struct state state; 572 573 state.max_sz = max_sz; 574 state.sz = 1; 575 state.str = malloc(state.sz); 576 if (state.str == NULL) { 577 *ret = NULL; 578 return -1; 579 } 580 state.s = state.str; 581 state.theend = state.s + state.sz - 1; 582 state.append_char = as_append_char; 583 state.reserve = as_reserve; 584 585 st = xyzprintf (&state, format, args); 586 if (st) { 587 free (state.str); 588 *ret = NULL; 589 return -1; 590 } else { 591 char *tmp; 592 593 *state.s = '\0'; 594 len = state.s - state.str; 595 tmp = realloc (state.str, len+1); 596 if (tmp == NULL) { 597 free (state.str); 598 *ret = NULL; 599 return -1; 600 } 601 *ret = tmp; 602 return len; 603 } 604} 605#endif 606#endif 607 608#ifndef HAVE_VSNPRINTF 609int 610vsnprintf (char *str, size_t sz, const char *format, va_list args) 611{ 612 struct state state; 613 int ret; 614 unsigned char *ustr = (unsigned char *)str; 615 616 state.max_sz = 0; 617 state.sz = sz; 618 state.str = ustr; 619 state.s = ustr; 620 state.theend = ustr + sz - 1; 621 state.append_char = sn_append_char; 622 state.reserve = sn_reserve; 623 624 ret = xyzprintf (&state, format, args); 625 *state.s = '\0'; 626 if (ret) 627 return sz; 628 else 629 return state.s - state.str; 630} 631#endif 632 633