From 4ebf244d3bbee104ac41c61bf1c50566d7fe2964 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 19 Nov 2022 13:15:13 +0100 Subject: [PATCH] Support printing some integers in output_integer --- kernel/src/main.cpp | 2 + luna/Format.h | 147 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index e0c7d376..258e35ee 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -26,6 +26,8 @@ extern "C" [[noreturn]] void _start() const u64 address = 0xfffffffff8000000; + Serial::printf("Mapping address 0x%lx\n", address); + u64 physical = MemoryManager::alloc_physical_page().release_value(); auto rc = MMU::map(address, physical, MMU::ReadWrite); diff --git a/luna/Format.h b/luna/Format.h index 1be99216..c683d882 100644 --- a/luna/Format.h +++ b/luna/Format.h @@ -200,9 +200,152 @@ static bool is_integer_format_specifier(char c) return (c == 'd') || (c == 'i') || (c == 'u') || (c == 'x') || (c == 'X') || (c == 'o') || (c == 'b'); } -static int output_integer(char, const conv_state&, format_state&, va_list) +template static usize to_string(T value, T base, char* buf, usize max, bool uppercase) { - return -1; // FIXME: Implement this. + usize i = 0; + if (!value && max) + { + buf[i] = '0'; + return 1; + } + do { + int digit = (int)(value % base); + char c = (char)(digit < 10 ? '0' + digit : ((uppercase ? 'A' : 'a') + (digit - 10))); + buf[i++] = c; + value /= base; + } while (value && i < max); + return i; +} + +static int output_integer(char specifier, const conv_state& vstate, format_state& state, va_list ap) +{ + usize base = 10; + bool is_signed = false; + bool uppercase = false; + bool negative = false; + + if (specifier == 'd' || specifier == 'i') is_signed = true; + switch (specifier) + { + case 'x': + case 'X': base = 16; break; + case 'o': base = 8; break; + case 'b': base = 2; break; + default: break; + } + if (specifier == 'X') uppercase = true; + + char buf[1024]; + usize buflen; + if (vstate.flags & FLAG_CHAR) + { + if (is_signed) + { + char v = (char)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (char)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned char v = (unsigned char)va_arg(ap, unsigned int); + buflen = to_string(v, (unsigned char)base, buf, sizeof(buf), uppercase); + } + } + else if (vstate.flags & FLAG_SHORT) + { + if (is_signed) + { + short v = (short)va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (short)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned short v = (unsigned short)va_arg(ap, unsigned int); + buflen = to_string(v, (unsigned short)base, buf, sizeof(buf), uppercase); + } + } + else if (vstate.flags & FLAG_LONG_LONG) + { + if (is_signed) + { + long long v = va_arg(ap, long long); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (long long)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned long long v = va_arg(ap, unsigned long long); + buflen = to_string(v, (unsigned long long)base, buf, sizeof(buf), uppercase); + } + } + else if (vstate.flags & FLAG_LONG) + { + if (is_signed) + { + long v = va_arg(ap, long); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (long)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned long v = va_arg(ap, unsigned long); + buflen = to_string(v, (unsigned long)base, buf, sizeof(buf), uppercase); + } + } + else + { + if (is_signed) + { + int v = va_arg(ap, int); + if (v < 0) + { + v = -v; + negative = true; + } + buflen = to_string(v, (int)base, buf, sizeof(buf), uppercase); + } + else + { + unsigned int v = va_arg(ap, unsigned int); + buflen = to_string(v, (unsigned int)base, buf, sizeof(buf), uppercase); + } + } + + // FIXME: Start padding and alternate forms. + + if (buflen < sizeof(buf)) + { + if (negative) buf[buflen++] = '-'; + else if (vstate.flags & FLAG_SIGN) + buf[buflen++] = '+'; + else if (vstate.flags & FLAG_BLANK_SIGNED) + buf[buflen++] = ' '; + } + + usize i = buflen; + + while (i--) TRY_PUTCHAR(buf[i], state); + + TRY_END_PAD(vstate, state, buflen); + + return 0; } #endif