From cce35f64d37b091c4525f63a9ec9dc384bd10b54 Mon Sep 17 00:00:00 2001 From: Alan Jian Date: Sat, 30 Mar 2024 13:37:27 +0800 Subject: [PATCH] Implement integer format specifiers --- include/types.h | 2 +- src/kmain.c | 1 + src/kprintf.c | 70 +++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/include/types.h b/include/types.h index 6083005..8e92ef9 100644 --- a/include/types.h +++ b/include/types.h @@ -15,6 +15,6 @@ typedef int32_t i32; typedef int64_t i64; typedef uintptr_t usize; -typedef uintptr_t ssize; +typedef intptr_t ssize; #endif // TYPES_H_ diff --git a/src/kmain.c b/src/kmain.c index b8f9e9a..b6343a6 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -1,5 +1,6 @@ #include #include +#include #include noreturn void kmain(void) { diff --git a/src/kprintf.c b/src/kprintf.c index 3163c1e..a51eb2a 100644 --- a/src/kprintf.c +++ b/src/kprintf.c @@ -1,7 +1,50 @@ #include - +#include #include +static void print_usize(usize val, i32 radix) { + if (val == 0) { + uart_putc('0'); + return; + } + + char buf[(usize) (sizeof(val) * 8.0 / 3 + 1)]; + usize pos = sizeof(buf); + + while (val != 0) { + pos--; + u8 digit = val % radix; + if (digit < 10) + buf[pos] = digit + '0'; + else + buf[pos] = digit - 10 + 'a'; + val /= radix; + } + + for (usize i = pos; i < sizeof(buf); i++) + uart_putc(buf[i]); +} + +static void print_ssize(ssize val, i32 radix) { + if (val < 0) { + uart_putc('-'); + val = -val; + } + + print_usize(val, radix); +} + +static void print_ptr(void *ptr) { + for (usize i = sizeof(ptr) * 2; i > 0; i--) { + u8 nibble = (usize) ptr >> ((i - 1) * 4) & 0xF; + if (nibble < 10) { + uart_putc(nibble + '0'); + } else { + uart_putc(nibble - 10 + 'a'); + } + } +} + void kprintf(const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -16,17 +59,34 @@ void kprintf(const char *fmt, ...) { fmt++; switch (*fmt++) { - case 'c': { - char c = va_arg(args, int); - uart_putc(c); + case '%': + uart_putc('%'); + break; + case 'c': + uart_putc(va_arg(args, int)); break; - } case 's': { const char *s = va_arg(args, const char *); for (; *s; s++) uart_putc(*s); break; } + case 'd': + case 'i': + print_ssize(va_arg(args, int), 10); + break; + case 'o': + print_usize(va_arg(args, unsigned), 8); + break; + case 'x': + print_usize(va_arg(args, unsigned), 16); + break; + case 'u': + print_usize(va_arg(args, unsigned), 10); + break; + case 'p': + print_ptr(va_arg(args, void *)); + break; } }