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);

Reply via email to