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