From c7979573854d18508118919b945e629472fd7fd6 Mon Sep 17 00:00:00 2001 From: Amelia Coutard Date: Sat, 15 Oct 2022 12:01:17 +0200 Subject: [PATCH] Added actual string formatting to the printing. --- kernel/src/interrupts.cpp | 20 +++++----- kernel/src/kernel.cpp | 14 +------ kernel/src/paging.cpp | 5 +-- kernel/src/serial.cpp | 32 +++++++-------- kernel/src/serial.hpp | 82 +++++++++++++++++++++++++++++++++------ 5 files changed, 98 insertions(+), 55 deletions(-) diff --git a/kernel/src/interrupts.cpp b/kernel/src/interrupts.cpp index c80d7d1..dac7e27 100644 --- a/kernel/src/interrupts.cpp +++ b/kernel/src/interrupts.cpp @@ -71,7 +71,7 @@ extern "C" void int_device_not_available() { } extern "C" void int_double_fault(std::uint32_t err_code) { os::print("Interrupt: Double Fault.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_coprocessor_segment_overrun() { @@ -80,27 +80,27 @@ extern "C" void int_coprocessor_segment_overrun() { } extern "C" void int_invalid_TSS(std::uint32_t err_code) { os::print("Interrupt: Invalid TSS.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_segment_not_present(std::uint32_t err_code) { os::print("Interrupt: Segment Not Present.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_stack_segment_fault(std::uint32_t err_code) { os::print("Interrupt: Stack-Segment Fault.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_general_protection_fault(std::uint32_t err_code) { os::print("Interrupt: General Protection Fault.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_page_fault(std::uint32_t err_code) { os::print("Interrupt: Page Fault.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_x87_floating_point_exception() { @@ -109,7 +109,7 @@ extern "C" void int_x87_floating_point_exception() { } extern "C" void int_alignment_check(std::uint32_t err_code) { os::print("Interrupt: Alignment Check.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_machine_check() { @@ -126,7 +126,7 @@ extern "C" void int_virtualization_exception() { } extern "C" void int_control_protection_exception(std::uint32_t err_code) { os::print("Interrupt: Control Protection Exception.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_hypervisor_injection_exception() { @@ -135,12 +135,12 @@ extern "C" void int_hypervisor_injection_exception() { } extern "C" void int_VMM_communication_exception(std::uint32_t err_code) { os::print("Interrupt: VMM Communication Exception.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_security_exception(std::uint32_t err_code) { os::print("Interrupt: Security Exception.\n"); - os::print("Err code: "); os::print(err_code); os::print(".\n"); + os::print("Err code: {}.\n", err_code); while (true) { os::hlt(); } } extern "C" void int_default() { diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp index c48b654..2fd9d35 100644 --- a/kernel/src/kernel.cpp +++ b/kernel/src/kernel.cpp @@ -50,12 +50,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr"); - os::print(multiboot2::modules_mod_end(it) / 0x1000 * 0x1000); - os::print(": "); - os::print(multiboot2::modules_string(it)); - os::printc('\n'); + os::print("{}->{}: {}\n", multiboot2::modules_mod_start(it) / 0x1000 * 0x1000, multiboot2::modules_mod_end(it) / 0x1000 * 0x1000, multiboot2::modules_string(it)); test_module.start_address = os::phys_ptr(multiboot2::modules_mod_start(it) / 0x1000 * 0x1000); test_module.end_address = os::phys_ptr(multiboot2::modules_mod_end(it) / 0x1000 * 0x1000); // [s,e], not [s,e[ break; @@ -192,12 +187,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr= 0xFFFF'8000'0000'0000) { return; } - os::print(std::uint64_t(virt)); - os::print("->"); - os::print(std::uint64_t(phys.get_phys_addr())); - os::print(" ("); - os::print(size); - os::print(")\n"); + os::print("{}->{} ({})\n", std::uint64_t(virt), std::uint64_t(phys.get_phys_addr()), size); }); // Allow userspaaaaaaaaace in ring 3. Otherwise, we just immediately page fault. diff --git a/kernel/src/paging.cpp b/kernel/src/paging.cpp index 302a675..1b92b52 100644 --- a/kernel/src/paging.cpp +++ b/kernel/src/paging.cpp @@ -62,10 +62,7 @@ void os::paging::page_allocator_t::print_all() const { if (is_empty()) { os::print("No RAM left.\n"); } else for (auto it = begin(); it != end(); it = it->next) { - os::print(it.get_phys_addr()); - os::print("->"); - os::print((it + it->size).get_phys_addr()); - os::printc('\n'); + os::print("{}->{}\n", it.get_phys_addr(), (it + it->size).get_phys_addr()); } } diff --git a/kernel/src/serial.cpp b/kernel/src/serial.cpp index faa4113..8486245 100644 --- a/kernel/src/serial.cpp +++ b/kernel/src/serial.cpp @@ -39,40 +39,38 @@ void os::write_serial(std::uint8_t v) { void os::printc(char c) { write_serial(c); } -void os::print(const char* format, const char* val) { - os::assert(format[0] == '\0', "Format string unsupported. TODO."); +void os::print_formatted(const char* format, const char* val) { + os::assert(format[0] == '}', "Format string unsupported. TODO."); for (std::size_t i = 0; val[i] != '\0'; i++) { os::printc(val[i]); } } -void os::print(const char* format, std::uint64_t val) { - os::assert(format[0] == '\0', "Format string unsupported. TODO."); +void os::print_formatted(const char* format, std::uint64_t val) { + os::assert(format[0] == '}', "Format string unsupported. TODO."); for (int i = 60; i >= 0; i -= 4) { const int v = (val >> i) & 0xF; os::printc(v < 10 ? v + '0' : v - 10 + 'a'); } } -void os::print(const char* format, std::int64_t val) { - os::assert(format[0] == '\0', "Format string unsupported. TODO."); +void os::print_formatted(const char* format, std::int64_t val) { + os::assert(format[0] == '}', "Format string unsupported. TODO."); if (val < 0) { os::printc('-'); - os::print(format, std::uint64_t(-val)); + os::print_formatted(format, std::uint64_t(-val)); } else { os::printc(' '); - os::print(format, std::uint64_t(val)); + os::print_formatted(format, std::uint64_t(val)); } } -void os::print(const char* format, std::uint32_t val) { os::print(format, std::uint64_t(val)); } -void os::print(const char* format, std::uint16_t val) { os::print(format, std::uint64_t(val)); } -void os::print(const char* format, std::uint8_t val) { os::print(format, std::uint64_t(val)); } -void os::print(const char* format, std::int32_t val) { os::print(format, std::int64_t(val)); } -void os::print(const char* format, std::int16_t val) { os::print(format, std::int64_t(val)); } -void os::print(const char* format, std::int8_t val) { os::print(format, std::int64_t(val)); } +void os::print_formatted(const char* format, std::uint32_t val) { os::print_formatted(format, std::uint64_t(val)); } +void os::print_formatted(const char* format, std::uint16_t val) { os::print_formatted(format, std::uint64_t(val)); } +void os::print_formatted(const char* format, std::uint8_t val) { os::print_formatted(format, std::uint64_t(val)); } +void os::print_formatted(const char* format, std::int32_t val) { os::print_formatted(format, std::int64_t(val)); } +void os::print_formatted(const char* format, std::int16_t val) { os::print_formatted(format, std::int64_t(val)); } +void os::print_formatted(const char* format, std::int8_t val) { os::print_formatted(format, std::int64_t(val)); } void os::assert(bool cond, const char* diagnostic) { if (!cond) { - os::print("Error: "); - os::print(diagnostic); - os::printc('\n'); + os::print("Error: {}\n", diagnostic); os::cli(); while (true) { os::hlt(); } } diff --git a/kernel/src/serial.hpp b/kernel/src/serial.hpp index db4f368..0aa0f2b 100644 --- a/kernel/src/serial.hpp +++ b/kernel/src/serial.hpp @@ -13,19 +13,77 @@ std::uint8_t read_serial(); bool serial_transmit_empty(); void write_serial(std::uint8_t v); +void assert(bool cond, const char* diagnostic); + void printc(char c); -void print(const char* format, const char* val); -void print(const char* format, std::uint64_t val); -void print(const char* format, std::int64_t val); -void print(const char* format, std::uint32_t val); -void print(const char* format, std::int32_t val); -void print(const char* format, std::uint16_t val); -void print(const char* format, std::int16_t val); -void print(const char* format, std::uint8_t val); -void print(const char* format, std::int8_t val); -template void print(const T& val) { - print("", val); +void print_formatted(const char* format, const char* val); +void print_formatted(const char* format, std::uint64_t val); +void print_formatted(const char* format, std::int64_t val); +void print_formatted(const char* format, std::uint32_t val); +void print_formatted(const char* format, std::int32_t val); +void print_formatted(const char* format, std::uint16_t val); +void print_formatted(const char* format, std::int16_t val); +void print_formatted(const char* format, std::uint8_t val); +void print_formatted(const char* format, std::int8_t val); + +struct print_nth_helper { + std::size_t n; + const char* format; + + template inline print_nth_helper operator%(const T& v) { + if (n == 0) { + print_formatted(format, v); + return print_nth_helper{std::size_t(-1), format}; + } else { + return print_nth_helper{n - 1, format}; + } + } +}; + +template +void print(const char* format, const Ts&... vs) { + std::size_t arg_n = 0; + for (std::size_t i = 0; format[i] != '\0'; i++) { + if (format[i] == '{') { + i++; + if (format[i] == '\0') { + os::assert(false, "Error in format string: unterminated '{}'."); + } else if (format[i] == '{') { + printc('{'); + continue; + } else { + std::size_t format_spec_end = i; + while (format[format_spec_end] != '}') { + if (format[format_spec_end++] == '\0') { + os::assert(false, "Error in format string: unterminated '{}'."); + } + } + std::size_t n = arg_n; + if ('0' <= format[i] && format[i] <= '9') { + std::size_t n_ = 0; + while ('0' <= format[i] && format[i] <= '9') { + n_ = n_ * 10 + (format[i++] - '0'); + } + n = n_; + } + if (format[i] == ':') { + i++; + } else { + os::assert(format[i] == '}', "Error in format string: ':' required before format spec."); + } + os::assert(n < sizeof...(vs), "Error in format string: not enough arguments."); + (print_nth_helper{n, &format[i]} % ... % vs); + i = format_spec_end; + arg_n++; + } + } else if (format[i] == '}') { + os::assert(format[i + 1] == '}', "Error in format strin: unexpected '}'."); + i++; + printc('}'); + } else { + printc(format[i]); + } + } } -void assert(bool cond, const char* diagnostic); } -- 2.47.0