| SNPRINTB(3) | Library Functions Manual | SNPRINTB(3) |
snprintb,
snprintb_m — bitmask output
conversion
System Utilities Library (libutil, -lutil)
#include
<util.h>
int
snprintb(char
*buf, size_t
bufsize, const char
*fmt, uint64_t
val);
int
snprintb_m(char
*buf, size_t
bufsize, const char
*fmt, uint64_t val,
size_t max);
The
snprintb()
function formats a bitmask into a mnemonic form suitable for printing.
It formats the integer val
into the buffer buf, of size
bufsize, interpreting the bits within that integer as
flags or groups of bits. The buffer is always NUL-terminated. If the buffer
buf is too small to hold the formatted output,
snprintb()
will fill as much as it can, and return the number of bytes that it would
have written if the buffer were long enough excluding the terminating NUL.
If bufsize is zero, nothing is written and
buf may be a null pointer.
The
snprintb_m()
function accepts an additional max argument. If this
argument is zero, the snprintb_m() function behaves
exactly like the snprintb() function. If the
max argument has a non-zero value, it represents the
maximum length of a formatted string. If the formatted string would require
more than max characters, the
snprintb_m() function returns multiple formatted
strings in the output buffer 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).
The decoding directive in fmt describes how the bitfield is to be interpreted and displayed. It follows two possible formats, referred to as “old” and “new”. The “old” format is limited to describing single bits in a 32-bit value, the bit positions are 1-based. The “new” format supports multi-bit fields and 64-bit values, the bit positions are 0-based.
If the first character of fmt is (in C
escape-character format) ‘\177’ or
‘\x7f’, the remainder of the
fmt argument follows the “new”
format.
The next character (the first for the “old” format)
specifies the numeral base in which to print the numbers in the output. The
possible values are ‘\010’ or
‘\x08’ for octal,
‘\012’ or
‘\x0a’ for decimal, and
‘\020’ or
‘\x10’ for hexadecimal.
The remaining characters in the fmt argument represent the formatting conversions, according to the “old” or “new” format.
In the “old” format, each conversion specifies a bit position and a description that is printed if the corresponding bit is set.
The bit position is a 1-based single-byte binary value, ranging
from ‘\001’ or
‘\x01’ (1) for the least significant
bit up to ‘\040’ or
‘\x20’ (32) for the most significant
bit.
The description is delimited by the next character whose value is 32 or less (see ascii(7)), or by the end of the format string itself.
In the “new” format, each conversion begins with a
conversion type, followed by type-specific parameters, each encoded as a
single byte, followed by a NUL-terminated description. The bit positions are
0-based, ranging from ‘\000’ or
‘\x00’ (0) for the least significant
bit to ‘\077’ or
‘\x3f’ (63) for the most significant
bit.
b
bit descrf
lsb width
descr=’ and
‘*’ conversions below.=
cmp descrf’ conversion to the single-byte
value cmp, ranging from
‘\000’ or
‘\x00’ (0) to
‘\377’ or
‘\xff’ (255). If they are equal,
prints ‘=’ followed by the
description from descr. This conversion may be
repeated.F
lsb width
[descr]f’, but just extracts the value for
use with the ‘:’ and
‘*’ conversions below. The
description from descr is ignored, it is only
present for uniformity with the other conversions.:
cmp descrF’ conversion to the single-byte
value cmp, ranging from
‘\000’ or
‘\x00’ (0) to
‘\377’ or
‘\xff’ (255). If they are equal,
prints the description from descr. This conversion
may be repeated.*
fmt=’ or
‘:’ conversions matched, prints the
format string fmt via
snprintf(3). The format
string fmt may contain a single
uintmax_t conversion specification to print the
field value that did not match.The new format is terminated by an additional NUL character at the end, following that delimiting the last conversion. This NUL is supplied by the compiler to terminate the string literal and doesn't need to be written explicitly.
The snprintb() and
snprintb_m() functions return the number of bytes
that they would have written to the buffer if there was adequate space,
excluding the final terminating NUL, or -1 in case an error occurred. For
snprintb_m(), the NUL characters terminating each
individual string are included in the total number of bytes.
Two examples of the old formatting style:
snprintb(buf, bufsize, "\010\002BITTWO\001BITONE", 3)
⇒ "03<BITTWO,BITONE>"
snprintb(buf, bufsize,
"\x10"
"\x10" "NOTBOOT"
"\x0f" "FPP"
"\x0e" "SDVMA"
"\x0c" "VIDEO"
"\x0b" "LORES"
"\x0a" "FPA"
"\x09" "DIAG"
"\x07" "CACHE"
"\x06" "IOCACHE"
"\x05" "LOOPBACK"
"\x04" "DBGCACHE",
0xe860)
⇒ "0xe860<NOTBOOT,FPP,SDVMA,VIDEO,CACHE,IOCACHE>"
An example of the new formatting style:
snprintb(buf, bufsize,
"\177\020"
"b\000" "LSB\0"
"b\001" "BITONE\0"
"f\004\004" "NIBBLE2\0"
"f\020\004" "BURST\0"
"=\x04" "FOUR\0"
"=\x0f" "FIFTEEN\0"
"b\037" "MSB\0",
0x800f0701)
⇒ "0x800f0701<LSB,NIBBLE2=0,BURST=0xf=FIFTEEN,MSB>"
The same example using snprintb_m:
snprintb_m(buf, bufsize,
"\177\020"
"b\000" "LSB\0"
"b\001" "BITONE\0"
"f\004\004" "NIBBLE2\0"
"f\020\004" "BURST\0"
"=\x04" "FOUR\0"
"=\x0f" "FIFTEEN\0"
"b\037" "MSB\0",
0x800f0701, 34)
⇒ "0x800f0701<LSB,NIBBLE2=0>\0"
"0x800f0701<BURST=0xf=FIFTEEN,MSB>\0"
""
A more complex example from
<sys/mman.h> that uses both
the single-bit ‘b’ formatting as well
as the multi-bit field ‘F’ formatting
with a default ‘*’:
#define MAP_FMT "\177\020" \
"b\0" "SHARED\0" \
"b\1" "PRIVATE\0" \
"b\2" "COPY\0" \
"b\4" "FIXED\0" \
"b\5" "RENAME\0" \
"b\6" "NORESERVE\0" \
"b\7" "INHERIT\0" \
"b\11" "HASSEMAPHORE\0" \
"b\12" "TRYFIXED\0" \
"b\13" "WIRED\0" \
"F\14\1\0" \
":\0" "FILE\0" \
":\1" "ANONYMOUS\0" \
"b\15" "STACK\0" \
"F\30\010\0" \
":\000" "ALIGN=NONE\0" \
":\012" "ALIGN=1KB\0" \
":\013" "ALIGN=2KB\0" \
":\014" "ALIGN=4KB\0" \
":\015" "ALIGN=8KB\0" \
":\016" "ALIGN=16KB\0" \
":\017" "ALIGN=32KB\0" \
":\020" "ALIGN=64KB\0" \
":\021" "ALIGN=128KB\0" \
":\022" "ALIGN=256KB\0" \
":\023" "ALIGN=512KB\0" \
":\024" "ALIGN=1MB\0" \
":\025" "ALIGN=2MB\0" \
":\026" "ALIGN=4MB\0" \
":\027" "ALIGN=8MB\0" \
":\030" "ALIGN=16MB\0" \
":\034" "ALIGN=256MB\0" \
":\040" "ALIGN=4GB\0" \
":\044" "ALIGN=64GB\0" \
":\050" "ALIGN=1TB\0" \
":\054" "ALIGN=16TB\0" \
":\060" "ALIGN=256TB\0" \
":\064" "ALIGN=4PB\0" \
":\070" "ALIGN=64PB\0" \
":\074" "ALIGN=1EB\0" \
"*" "ALIGN=2^%ju\0"
snprintb(buf, bufsize, MAP_FMT, 0x0d001234)
⇒ "0xd001234<COPY,FIXED,RENAME,HASSEMAPHORE,ANONYMOUS,ALIGN=8KB>"
snprintb(buf, bufsize, MAP_FMT, 0x2e000000)
⇒ "0x2e000000<FILE,ALIGN=2^46>"
snprintb() will fail if:
EINVAL]snprintf() failed.The snprintb() function was originally
implemented as a non-standard %b format string for
the kernel printf() function in
NetBSD 1.5 and earlier releases. It was called
bitmask_snprintf() in NetBSD
5.0 and earlier releases.
The “new” format was the invention of Chris Torek.
When using hexadecimal character escapes for bit positions or
field widths, if a following description starts with one of the letters A to
F, that letter is considered part of the character escape. In such a
situation, the character escape and the description must be put into
separate string literals, as in "\x0f"
"FIFTEEN".
| April 8, 2024 | NetBSD 11.0 |