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
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd December 18, 2025
|
.Dd December 19, 2025
|
||||||
.Dt PRINTF 9
|
.Dt PRINTF 9
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -95,14 +95,15 @@ arguments.
|
|||||||
The base value is the output base (radix) expressed as an octal value;
|
The base value is the output base (radix) expressed as an octal value;
|
||||||
for example, \e10 gives octal and \e20 gives hexadecimal.
|
for example, \e10 gives octal and \e20 gives hexadecimal.
|
||||||
The arguments are made up of a sequence of bit identifiers.
|
The arguments are made up of a sequence of bit identifiers.
|
||||||
Each bit identifier begins with an
|
Each bit identifier begins with a character specifying the number of the bit
|
||||||
.Em octal
|
(starting from 1) this identifier describes.
|
||||||
value which is the number of the bit (starting from 1) this identifier
|
The characters from \e01 to \e40 can be used to specify bit numbers in the
|
||||||
describes.
|
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 rest of the identifier is a string of characters containing the name of
|
||||||
the bit.
|
the bit.
|
||||||
The string is terminated by either the bit number at the start of the next
|
The identifier is terminated by either the bit number at the start of the next
|
||||||
bit identifier or
|
bit identifier or by
|
||||||
.Dv NUL
|
.Dv NUL
|
||||||
for the last bit identifier.
|
for the last bit identifier.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -173,6 +174,16 @@ reg=3<BITTWO,BITONE>
|
|||||||
out: 41:41:5a:5a
|
out: 41:41:5a:5a
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.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
|
The call
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
log(LOG_DEBUG, "%s%d: been there.\en", sc->sc_name, sc->sc_unit);
|
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);
|
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).
|
* 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.
|
* 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,
|
* \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 first of which gives the bit number to be inspected and the next
|
||||||
* the next characters (up to a control character, i.e. a character <= 32),
|
* characters (up to the bit number of the next argument or a final NUL
|
||||||
* give the name of the register. Thus:
|
* 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");
|
* 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>
|
* 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:
|
* XXX: %D -- Hexdump, takes pointer and separator string:
|
||||||
* ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
|
* ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
|
||||||
* ("%*D", len, ptr, " " -> 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) {
|
if (bconv && num != 0) {
|
||||||
/* %b conversion flag format. */
|
/* %b conversion flag format. */
|
||||||
tmp = retval;
|
tmp = retval;
|
||||||
while (*q) {
|
while (isbitpos(*q)) {
|
||||||
n = *q++;
|
if ((*q & 0x80) != 0)
|
||||||
if (num & (1 << (n - 1))) {
|
n = *q++ & 0x7f;
|
||||||
|
else
|
||||||
|
n = *q++ - 1;
|
||||||
|
if (num & (1ULL << n)) {
|
||||||
PCHAR(retval != tmp ?
|
PCHAR(retval != tmp ?
|
||||||
',' : '<');
|
',' : '<');
|
||||||
for (; (n = *q) > ' '; ++q)
|
for (; isprintnospace(*q); ++q)
|
||||||
PCHAR(n);
|
PCHAR(*q);
|
||||||
} else
|
} else
|
||||||
for (; *q > ' '; ++q)
|
for (; isprintnospace(*q); ++q)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (retval != tmp) {
|
if (retval != tmp) {
|
||||||
|
|||||||
Reference in New Issue
Block a user