summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/lib/roken/snprintf.c
diff options
context:
space:
mode:
authornectar <nectar@FreeBSD.org>2002-02-19 15:46:56 +0000
committernectar <nectar@FreeBSD.org>2002-02-19 15:46:56 +0000
commit69a91bec14ec3ad49d1c8a82c40a796755f9e4a3 (patch)
tree85ecf91fd00875cec4b93111d3a8ed9eec9cddfe /crypto/heimdal/lib/roken/snprintf.c
parent8db4cdb3da4228a5d93635e43825e2e8a2f66db7 (diff)
downloadFreeBSD-src-69a91bec14ec3ad49d1c8a82c40a796755f9e4a3.zip
FreeBSD-src-69a91bec14ec3ad49d1c8a82c40a796755f9e4a3.tar.gz
Import of Heimdal Kerberos from KTH repository circa 2002/02/17.
Diffstat (limited to 'crypto/heimdal/lib/roken/snprintf.c')
-rw-r--r--crypto/heimdal/lib/roken/snprintf.c341
1 files changed, 186 insertions, 155 deletions
diff --git a/crypto/heimdal/lib/roken/snprintf.c b/crypto/heimdal/lib/roken/snprintf.c
index 205dc58..afb9754 100644
--- a/crypto/heimdal/lib/roken/snprintf.c
+++ b/crypto/heimdal/lib/roken/snprintf.c
@@ -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.
*
@@ -33,7 +33,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id: snprintf.c,v 1.28 2000/12/15 14:04:42 joda Exp $");
+RCSID("$Id: snprintf.c,v 1.33 2001/09/24 12:16:37 joda Exp $");
#endif
#include <stdio.h>
#include <stdarg.h>
@@ -54,38 +54,37 @@ enum format_flags {
* Common state
*/
-struct state {
+struct snprintf_state {
unsigned char *str;
unsigned char *s;
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 snprintf_state *, unsigned char);
/* XXX - methods */
};
-#ifndef HAVE_VSNPRINTF
+#if TEST_SNPRINTF
+#include "snprintf-test.h"
+#endif /* TEST_SNPRINTF */
+
+#if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF)
static int
-sn_reserve (struct state *state, size_t n)
+sn_reserve (struct snprintf_state *state, size_t n)
{
return state->s + n > state->theend;
}
-static int
-sn_append_char (struct state *state, unsigned char c)
+static void
+sn_append_char (struct snprintf_state *state, unsigned char c)
{
- if (sn_reserve (state, 1)) {
- return 1;
- } else {
+ if (!sn_reserve (state, 1))
*state->s++ = c;
- return 0;
- }
}
#endif
static int
-as_reserve (struct state *state, size_t n)
+as_reserve (struct snprintf_state *state, size_t n)
{
if (state->s + n > state->theend) {
int off = state->s - state->str;
@@ -107,24 +106,41 @@ as_reserve (struct state *state, size_t n)
return 0;
}
-static int
-as_append_char (struct state *state, unsigned char c)
+static void
+as_append_char (struct snprintf_state *state, unsigned char c)
{
- if(as_reserve (state, 1))
- return 1;
- else {
+ if(!as_reserve (state, 1))
*state->s++ = c;
- return 0;
- }
+}
+
+/* longest integer types */
+
+#ifdef HAVE_LONG_LONG
+typedef unsigned long long u_longest;
+typedef long long longest;
+#else
+typedef unsigned long u_longest;
+typedef long longest;
+#endif
+
+/*
+ * is # supposed to do anything?
+ */
+
+static int
+use_alternative (int flags, u_longest num, unsigned base)
+{
+ return flags & alternate_flag && (base == 16 || base == 8) && num != 0;
}
static int
-append_number(struct state *state,
- unsigned long num, unsigned base, char *rep,
+append_number(struct snprintf_state *state,
+ u_longest num, unsigned base, char *rep,
int width, int prec, int flags, int minusp)
{
int len = 0;
int i;
+ u_longest n = num;
/* given precision, ignore zero flag */
if(prec != -1)
@@ -132,23 +148,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 +170,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 +200,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,60 +210,71 @@ 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,
+append_string (struct snprintf_state *state,
+ 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
-append_char(struct state *state,
+append_char(struct snprintf_state *state,
unsigned char arg,
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;
}
@@ -264,6 +282,20 @@ append_char(struct state *state,
* This can't be made into a function...
*/
+#ifdef HAVE_LONG_LONG
+
+#define PARSE_INT_FORMAT(res, arg, unsig) \
+if (long_long_flag) \
+ res = (unsig long long)va_arg(arg, unsig long long); \
+else if (long_flag) \
+ res = (unsig long)va_arg(arg, unsig long); \
+else if (short_flag) \
+ res = (unsig short)va_arg(arg, unsig int); \
+else \
+ res = (unsig int)va_arg(arg, unsig int)
+
+#else
+
#define PARSE_INT_FORMAT(res, arg, unsig) \
if (long_flag) \
res = (unsig long)va_arg(arg, unsig long); \
@@ -272,23 +304,27 @@ else if (short_flag) \
else \
res = (unsig int)va_arg(arg, unsig int)
+#endif
+
/*
- * zyxprintf - return 0 or -1
+ * zyxprintf - return length, as snprintf
*/
static int
-xyzprintf (struct state *state, const char *char_format, va_list ap)
+xyzprintf (struct snprintf_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 == '%') {
- int flags = 0;
- int width = 0;
- int prec = -1;
- int long_flag = 0;
- int short_flag = 0;
+ int flags = 0;
+ int width = 0;
+ int prec = -1;
+ int long_long_flag = 0;
+ int long_flag = 0;
+ int short_flag = 0;
/* flags */
while((c = *format++)){
@@ -346,25 +382,28 @@ xyzprintf (struct state *state, const char *char_format, va_list ap)
} else if (c == 'l') {
long_flag = 1;
c = *format++;
+ if (c == 'l') {
+ long_long_flag = 1;
+ c = *format++;
+ }
}
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' : {
- long arg;
- unsigned long num;
+ longest arg;
+ u_longest num;
int minusp = 0;
PARSE_INT_FORMAT(arg, ap, signed);
@@ -375,57 +414,51 @@ 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' : {
- unsigned long arg;
+ u_longest arg;
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' : {
- unsigned long arg;
+ u_longest arg;
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' : {
- unsigned long arg;
+ u_longest arg;
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' :{
- unsigned long arg;
+ u_longest arg;
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 +470,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, ...)
{
@@ -462,6 +496,7 @@ snprintf (char *str, size_t sz, const char *format, ...)
va_start(args, format);
ret = vsnprintf (str, sz, format, args);
+ va_end(args);
#ifdef PARANOIA
{
@@ -472,19 +507,20 @@ snprintf (char *str, size_t sz, const char *format, ...)
if (tmp == NULL)
abort ();
+ va_start(args, format);
ret2 = vsprintf (tmp, format, args);
+ va_end(args);
if (ret != ret2 || strcmp(str, tmp))
abort ();
free (tmp);
}
#endif
- va_end(args);
return ret;
}
#endif
-#ifndef HAVE_ASPRINTF
+#if !defined(HAVE_ASPRINTF) || defined(TEST_SNPRINTF)
int
asprintf (char **ret, const char *format, ...)
{
@@ -493,6 +529,7 @@ asprintf (char **ret, const char *format, ...)
va_start(args, format);
val = vasprintf (ret, format, args);
+ va_end(args);
#ifdef PARANOIA
{
@@ -502,19 +539,20 @@ asprintf (char **ret, const char *format, ...)
if (tmp == NULL)
abort ();
+ va_start(args, format);
ret2 = vsprintf (tmp, format, args);
+ va_end(args);
if (val != ret2 || strcmp(*ret, tmp))
abort ();
free (tmp);
}
#endif
- va_end(args);
return val;
}
#endif
-#ifndef HAVE_ASNPRINTF
+#if !defined(HAVE_ASNPRINTF) || defined(TEST_SNPRINTF)
int
asnprintf (char **ret, size_t max_sz, const char *format, ...)
{
@@ -544,7 +582,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,13 +591,12 @@ 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;
+ struct snprintf_state state;
state.max_sz = max_sz;
state.sz = 1;
@@ -571,10 +608,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,24 +618,23 @@ 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)
{
- struct state state;
+ struct snprintf_state state;
int ret;
unsigned char *ustr = (unsigned char *)str;
@@ -607,16 +642,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
-
OpenPOWER on IntegriCloud