printf.9: Support more than 32 bits in %b
This will be usable after clang has been extended to accept length modifiers for %b when compiling kernel code. But we need FreeBSD to support it first... Reviewed by: markj, Timo Völker MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D54286
This commit is contained in:
+18
-7
@@ -24,7 +24,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd December 18, 2025
|
||||
.Dd December 19, 2025
|
||||
.Dt PRINTF 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -95,14 +95,15 @@ arguments.
|
||||
The base value is the output base (radix) expressed as an octal value;
|
||||
for example, \e10 gives octal and \e20 gives hexadecimal.
|
||||
The arguments are made up of a sequence of bit identifiers.
|
||||
Each bit identifier begins with an
|
||||
.Em octal
|
||||
value which is the number of the bit (starting from 1) this identifier
|
||||
describes.
|
||||
Each bit identifier begins with a character specifying the number of the bit
|
||||
(starting from 1) this identifier describes.
|
||||
The characters from \e01 to \e40 can be used to specify bit numbers in the
|
||||
range from 1 to 32 and characters from \e200 to \e377 to specify bit numbers
|
||||
in the range from 1 to 128.
|
||||
The rest of the identifier is a string of characters containing the name of
|
||||
the bit.
|
||||
The string is terminated by either the bit number at the start of the next
|
||||
bit identifier or
|
||||
The identifier is terminated by either the bit number at the start of the next
|
||||
bit identifier or by
|
||||
.Dv NUL
|
||||
for the last bit identifier.
|
||||
.Pp
|
||||
@@ -173,6 +174,16 @@ reg=3<BITTWO,BITONE>
|
||||
out: 41:41:5a:5a
|
||||
.Ed
|
||||
.Pp
|
||||
The same output will be generated by the following function:
|
||||
.Bd -literal -offset indent
|
||||
void
|
||||
printf_test(void)
|
||||
{
|
||||
printf("reg=%b\en", 3, "\e10\e201BITTWO\e200BITONE");
|
||||
printf("out: %4D\en", "AAZZ", ":");
|
||||
}
|
||||
.Ed
|
||||
.Pp
|
||||
The call
|
||||
.Bd -literal -offset indent
|
||||
log(LOG_DEBUG, "%s%d: been there.\en", sc->sc_name, sc->sc_unit);
|
||||
|
||||
+31
-9
@@ -628,6 +628,18 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
|
||||
return (p);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
isbitpos(char c)
|
||||
{
|
||||
return (c != '\0' && (c <= ' ' || (c & 0x80) != 0));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
isprintnospace(char c)
|
||||
{
|
||||
return (isprint(c) && c != ' ');
|
||||
}
|
||||
|
||||
/*
|
||||
* Scaled down version of printf(3).
|
||||
*
|
||||
@@ -640,9 +652,12 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
|
||||
*
|
||||
* where <base> is the output base expressed as a control character, e.g.
|
||||
* \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
|
||||
* the first of which gives the bit number to be inspected (origin 1), and
|
||||
* the next characters (up to a control character, i.e. a character <= 32),
|
||||
* give the name of the register. Thus:
|
||||
* the first of which gives the bit number to be inspected and the next
|
||||
* characters (up to the bit number of the next argument or a final NUL
|
||||
* character), give the name of the register.
|
||||
* The bit number can be encoded as a character between 1 and 32 or as a
|
||||
* character between 128 and 255.
|
||||
* Thus:
|
||||
*
|
||||
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE");
|
||||
*
|
||||
@@ -650,6 +665,10 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
|
||||
*
|
||||
* reg=3<BITTWO,BITONE>
|
||||
*
|
||||
* The same output would be generated by using:
|
||||
*
|
||||
* kvprintf("reg=%b\n", 3, "\10\201BITTWO\200BITONE");
|
||||
*
|
||||
* XXX: %D -- Hexdump, takes pointer and separator string:
|
||||
* ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
|
||||
* ("%*D", len, ptr, " " -> XX XX XX XX ...
|
||||
@@ -950,15 +969,18 @@ reswitch: switch (ch = (u_char)*fmt++) {
|
||||
if (bconv && num != 0) {
|
||||
/* %b conversion flag format. */
|
||||
tmp = retval;
|
||||
while (*q) {
|
||||
n = *q++;
|
||||
if (num & (1 << (n - 1))) {
|
||||
while (isbitpos(*q)) {
|
||||
if ((*q & 0x80) != 0)
|
||||
n = *q++ & 0x7f;
|
||||
else
|
||||
n = *q++ - 1;
|
||||
if (num & (1ULL << n)) {
|
||||
PCHAR(retval != tmp ?
|
||||
',' : '<');
|
||||
for (; (n = *q) > ' '; ++q)
|
||||
PCHAR(n);
|
||||
for (; isprintnospace(*q); ++q)
|
||||
PCHAR(*q);
|
||||
} else
|
||||
for (; *q > ' '; ++q)
|
||||
for (; isprintnospace(*q); ++q)
|
||||
continue;
|
||||
}
|
||||
if (retval != tmp) {
|
||||
|
||||
Reference in New Issue
Block a user