printk: Add basic support for width modifier and zero padding
This adds basic support for width modifier when printing integers. Supported specifiers are u,i,d,x,X. Width '*' is not supported. Flag '0' for left-pading number with zero is also supported. examples: printk("0x%x 0x%02x 0x%04x 0x%08x\n", 1, 1, 1, 1); 0x1 0x01 0x0001 0x00000001 printk("0x%x 0x%2x 0x%4x 0x%8x\n", 1, 1, 1, 1); 0x1 0x 1 0x 1 0x 1 This should make printk usable for pretty printing u8 and u16 integers. Change-Id: I58fa869e9c295a052f97fbf052291ef4d132811e Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
This commit is contained in:
parent
7df7862749
commit
bde20d5447
2 changed files with 66 additions and 9 deletions
|
@ -27,8 +27,10 @@
|
|||
#include <toolchain.h>
|
||||
#include <sections.h>
|
||||
|
||||
static void _printk_dec_ulong(const unsigned long num);
|
||||
static void _printk_hex_ulong(const unsigned long num);
|
||||
static void _printk_dec_ulong(const unsigned long num, int pad_zero,
|
||||
int min_width);
|
||||
static void _printk_hex_ulong(const unsigned long num, int pad_zero,
|
||||
int min_width);
|
||||
|
||||
/**
|
||||
* @brief Default character output routine that does nothing
|
||||
|
@ -73,6 +75,8 @@ void __printk_hook_install(int (*fn)(int))
|
|||
static inline void _vprintk(const char *fmt, va_list ap)
|
||||
{
|
||||
int might_format = 0; /* 1 if encountered a '%' */
|
||||
int pad_zero = 0;
|
||||
int min_width = -1;
|
||||
|
||||
/* fmt has already been adjusted if needed */
|
||||
|
||||
|
@ -82,9 +86,24 @@ static inline void _vprintk(const char *fmt, va_list ap)
|
|||
_char_out((int)*fmt);
|
||||
} else {
|
||||
might_format = 1;
|
||||
min_width = -1;
|
||||
pad_zero = 0;
|
||||
}
|
||||
} else {
|
||||
switch (*fmt) {
|
||||
case '0':
|
||||
if (min_width < 0 && pad_zero == 0) {
|
||||
pad_zero = 1;
|
||||
goto still_might_format;
|
||||
}
|
||||
/* Fall through */
|
||||
case '1' ... '9':
|
||||
if (min_width < 0) {
|
||||
min_width = *fmt - '0';
|
||||
} else {
|
||||
min_width = 10 * min_width + *fmt - '0';
|
||||
}
|
||||
goto still_might_format;
|
||||
case 'z':
|
||||
case 'l':
|
||||
case 'h':
|
||||
|
@ -97,25 +116,29 @@ static inline void _vprintk(const char *fmt, va_list ap)
|
|||
if (d < 0) {
|
||||
_char_out((int)'-');
|
||||
d = -d;
|
||||
min_width--;
|
||||
}
|
||||
_printk_dec_ulong(d);
|
||||
_printk_dec_ulong(d, pad_zero, min_width);
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
unsigned long u = va_arg(
|
||||
ap, unsigned long);
|
||||
_printk_dec_ulong(u);
|
||||
_printk_dec_ulong(u, pad_zero, min_width);
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
_char_out('0');
|
||||
_char_out('x');
|
||||
/* left-pad pointers with zeros */
|
||||
pad_zero = 1;
|
||||
min_width = 8;
|
||||
/* Fall through */
|
||||
case 'x':
|
||||
case 'X': {
|
||||
unsigned long x = va_arg(
|
||||
ap, unsigned long);
|
||||
_printk_hex_ulong(x);
|
||||
_printk_hex_ulong(x, pad_zero, min_width);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
|
@ -183,14 +206,26 @@ void printk(const char *fmt, ...)
|
|||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static void _printk_hex_ulong(const unsigned long num)
|
||||
static void _printk_hex_ulong(const unsigned long num, int pad_zero,
|
||||
int min_width)
|
||||
{
|
||||
int size = sizeof(num) * 2;
|
||||
int found_largest_digit = 0;
|
||||
int remaining = 8; /* 8 digits max */
|
||||
|
||||
for (; size; size--) {
|
||||
char nibble = (num >> ((size - 1) << 2) & 0xf);
|
||||
nibble += nibble > 9 ? 87 : 48;
|
||||
_char_out((int)nibble);
|
||||
|
||||
if (nibble || found_largest_digit || size == 1) {
|
||||
found_largest_digit = 1;
|
||||
nibble += nibble > 9 ? 87 : 48;
|
||||
_char_out((int)nibble);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (remaining-- <= min_width) {
|
||||
_char_out((int)(pad_zero ? '0' : ' '));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,17 +238,27 @@ static void _printk_hex_ulong(const unsigned long num)
|
|||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static void _printk_dec_ulong(const unsigned long num)
|
||||
static void _printk_dec_ulong(const unsigned long num, int pad_zero,
|
||||
int min_width)
|
||||
{
|
||||
unsigned long pos = 999999999;
|
||||
unsigned long remainder = num;
|
||||
int found_largest_digit = 0;
|
||||
int remaining = 10; /* 10 digits max */
|
||||
|
||||
/* make sure we don't skip if value is zero */
|
||||
if (min_width <= 0) {
|
||||
min_width = 1;
|
||||
}
|
||||
|
||||
while (pos >= 9) {
|
||||
if (found_largest_digit || remainder > pos) {
|
||||
found_largest_digit = 1;
|
||||
_char_out((int)((remainder / (pos + 1)) + 48));
|
||||
} else if (remaining <= min_width) {
|
||||
_char_out((int)(pad_zero ? '0' : ' '));
|
||||
}
|
||||
remaining--;
|
||||
remainder %= (pos + 1);
|
||||
pos /= 10;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,12 @@ int (*_old_char_out)(int);
|
|||
char *expected = "22 113 10000 32768 40000 22\n"
|
||||
"p 112 -10000 -32768 -40000 -22\n"
|
||||
"0xcafebabe 0x0000beef\n"
|
||||
"0x1 0x01 0x0001 0x00000001\n"
|
||||
"0x1 0x 1 0x 1 0x 1\n"
|
||||
"42 42 0042 00000042\n"
|
||||
"-42 -42 -042 -0000042\n"
|
||||
"42 42 42 42\n"
|
||||
"42 42 0042 00000042\n"
|
||||
;
|
||||
|
||||
|
||||
|
@ -67,6 +73,12 @@ void printk_test(void)
|
|||
printk("%zu %hhu %hu %u %lu %llu\n", stv, uc, usi, ui, ul, ull);
|
||||
printk("%c %hhd %hd %d %ld %lld\n", c, c, ssi, si, sl, sll);
|
||||
printk("0x%x %p\n", hex, ptr);
|
||||
printk("0x%x 0x%02x 0x%04x 0x%08x\n", 1, 1, 1, 1);
|
||||
printk("0x%x 0x%2x 0x%4x 0x%8x\n", 1, 1, 1, 1);
|
||||
printk("%d %02d %04d %08d\n", 42, 42, 42, 42);
|
||||
printk("%d %02d %04d %08d\n", -42, -42, -42, -42);
|
||||
printk("%u %2u %4u %8u\n", 42, 42, 42, 42);
|
||||
printk("%u %02u %04u %08u\n", 42, 42, 42, 42);
|
||||
|
||||
ram_console[pos] = '\0';
|
||||
assert_true((strcmp(ram_console, expected) == 0), "printk failed");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue