From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Sat, 15 Oct 2022 10:01:17 +0000 (+0200)
Subject: Added actual string formatting to the printing.
X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=c7979573854d18508118919b945e629472fd7fd6;p=voyage-au-centre-des-fichiers.git

Added actual string formatting to the printing.
---

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<const multiboot2::info_s
 				}
 				break;
 			case multiboot2::info::type_t::modules:
-				os::print(multiboot2::modules_mod_start(it) / 0x1000 * 0x1000);
-				os::print("->");
-				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<os::paging::page>(multiboot2::modules_mod_start(it) / 0x1000 * 0x1000);
 				test_module.end_address   = os::phys_ptr<os::paging::page>(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<const multiboot2::info_s
 		if (std::uint64_t(virt) >= 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 <typename T> 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 <typename T> 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<typename... Ts>
+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);
 
 }