Module Name: src
Committed By: pgoyette
Date: Wed May 13 02:50:32 UTC 2009
Modified Files:
src/common/lib/libutil: snprintb.c
src/distrib/sets/lists/base: md.amd64 shl.mi
src/distrib/sets/lists/comp: mi
src/include: util.h
src/lib/libutil: Makefile shlib_version snprintb.3
src/sys/lib/libkern: libkern.h
Log Message:
Implement snprintb_m(3) to provide multi-line bit/bit-field decode.
Discussed on tech-kern.
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/common/lib/libutil/snprintb.c
cvs rdiff -u -r1.48 -r1.49 src/distrib/sets/lists/base/md.amd64
cvs rdiff -u -r1.472 -r1.473 src/distrib/sets/lists/base/shl.mi
cvs rdiff -u -r1.1258 -r1.1259 src/distrib/sets/lists/comp/mi
cvs rdiff -u -r1.50 -r1.51 src/include/util.h
cvs rdiff -u -r1.60 -r1.61 src/lib/libutil/Makefile
cvs rdiff -u -r1.46 -r1.47 src/lib/libutil/shlib_version
cvs rdiff -u -r1.13 -r1.14 src/lib/libutil/snprintb.3
cvs rdiff -u -r1.90 -r1.91 src/sys/lib/libkern/libkern.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/common/lib/libutil/snprintb.c
diff -u src/common/lib/libutil/snprintb.c:1.4 src/common/lib/libutil/snprintb.c:1.5
--- src/common/lib/libutil/snprintb.c:1.4 Sun Jan 18 12:05:49 2009
+++ src/common/lib/libutil/snprintb.c Wed May 13 02:50:31 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: snprintb.c,v 1.4 2009/01/18 12:05:49 lukem Exp $ */
+/* $NetBSD: snprintb.c,v 1.5 2009/05/13 02:50:31 pgoyette Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
# include <sys/cdefs.h>
# if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: snprintb.c,v 1.4 2009/01/18 12:05:49 lukem Exp $");
+__RCSID("$NetBSD: snprintb.c,v 1.5 2009/05/13 02:50:31 pgoyette Exp $");
# endif
# include <sys/types.h>
@@ -51,7 +51,7 @@
# include <errno.h>
# else
# include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.4 2009/01/18 12:05:49 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: snprintb.c,v 1.5 2009/05/13 02:50:31 pgoyette Exp $");
# include <sys/param.h>
# include <sys/inttypes.h>
# include <sys/systm.h>
@@ -59,11 +59,14 @@
# endif
int
-snprintb(char *buf, size_t buflen, const char *bitfmt, uint64_t val)
+snprintb_m(char *buf, size_t buflen, const char *bitfmt, uint64_t val,
+ size_t l_max)
{
- char *bp = buf;
+ char *bp = buf, *s_bp = NULL;
+ const char *c_fmt, *s_fmt = NULL, *cur_fmt;
const char *sbase;
- int bit, ch, len, sep, flen;
+ int bit, ch, t_len, s_len = 0, l_len, f_len, v_len, sep;
+ int restart = 0;
uint64_t field;
#ifdef _KERNEL
@@ -89,12 +92,18 @@
goto internal;
}
- len = snprintf(bp, buflen, sbase, val);
- if (len < 0)
+ /* Reserve space for trailing blank line if needed */
+ if (l_max > 0)
+ buflen--;
+
+ t_len = snprintf(bp, buflen, sbase, val);
+ if (t_len < 0)
goto internal;
- if ((size_t)len < buflen)
- bp += len;
+ v_len = l_len = t_len;
+
+ if ((size_t)t_len < buflen)
+ bp += t_len;
else
bp += buflen - 1;
@@ -105,8 +114,55 @@
if ((val == 0) && (ch != '\177'))
goto terminate;
-#define PUTC(c) if ((size_t)(++len) < buflen) *bp++ = (c)
-#define PUTS(s) while ((ch = *(s)++) != 0) PUTC(ch)
+#define STORE(c) { l_len++; \
+ if ((size_t)(++t_len) < buflen) \
+ *bp++ = (c); \
+ } while ( /* CONSTCOND */ 0)
+
+#define BACKUP { if (s_bp != NULL) { \
+ bp = s_bp; s_bp = NULL; \
+ t_len -= l_len - s_len; \
+ restart = 1; \
+ bitfmt = s_fmt; \
+ } \
+ STORE('>'); STORE('\0'); \
+ if ((size_t)t_len < buflen) \
+ snprintf(bp, buflen - t_len, sbase, val); \
+ t_len += v_len; l_len = v_len; bp += v_len; \
+ } while ( /* CONSTCOND */ 0)
+
+#define PUTSEP \
+ if (l_max > 0 && (size_t)l_len >= l_max) { \
+ BACKUP; \
+ STORE('<'); \
+ } else { \
+ /* Remember separator location */ \
+ if ( l_max > 0 && sep != '<') { \
+ s_len = l_len; \
+ s_bp = bp; \
+ s_fmt = cur_fmt; \
+ } \
+ STORE(sep); \
+ restart = 0; \
+ } \
+
+#define PUTCHR(c) \
+ if (l_max > 0 && (size_t)l_len >= (l_max - 1)) { \
+ BACKUP; \
+ if (restart == 0) { \
+ STORE(c); \
+ } else \
+ sep = '<'; \
+ } else { \
+ STORE(c); \
+ restart = 0; \
+ } \
+
+#define PUTS(s) while ((ch = *(s)++) != 0) { \
+ PUTCHR(ch); \
+ if (restart) \
+ break; \
+ }
/*
* Chris Torek's new bitmask format is identified by a leading \177
@@ -114,12 +170,18 @@
sep = '<';
if (ch != '\177') {
/* old (standard) format. */
- for (;(bit = *bitfmt++) != 0;) {
+ for (;(bit = *bitfmt) != 0;) {
+ cur_fmt = bitfmt++;
if (val & (1 << (bit - 1))) {
- PUTC(sep);
- for (; (ch = *bitfmt) > ' '; ++bitfmt)
- PUTC(ch);
+ PUTSEP;
+ if (restart)
+ continue;
sep = ',';
+ for (; (ch = *bitfmt) > ' '; ++bitfmt) {
+ PUTCHR(ch);
+ if (restart)
+ break;
+ }
} else
for (; *bitfmt > ' '; ++bitfmt)
continue;
@@ -127,33 +189,50 @@
} else {
/* new quad-capable format; also does fields. */
field = val;
- while ((ch = *bitfmt++) != '\0') {
+ while (c_fmt = bitfmt, (ch = *bitfmt++) != '\0') {
bit = *bitfmt++; /* now 0-origin */
switch (ch) {
case 'b':
if (((u_int)(val >> bit) & 1) == 0)
goto skip;
- PUTC(sep);
+ cur_fmt = c_fmt;
+ PUTSEP;
+ if (restart)
+ break;
PUTS(bitfmt);
- sep = ',';
+ if (restart == 0)
+ sep = ',';
break;
case 'f':
case 'F':
- flen = *bitfmt++; /* field length */
+ cur_fmt = c_fmt;
+ f_len = *bitfmt++; /* field length */
field = (val >> bit) &
- (((uint64_t)1 << flen) - 1);
+ (((uint64_t)1 << f_len) - 1);
if (ch == 'F') /* just extract */
break;
- PUTC(sep);
- sep = ',';
- PUTS(bitfmt);
- PUTC('=');
- flen = snprintf(bp, buflen - len, sbase, field);
- if (flen < 0)
- goto internal;
- len += flen;
- if ((size_t)len < buflen)
- bp += flen;
+ PUTSEP;
+ if (restart == 0) {
+ sep = ',';
+ PUTS(bitfmt);
+ }
+ if (restart == 0) {
+ PUTCHR('=');
+ }
+ if (restart == 0) {
+ f_len = snprintf(bp, buflen - t_len,
+ sbase, field);
+ if (f_len < 0)
+ goto internal;
+ t_len += f_len;
+ l_len += f_len;
+ if ((size_t)t_len < buflen)
+ bp += f_len;
+ if (l_max > 0 &&
+ (size_t)l_len > l_max) {
+ PUTCHR('#');
+ }
+ }
break;
case '=':
case ':':
@@ -166,7 +245,7 @@
if ((int)field != bit)
goto skip;
if (ch == '=') {
- PUTC('=');
+ PUTCHR('=');
}
PUTS(bitfmt);
break;
@@ -178,16 +257,26 @@
}
}
}
- if (sep != '<') {
- PUTC('>');
- }
+ l_len++;
+ if ((size_t)(++t_len) < buflen)
+ *bp++ = '>';
terminate:
- *bp = '\0';
- return len;
+ *bp++ = '\0';
+ if (l_max != 0) {
+ t_len++;
+ *bp = '\0';
+ }
+ return t_len;
internal:
#ifndef _KERNEL
errno = EINVAL;
#endif
return -1;
}
+
+int
+snprintb(char *buf, size_t buflen, const char *bitfmt, uint64_t val)
+{
+ return snprintb_m(buf, buflen, bitfmt, val, 0);
+}
#endif
Index: src/distrib/sets/lists/base/md.amd64
diff -u src/distrib/sets/lists/base/md.amd64:1.48 src/distrib/sets/lists/base/md.amd64:1.49
--- src/distrib/sets/lists/base/md.amd64:1.48 Tue May 12 18:07:54 2009
+++ src/distrib/sets/lists/base/md.amd64 Wed May 13 02:50:31 2009
@@ -1,4 +1,4 @@
-# $NetBSD: md.amd64,v 1.48 2009/05/12 18:07:54 plunky Exp $
+# $NetBSD: md.amd64,v 1.49 2009/05/13 02:50:31 pgoyette Exp $
./dev/lms0 base-obsolete obsolete
./dev/mms0 base-obsolete obsolete
./usr/bin/fdformat base-util-bin
@@ -199,7 +199,7 @@
./usr/lib/i386/libusbhid.so.1 base-compat-shlib compat,pic
./usr/lib/i386/libusbhid.so.1.0 base-compat-shlib compat,pic
./usr/lib/i386/libutil.so.7 base-compat-shlib compat,pic
-./usr/lib/i386/libutil.so.7.16 base-compat-shlib compat,pic
+./usr/lib/i386/libutil.so.7.17 base-compat-shlib compat,pic
./usr/lib/i386/libwrap.so.1 base-compat-shlib compat,pic
./usr/lib/i386/libwrap.so.1.0 base-compat-shlib compat,pic
./usr/lib/i386/libz.so.1 base-compat-shlib compat,pic
Index: src/distrib/sets/lists/base/shl.mi
diff -u src/distrib/sets/lists/base/shl.mi:1.472 src/distrib/sets/lists/base/shl.mi:1.473
--- src/distrib/sets/lists/base/shl.mi:1.472 Tue May 12 18:07:54 2009
+++ src/distrib/sets/lists/base/shl.mi Wed May 13 02:50:31 2009
@@ -1,4 +1,4 @@
-# $NetBSD: shl.mi,v 1.472 2009/05/12 18:07:54 plunky Exp $
+# $NetBSD: shl.mi,v 1.473 2009/05/13 02:50:31 pgoyette Exp $
#
# Note: Don't delete entries from here - mark them as "obsolete" instead,
# unless otherwise stated below.
@@ -27,7 +27,7 @@
./lib/libradius.so.3.0 base-sys-shlib dynamicroot
./lib/libtermcap.so.0.6 base-sys-shlib dynamicroot
./lib/libtermlib.so.0.6 base-sys-shlib dynamicroot
-./lib/libutil.so.7.16 base-sys-shlib dynamicroot
+./lib/libutil.so.7.17 base-sys-shlib dynamicroot
./lib/libz.so.1.0 base-sys-shlib dynamicroot
./usr/lib/i18n/libBIG5.so.5.0 base-i18n-shlib
./usr/lib/i18n/libDECHanyu.so.5.0 base-i18n-shlib
@@ -152,7 +152,7 @@
./usr/lib/libtermlib.so.0.6 base-sys-shlib
./usr/lib/libukfs.so.1.0 base-sys-shlib
./usr/lib/libusbhid.so.1.0 base-sys-shlib
-./usr/lib/libutil.so.7.16 base-sys-shlib
+./usr/lib/libutil.so.7.17 base-sys-shlib
./usr/lib/libwrap.so.1.0 base-net-shlib
./usr/lib/libz.so.1.0 base-sys-shlib
./usr/lib/security/pam_afslog.so.2 base-sys-shlib kerberos,pam
Index: src/distrib/sets/lists/comp/mi
diff -u src/distrib/sets/lists/comp/mi:1.1258 src/distrib/sets/lists/comp/mi:1.1259
--- src/distrib/sets/lists/comp/mi:1.1258 Tue May 12 18:07:55 2009
+++ src/distrib/sets/lists/comp/mi Wed May 13 02:50:31 2009
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1258 2009/05/12 18:07:55 plunky Exp $
+# $NetBSD: mi,v 1.1259 2009/05/13 02:50:31 pgoyette Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@@ -7519,6 +7519,7 @@
./usr/share/man/cat3/sl_init.0 comp-c-catman .cat
./usr/share/man/cat3/sleep.0 comp-c-catman .cat
./usr/share/man/cat3/snprintb.0 comp-c-catman .cat
+./usr/share/man/cat3/snprintb_m.0 comp-c-catman .cat
./usr/share/man/cat3/snprintf.0 comp-c-catman .cat
./usr/share/man/cat3/sockaddr_snprintf.0 comp-c-catman .cat
./usr/share/man/cat3/sockatmark.0 comp-c-catman .cat
@@ -12899,6 +12900,7 @@
./usr/share/man/html3/sl_init.html comp-c-htmlman html
./usr/share/man/html3/sleep.html comp-c-htmlman html
./usr/share/man/html3/snprintb.html comp-c-htmlman html
+./usr/share/man/html3/snprintb_m.html comp-c-htmlman html
./usr/share/man/html3/snprintf.html comp-c-htmlman html
./usr/share/man/html3/sockaddr_snprintf.html comp-c-htmlman html
./usr/share/man/html3/sockatmark.html comp-c-htmlman html
@@ -18318,6 +18320,7 @@
./usr/share/man/man3/sl_init.3 comp-c-man .man
./usr/share/man/man3/sleep.3 comp-c-man .man
./usr/share/man/man3/snprintb.3 comp-c-man .man
+./usr/share/man/man3/snprintb_m.3 comp-c-man .man
./usr/share/man/man3/snprintf.3 comp-c-man .man
./usr/share/man/man3/sockaddr_snprintf.3 comp-c-man .man
./usr/share/man/man3/sockatmark.3 comp-c-man .man
Index: src/include/util.h
diff -u src/include/util.h:1.50 src/include/util.h:1.51
--- src/include/util.h:1.50 Sun Jan 11 03:04:12 2009
+++ src/include/util.h Wed May 13 02:50:32 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: util.h,v 1.50 2009/01/11 03:04:12 christos Exp $ */
+/* $NetBSD: util.h,v 1.51 2009/05/13 02:50:32 pgoyette Exp $ */
/*-
* Copyright (c) 1995
@@ -115,6 +115,7 @@
int pw_setprefix(const char *);
int raise_default_signal(int);
int secure_path(const char *);
+int snprintb_m(char *, size_t, const char *, uint64_t, size_t);
int snprintb(char *, size_t, const char *, uint64_t);
int sockaddr_snprintf(char *, size_t, const char *,
const struct sockaddr *);
Index: src/lib/libutil/Makefile
diff -u src/lib/libutil/Makefile:1.60 src/lib/libutil/Makefile:1.61
--- src/lib/libutil/Makefile:1.60 Sun Jan 18 12:13:32 2009
+++ src/lib/libutil/Makefile Wed May 13 02:50:32 2009
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.60 2009/01/18 12:13:32 lukem Exp $
+# $NetBSD: Makefile,v 1.61 2009/05/13 02:50:32 pgoyette Exp $
# @(#)Makefile 8.1 (Berkeley) 6/4/93
USE_SHLIBDIR= yes
@@ -77,5 +77,6 @@
MLINKS+=efun.3 evasprintf.3
MLINKS+=stat_flags.3 string_to_flags.3
MLINKS+=stat_flags.3 flags_to_string.3
+MLINKS+=snprintb.3 snprintb_m.3
.include <bsd.lib.mk>
Index: src/lib/libutil/shlib_version
diff -u src/lib/libutil/shlib_version:1.46 src/lib/libutil/shlib_version:1.47
--- src/lib/libutil/shlib_version:1.46 Sun Jan 11 02:57:18 2009
+++ src/lib/libutil/shlib_version Wed May 13 02:50:32 2009
@@ -1,5 +1,5 @@
-# $NetBSD: shlib_version,v 1.46 2009/01/11 02:57:18 christos Exp $
+# $NetBSD: shlib_version,v 1.47 2009/05/13 02:50:32 pgoyette Exp $
# Remember to update distrib/sets/lists/base/shl.* when changing
#
major=7
-minor=16
+minor=17
Index: src/lib/libutil/snprintb.3
diff -u src/lib/libutil/snprintb.3:1.13 src/lib/libutil/snprintb.3:1.14
--- src/lib/libutil/snprintb.3:1.13 Tue May 5 13:12:25 2009
+++ src/lib/libutil/snprintb.3 Wed May 13 02:50:32 2009
@@ -1,4 +1,4 @@
-.\" $NetBSD: snprintb.3,v 1.13 2009/05/05 13:12:25 pgoyette Exp $
+.\" $NetBSD: snprintb.3,v 1.14 2009/05/13 02:50:32 pgoyette Exp $
.\"
.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd May 5, 2009
+.Dd May 7, 2009
.Dt SNPRINTB 3
.Os
.Sh NAME
@@ -38,7 +38,10 @@
.Sh SYNOPSIS
.In util.h
.Ft int
-.Fn "snprintb" "char *buf" "size_t buflen" "const char *fmt" "uint_t val"
+.Fn "snprintb" "char *buf" "size_t buflen" "const char *fmt" "uint64_t val"
+.Ft int
+.Fn "snprintb_m" "char *buf" "size_t buflen" "const char *fmt" "uint64_t val" \
+"size_t max"
.Sh DESCRIPTION
The
.Fn snprintb
@@ -181,12 +184,43 @@
By convention, the format string has an additional NUL character at
the end, following that delimiting the last bit-position\(endescription
pair.
+.Pp
+The
+.Fn snprintb_m
+function accepts an additional
+.Fa max
+argument.
+If this argument is zero, the
+.Fn snprintb_m
+function returns exactly the same results in the
+.Fa buf
+as the
+.Fn snprintb
+function.
+If the
+.Fa max
+argument is present and has a non-zero value, it represents the maximum
+length of a formatted string.
+If the formatted string would require more than
+.Fa max
+characters, the
+.Fn snprintb_m
+function returns multiple formatted strings in the output buffer
+.Fa buf .
+Each string is NUL-terminated, and the last string is followed by an
+additional NUL character (or, if you prefer, a zero-length string).
.Sh RETURN VALUES
The
.Fn snprintb
-function returns the number of bytes that would have written to the buffer
-if there was adequate space, excluding the terminating NUL, or \-1 in case
-an error occurred.
+and
+.Fn snprintb_m
+functions return the number of bytes that would have written to the buffer
+if there was adequate space, excluding the final terminating NUL, or \-1 in
+case an error occurred.
+For
+.Fn snprintb_m ,
+the NUL characters terminating each individual string are included in the
+total number of bytes.
.Sh EXAMPLES
Two examples of the old formatting style:
.Bd -literal -offset indent
Index: src/sys/lib/libkern/libkern.h
diff -u src/sys/lib/libkern/libkern.h:1.90 src/sys/lib/libkern/libkern.h:1.91
--- src/sys/lib/libkern/libkern.h:1.90 Wed Mar 25 18:41:06 2009
+++ src/sys/lib/libkern/libkern.h Wed May 13 02:50:32 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: libkern.h,v 1.90 2009/03/25 18:41:06 tls Exp $ */
+/* $NetBSD: libkern.h,v 1.91 2009/05/13 02:50:32 pgoyette Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -335,6 +335,7 @@
unsigned long long strtoull(const char *, char **, int);
uintmax_t strtoumax(const char *, char **, int);
int snprintb(char *, size_t, const char *, uint64_t);
+int snprintb_m(char *, size_t, const char *, uint64_t, size_t);
int kheapsort(void *, size_t, size_t, int (*)(const void *, const void *),
void *);
uint32_t crc32(uint32_t, const uint8_t *, size_t);