rewrite so that it does not stop as soon as there are no more

characters to print, we need to figure out how long the string would
have to be.  this also fixes snprintf(NULL, 0


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@10247 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Assar Westerlund
2001-07-02 23:13:23 +00:00
parent 26f783c592
commit 609e9edb25

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1995-2000 Kungliga Tekniska H<>gskolan
* Copyright (c) 1995-2001 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -60,27 +60,22 @@ struct state {
unsigned char *theend;
size_t sz;
size_t max_sz;
int (*append_char)(struct state *, unsigned char);
int (*reserve)(struct state *, size_t);
void (*append_char)(struct state *, unsigned char);
/* XXX - methods */
};
#ifndef HAVE_VSNPRINTF
#if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF)
static int
sn_reserve (struct state *state, size_t n)
{
return state->s + n > state->theend;
}
static int
static void
sn_append_char (struct state *state, unsigned char c)
{
if (sn_reserve (state, 1)) {
return 1;
} else {
if (!sn_reserve (state, 1))
*state->s++ = c;
return 0;
}
}
#endif
@@ -107,15 +102,21 @@ as_reserve (struct state *state, size_t n)
return 0;
}
static int
static void
as_append_char (struct state *state, unsigned char c)
{
if(as_reserve (state, 1))
return 1;
else {
if(!as_reserve (state, 1))
*state->s++ = c;
return 0;
}
}
/*
* is # supposed to do anything?
*/
static int
use_alternative (int flags, unsigned long num, unsigned base)
{
return flags & alternate_flag && (base == 16 || base == 8) && num != 0;
}
static int
@@ -125,6 +126,7 @@ append_number(struct state *state,
{
int len = 0;
int i;
unsigned long n = num;
/* given precision, ignore zero flag */
if(prec != -1)
@@ -132,23 +134,21 @@ append_number(struct state *state,
else
prec = 1;
/* zero value with zero precision -> "" */
if(prec == 0 && num == 0)
if(prec == 0 && n == 0)
return 0;
do{
if((*state->append_char)(state, rep[num % base]))
return 1;
len++;
num /= base;
}while(num);
(*state->append_char)(state, rep[n % base]);
++len;
n /= base;
} while(n);
prec -= len;
/* pad with prec zeros */
while(prec-- > 0){
if((*state->append_char)(state, '0'))
return 1;
len++;
(*state->append_char)(state, '0');
++len;
}
/* add length of alternate prefix (added later) to len */
if(flags & alternate_flag && (base == 16 || base == 8))
if(use_alternative(flags, num, base))
len += base / 8;
/* pad with zeros */
if(flags & zero_flag){
@@ -156,32 +156,26 @@ append_number(struct state *state,
if(minusp || (flags & space_flag) || (flags & plus_flag))
width--;
while(width-- > 0){
if((*state->append_char)(state, '0'))
return 1;
(*state->append_char)(state, '0');
len++;
}
}
/* add alternate prefix */
if(flags & alternate_flag && (base == 16 || base == 8)){
if(use_alternative(flags, num, base)){
if(base == 16)
if((*state->append_char)(state, rep[10] + 23)) /* XXX */
return 1;
if((*state->append_char)(state, '0'))
return 1;
(*state->append_char)(state, rep[10] + 23); /* XXX */
(*state->append_char)(state, '0');
}
/* add sign */
if(minusp){
if((*state->append_char)(state, '-'))
return 1;
len++;
(*state->append_char)(state, '-');
++len;
} else if(flags & plus_flag) {
if((*state->append_char)(state, '+'))
return 1;
len++;
(*state->append_char)(state, '+');
++len;
} else if(flags & space_flag) {
if((*state->append_char)(state, ' '))
return 1;
len++;
(*state->append_char)(state, ' ');
++len;
}
if(flags & minus_flag)
/* swap before padding with spaces */
@@ -192,9 +186,8 @@ append_number(struct state *state,
}
width -= len;
while(width-- > 0){
if((*state->append_char)(state, ' '))
return 1;
len++;
(*state->append_char)(state, ' ');
++len;
}
if(!(flags & minus_flag))
/* swap after padding with spaces */
@@ -203,42 +196,51 @@ append_number(struct state *state,
state->s[-i-1] = state->s[-len+i];
state->s[-len+i] = c;
}
return 0;
return len;
}
/*
* return length
*/
static int
append_string (struct state *state,
unsigned char *arg,
const unsigned char *arg,
int width,
int prec,
int flags)
{
int len = 0;
if(arg == NULL)
arg = (unsigned char*)"(null)";
arg = (const unsigned char*)"(null)";
if(prec != -1)
width -= prec;
else
width -= strlen((char *)arg);
width -= strlen((const char *)arg);
if(!(flags & minus_flag))
while(width-- > 0)
if((*state->append_char) (state, ' '))
return 1;
while(width-- > 0) {
(*state->append_char) (state, ' ');
++len;
}
if (prec != -1) {
while (*arg && prec--)
if ((*state->append_char) (state, *arg++))
return 1;
while (*arg && prec--) {
(*state->append_char) (state, *arg++);
++len;
}
} else {
while (*arg)
if ((*state->append_char) (state, *arg++))
return 1;
while (*arg) {
(*state->append_char) (state, *arg++);
++len;
}
}
if(flags & minus_flag)
while(width-- > 0)
if((*state->append_char) (state, ' '))
return 1;
return 0;
while(width-- > 0) {
(*state->append_char) (state, ' ');
++len;
}
return len;
}
static int
@@ -247,16 +249,18 @@ append_char(struct state *state,
int width,
int flags)
{
while(!(flags & minus_flag) && --width > 0)
if((*state->append_char) (state, ' '))
return 1;
if((*state->append_char) (state, arg))
return 1;
while((flags & minus_flag) && --width > 0)
if((*state->append_char) (state, ' '))
return 1;
int len = 0;
while(!(flags & minus_flag) && --width > 0) {
(*state->append_char) (state, ' ') ;
++len;
}
(*state->append_char) (state, arg);
++len;
while((flags & minus_flag) && --width > 0) {
(*state->append_char) (state, ' ');
++len;
}
return 0;
}
@@ -273,7 +277,7 @@ else \
res = (unsig int)va_arg(arg, unsig int)
/*
* zyxprintf - return 0 or -1
* zyxprintf - return length, as snprintf
*/
static int
@@ -281,6 +285,7 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
{
const unsigned char *format = (const unsigned char *)char_format;
unsigned char c;
int len = 0;
while((c = *format++)) {
if (c == '%') {
@@ -350,16 +355,15 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
switch (c) {
case 'c' :
if(append_char(state, va_arg(ap, int), width, flags))
return -1;
append_char(state, va_arg(ap, int), width, flags);
++len;
break;
case 's' :
if (append_string(state,
va_arg(ap, unsigned char*),
width,
prec,
flags))
return -1;
len += append_string(state,
va_arg(ap, unsigned char*),
width,
prec,
flags);
break;
case 'd' :
case 'i' : {
@@ -375,9 +379,8 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
} else
num = arg;
if (append_number (state, num, 10, "0123456789",
width, prec, flags, minusp))
return -1;
len += append_number (state, num, 10, "0123456789",
width, prec, flags, minusp);
break;
}
case 'u' : {
@@ -385,9 +388,8 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
PARSE_INT_FORMAT(arg, ap, unsigned);
if (append_number (state, arg, 10, "0123456789",
width, prec, flags, 0))
return -1;
len += append_number (state, arg, 10, "0123456789",
width, prec, flags, 0);
break;
}
case 'o' : {
@@ -395,9 +397,8 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
PARSE_INT_FORMAT(arg, ap, unsigned);
if (append_number (state, arg, 010, "01234567",
width, prec, flags, 0))
return -1;
len += append_number (state, arg, 010, "01234567",
width, prec, flags, 0);
break;
}
case 'x' : {
@@ -405,9 +406,8 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
PARSE_INT_FORMAT(arg, ap, unsigned);
if (append_number (state, arg, 0x10, "0123456789abcdef",
width, prec, flags, 0))
return -1;
len += append_number (state, arg, 0x10, "0123456789abcdef",
width, prec, flags, 0);
break;
}
case 'X' :{
@@ -415,17 +415,15 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
PARSE_INT_FORMAT(arg, ap, unsigned);
if (append_number (state, arg, 0x10, "0123456789ABCDEF",
width, prec, flags, 0))
return -1;
len += append_number (state, arg, 0x10, "0123456789ABCDEF",
width, prec, flags, 0);
break;
}
case 'p' : {
unsigned long arg = (unsigned long)va_arg(ap, void*);
if (append_number (state, arg, 0x10, "0123456789ABCDEF",
width, prec, flags, 0))
return -1;
len += append_number (state, arg, 0x10, "0123456789ABCDEF",
width, prec, flags, 0);
break;
}
case 'n' : {
@@ -437,23 +435,24 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
--format;
/* FALLTHROUGH */
case '%' :
if ((*state->append_char)(state, c))
return -1;
(*state->append_char)(state, c);
++len;
break;
default :
if ( (*state->append_char)(state, '%')
|| (*state->append_char)(state, c))
return -1;
(*state->append_char)(state, '%');
(*state->append_char)(state, c);
len += 2;
break;
}
} else
if ((*state->append_char) (state, c))
return -1;
} else {
(*state->append_char) (state, c);
++len;
}
}
return 0;
return len;
}
#ifndef HAVE_SNPRINTF
#if !defined(HAVE_SNPRINTF) || defined(TEST_SNPRINTF)
int
snprintf (char *str, size_t sz, const char *format, ...)
{
@@ -484,7 +483,7 @@ snprintf (char *str, size_t sz, const char *format, ...)
}
#endif
#ifndef HAVE_ASPRINTF
#if !defined(HAVE_ASPRINTF) || defined(TEST_SNPRINTF)
int
asprintf (char **ret, const char *format, ...)
{
@@ -514,7 +513,7 @@ asprintf (char **ret, const char *format, ...)
}
#endif
#ifndef HAVE_ASNPRINTF
#if !defined(HAVE_ASNPRINTF) || defined(TEST_SNPRINTF)
int
asnprintf (char **ret, size_t max_sz, const char *format, ...)
{
@@ -544,7 +543,7 @@ asnprintf (char **ret, size_t max_sz, const char *format, ...)
}
#endif
#ifndef HAVE_VASPRINTF
#if !defined(HAVE_VASPRINTF) || defined(TEST_SNPRINTF)
int
vasprintf (char **ret, const char *format, va_list args)
{
@@ -553,12 +552,11 @@ vasprintf (char **ret, const char *format, va_list args)
#endif
#ifndef HAVE_VASNPRINTF
#if !defined(HAVE_VASNPRINTF) || defined(TEST_SNPRINTF)
int
vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
{
int st;
size_t len;
struct state state;
state.max_sz = max_sz;
@@ -571,10 +569,9 @@ vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
state.s = state.str;
state.theend = state.s + state.sz - 1;
state.append_char = as_append_char;
state.reserve = as_reserve;
st = xyzprintf (&state, format, args);
if (st) {
if (st > state.sz) {
free (state.str);
*ret = NULL;
return -1;
@@ -582,20 +579,19 @@ vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
char *tmp;
*state.s = '\0';
len = state.s - state.str;
tmp = realloc (state.str, len+1);
tmp = realloc (state.str, st+1);
if (tmp == NULL) {
free (state.str);
*ret = NULL;
return -1;
}
*ret = tmp;
return len;
return st;
}
}
#endif
#ifndef HAVE_VSNPRINTF
#if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF)
int
vsnprintf (char *str, size_t sz, const char *format, va_list args)
{
@@ -607,16 +603,12 @@ vsnprintf (char *str, size_t sz, const char *format, va_list args)
state.sz = sz;
state.str = ustr;
state.s = ustr;
state.theend = ustr + sz - 1;
state.theend = ustr + sz - (sz > 0);
state.append_char = sn_append_char;
state.reserve = sn_reserve;
ret = xyzprintf (&state, format, args);
*state.s = '\0';
if (ret)
return sz;
else
return state.s - state.str;
if (state.s != NULL)
*state.s = '\0';
return ret;
}
#endif