]> git.ameliathe1st.gay Git - voyage-au-centre-des-fichiers.git/commitdiff
Remplacement de os::assert par une macro assert dans la "librairie standard"
authorAmelia Coutard <eliottulio.coutard@gmail.com>
Fri, 29 Dec 2023 03:29:14 +0000 (04:29 +0100)
committerAmelia Coutard <eliottulio.coutard@gmail.com>
Fri, 29 Dec 2023 03:29:43 +0000 (04:29 +0100)
kernel/src/elf64.cpp
kernel/src/interrupts.cpp
kernel/src/interrupts.hpp
kernel/src/kernel.cpp
kernel/src/lib/phys_ptr.hpp
kernel/src/paging.hpp
kernel/src/ring3.cpp
kernel/src/serial.cpp
kernel/src/serial.hpp
kernel/src/utils.hpp
libcpp/assert.hpp [new file with mode: 0644]

index d5df9d90777454787c0492f1e12761335c721c71..9ced6fbc8e7848627278e429dcad0f7f03f7585a 100644 (file)
 // not, see <https://www.gnu.org/licenses/>.
 
 #include "elf64.hpp"
+#include <assert.hpp>
 
 void os::elf::load_elf(os::process& result, amy::byte* start, amy::size length, const paging::PML4T& original_PML4T) {
-       os::assert(length >= amy::byte_size<os::elf::header>(), "Elf file isn't big enough to contain a header: there is an error.");
+       assert(length >= amy::byte_size<os::elf::header>(), "Elf file isn't big enough to contain a header: there is an error.");
        // TODO: Check that the elf file sections are all fully inside the file.
 
        // Load test-module elf file:
        const os::elf::header elf_header = *(os::elf::header*)start;
 
        // Check if elf is valid:
-       os::assert(elf_header.magic[0] == '\x7f', "No elf header.");
-       os::assert(elf_header.magic[1] == 'E', "No elf header.");
-       os::assert(elf_header.magic[2] == 'L', "No elf header.");
-       os::assert(elf_header.magic[3] == 'F', "No elf header.");
-       os::assert(elf_header.bitn == 2, "Elf file not 64 bits.");
-       os::assert(elf_header.endianness == 1, "Elf file not little endian.");
-       os::assert(elf_header.type == 2, "Elf file not executable.");
-       os::assert(elf_header.arch == 0x3E, "Elf file not x86_64.");
+       assert(elf_header.magic[0] == '\x7f', "No elf header.");
+       assert(elf_header.magic[1] == 'E', "No elf header.");
+       assert(elf_header.magic[2] == 'L', "No elf header.");
+       assert(elf_header.magic[3] == 'F', "No elf header.");
+       assert(elf_header.bitn == 2, "Elf file not 64 bits.");
+       assert(elf_header.endianness == 1, "Elf file not little endian.");
+       assert(elf_header.type == 2, "Elf file not executable.");
+       assert(elf_header.arch == 0x3E, "Elf file not x86_64.");
 
        constexpr amy::size stack_size = 16 * 0x1000 /* 64KiB */;
        amy::byte* const stack = (amy::byte*)0x0000'8000'0000'0000 - stack_size;
 
        const auto page = os::paging::page_allocator.allocate(1);
-       os::assert(page.ptr != nullptr, "Not enough memory for elf file loading.");
+       assert(page.ptr != amy::nil, "Not enough memory for elf file loading.");
        result.PML4T = phys_ptr<paging::PML4T>(page.ptr.get_phys_addr());
        result.rip = amy::u64(elf_header.entry);
        result.rsp = amy::u64(stack + stack_size);
@@ -68,7 +69,7 @@ void os::elf::load_elf(os::process& result, amy::byte* start, amy::size length,
                        continue;
                }
                os::print("Segment: loadable\n");
-               os::assert(0x1000 <= amy::u64(program_header.p_vaddr)
+               assert(0x1000 <= amy::u64(program_header.p_vaddr)
                                && amy::u64(program_header.p_vaddr + program_header.p_memsz) < 0x10'0000'0000,
                        "Program segments must be contained between 0x1000 and 0x10'0000'0000 (i.e. 64GiB).");
 
@@ -76,7 +77,7 @@ void os::elf::load_elf(os::process& result, amy::byte* start, amy::size length,
                amy::size nb_pages = (amy::u64(program_header.p_vaddr) % 0x1000 + program_header.p_memsz + 0x1000 - 1) / 0x1000;
                for (amy::size i = 0; i < nb_pages; i++) {
                        auto const alloc = os::paging::page_allocator.allocate(1);
-                       os::assert(alloc.ptr != nullptr, "Failed to allocate enough memory for loading of elf binary.");
+                       assert(alloc.ptr != nullptr, "Failed to allocate enough memory for loading of elf binary.");
                        os::paging::map_page(*result.PML4T, (os::paging::page<0>*)(program_header.p_vaddr + i * 0x1000), alloc.ptr, {
                                .RW = ((program_header.flags & 2) >> 1) != 0,
                                .US = true, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = false, .AVL = 0,
index 228803966136127ced4635e61a8c07f86aa65d97..3b7d9efaac27a9af685daabaf9cc629853133d0a 100644 (file)
@@ -112,7 +112,7 @@ extern "C" void int_page_fault(amy::u32 err_code, amy::u64 vaddr) {
        ) { // Kernel memory
                os::print("Allocating (Ring 0): {}\n", (void*)vaddr);
                auto const alloc = os::paging::page_allocator.allocate(1);
-               os::assert(alloc.ptr != nullptr, "Out of memory.");
+               assert(alloc.ptr != nullptr, "Out of memory.");
                os::paging::map_page(os::paging::global_PML4T, (os::paging::page<0>*)vaddr, alloc.ptr,
                        {.RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = true});
                return;
@@ -121,7 +121,7 @@ extern "C" void int_page_fault(amy::u32 err_code, amy::u64 vaddr) {
        ) { // Userspace memory
                os::print("Allocating (Ring 3): {}\n", (void*)vaddr);
                auto const alloc = os::paging::page_allocator.allocate(1);
-               os::assert(alloc.ptr != nullptr, "Out of memory.");
+               assert(alloc.ptr != nullptr, "Out of memory.");
                os::paging::map_page(*os::get_process(os::current_pid).PML4T, (os::paging::page<0>*)vaddr, alloc.ptr,
                        {.RW = true, .US = true, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = false, .AVL = 0, .NX = true});
                return;
index 1ea335f836d4ac98c4f1c0611e36e91fe42bd8be..846168f97ed4279c831b3ae1ae30798549e0829c 100644 (file)
@@ -14,6 +14,7 @@
 #pragma once
 
 #include <types.hpp>
+#include <assert.hpp>
 #include "lib/phys_ptr.hpp"
 #include "serial.hpp"
 #include "utils.hpp"
@@ -58,12 +59,9 @@ struct isr_info {
        bool present : 1 = true;
 };
 
-template<typename... Ts>
-void assert(bool cond, const char* format, const Ts&... vs);
-
 template<amy::size interrupt_nb>
 void enable_interrupts(const isr_info (&ISRs)[interrupt_nb], os::idt<interrupt_nb>& idt) {
-       os::assert(is_APIC_builtin(), "No builtin APIC.");
+       assert(is_APIC_builtin(), "No builtin APIC.");
 
        disable_PIC();
        set_APIC_reg(0xF0, 0x1FF); // Enable APIC
index 42d0355ee6044e70c5a17b8eaf86e781df2a07f7..76dcd4a3b2a54bf28b93db36fea0f66334f22929 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <allocator.hpp>
 #include <vector.hpp>
+#include <assert.hpp>
 #include "lib/multiboot2.hpp"
 #include "paging.hpp"
 #include "utils.hpp"
@@ -37,18 +38,18 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
                        os::hlt();
                }
        }
-       os::assert(magic == 0x36D76289, "Incorrect magic number: wasn't booted with multiboot2.");
+       assert(magic == 0x36D76289, "Incorrect magic number: wasn't booted with multiboot2.");
 
        os::paging::page_allocator.deallocate({
                .ptr = os::phys_ptr<os::paging::page<0>>(amy::ptr(&bootstrap_pages_for_memory) & amy::ptr(~0xFFFF'FFFF'8000'0000)),
                .size = amy::byte_size<decltype(bootstrap_pages_for_memory)>() / amy::byte_size<decltype(bootstrap_pages_for_memory[0])>()
        });
 
-       os::assert(os::cpu_has_msr(), "MSRs aren't supported.");
+       assert(os::cpu_has_msr(), "MSRs aren't supported.");
        // Initialise kernel map.
-       os::assert(amy::ptr(&_kernel_phys_start) % 4096 == 0, "Kernel isn't page aligned !");
-       os::assert(amy::ptr(&_kernel_phys_rw_start) % 4096 == 0, "Kernel isn't page aligned !");
-       os::assert(amy::ptr(&_kernel_phys_end) % 4096 == 0, "Kernel isn't page aligned !");
+       assert(amy::ptr(&_kernel_phys_start) % 4096 == 0, "Kernel isn't page aligned !");
+       assert(amy::ptr(&_kernel_phys_rw_start) % 4096 == 0, "Kernel isn't page aligned !");
+       assert(amy::ptr(&_kernel_phys_end) % 4096 == 0, "Kernel isn't page aligned !");
        for (amy::size i = amy::ptr(&_kernel_phys_start); i < amy::ptr(&_kernel_phys_rw_start); ) {
                if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < amy::ptr(&_kernel_phys_rw_start)) {
                        os::paging::map_page<2, 3>(os::paging::global_PML4T, (os::paging::page<2>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<2>>(i),
@@ -94,8 +95,8 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
                                if (e <= 1024 * 1024) { // I'll ignore lower memory for now.
                                        continue;
                                }
-                               os::assert(s % 0x1000 == 0, "Memory map unaligned on page boundaries.");
-                               os::assert(e % 0x1000 == 0, "Memory map unaligned on page boundaries.");
+                               assert(s % 0x1000 == 0, "Memory map unaligned on page boundaries.");
+                               assert(e % 0x1000 == 0, "Memory map unaligned on page boundaries.");
                                for (amy::ptr j = s; j < e; ) {
                                        if (j % (1024 * 1024 * 1024) == 0 && j + 1024 * 1024 * 1024 < e) {
                                                os::paging::map_page<2, 3>(
@@ -193,7 +194,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
                };
                amy::stack_allocator<amy::byte_size<ram_range>() * 64, amy::byte_align<ram_range>()> available_ram_allocator;
                amy::vector<ram_range, decltype(available_ram_allocator)> available_ram(available_ram_allocator);
-               os::assert(!available_ram.construction_failed(), "Failed to create vector.");
+               assert(!available_ram.construction_failed(), "Failed to create vector.");
                amy::size available_ram_length = 0;
 
                bool module_specified = false;
@@ -215,7 +216,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
                                        if (e.get_phys_addr() <= 1024 * 1024) { // I'll ignore lower memory for now.
                                                continue;
                                        }
-                                       os::assert(available_ram.push_back({.start_address = s, .end_address = e}),
+                                       assert(available_ram.push_back({.start_address = s, .end_address = e}),
                                                "Too much available RAM sections to initialise correctly. Will fix eventually, probably.");
                                }
                                break;
@@ -231,7 +232,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
                        }
                }
 
-               os::assert(module_specified, "No modules specified in the multiboot. This is unsupported.");
+               assert(module_specified, "No modules specified in the multiboot. This is unsupported.");
 
                // kernel_start and kernel_end are aligned to 4K by the linker script.
                const os::phys_ptr<os::paging::page<0>> kernel_s{amy::ptr(&_kernel_phys_start)};
@@ -250,7 +251,7 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr<const multiboot2::info_s
                        } else if (available_ram[i].end_address <= kernel_e) {
                                available_ram[i].end_address = kernel_s - 1; // Since start_address < s, start_address <= new end_address.
                        } else {
-                               os::assert(available_ram.push_back(available_ram[i]),
+                               assert(available_ram.push_back(available_ram[i]),
                                        "Too much available RAM sections to initialise correctly. Will fix eventually, probably.");
                                available_ram[i].end_address = kernel_s - 1;
                                available_ram[available_ram.size() - 1].start_address = kernel_e + 1;
index 4fb474ac1b3f5023962891d07c73bf41413338cd..b9e09893708a5f8fdda694fb5aeb173528dd1385 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <types.hpp>
 #include <memory.hpp>
+#include <assert.hpp>
 
 namespace os {
 
@@ -28,9 +29,11 @@ public:
        constexpr phys_ptr(amy::nil_t): phys_addr(0xF000'0000'0000'0000) {}
 
        inline void* operator->() const {
+               assert(*this != amy::nil);
                return get_virt_addr();
        }
        inline explicit operator void*() const {
+               assert(*this != amy::nil);
                return get_virt_addr();
        }
 
@@ -60,12 +63,15 @@ public:
        constexpr phys_ptr(amy::nil_t): phys_addr(0xF000'0000'0000'0000) {}
 
        T& operator[](amy::diff i) const {
+               assert(*this != amy::nil);
                return get_virt_addr()[i];
        }
        T& operator*() const {
+               assert(*this != amy::nil);
                return *get_virt_addr();
        }
        T* operator->() const {
+               assert(*this != amy::nil);
                return get_virt_addr();
        }
        explicit operator T*() const {
index ede7e3ba22f04eeac78f8a78bd80c884c9ba64a0..67df51805faabdfc02a750d65ff85d5202f99d34 100644 (file)
 
 #pragma once
 
+#include <assert.hpp>
 #include <types.hpp>
+#include "lib/phys_ptr.hpp"
 #include "serial.hpp"
 #include "utils.hpp"
-#include "lib/phys_ptr.hpp"
 
 namespace os { namespace paging {
 
@@ -53,12 +54,12 @@ template <amy::size depth> struct paging_entry {
                return (data & (1 << 0)) != 0;
        }
        bool is_page() {
-               os::assert(is_present(), "Cannot check if a paging_entry is a page if it's not present.");
+               assert(is_present(), "Cannot check if a paging_entry is a page if it's not present.");
                return depth == 0 || (data & (1 << 7)) != 0;
        }
 
        paging::page_info page_info() {
-               os::assert(is_page(), "Cannot access page info for a non-page.");
+               assert(is_page(), "Cannot access page info for a non-page.");
                return {
                        .RW = (data & (1ull << 1)) != 0,
                        .US = (data & (1ull << 2)) != 0,
@@ -76,12 +77,12 @@ template <amy::size depth> struct paging_entry {
                };
        }
        os::phys_ptr<os::paging::page<depth>> page_ptr() {
-               os::assert(is_page(), "Cannot access page physical pointer for a non-page.");
+               assert(is_page(), "Cannot access page physical pointer for a non-page.");
                amy::ptr addr = data & (depth == 0 ? 0x0000'FFFF'FFFF'F000 : 0x0000'FFFF'FFFF'E000);
                return os::phys_ptr<os::paging::page<depth>>(addr | ((addr & 0x0000'8000'0000'0000) != 0 ? 0xFFFF'8000'0000'0000 : 0));
        }
        void page_ptr(os::phys_ptr<os::paging::page<depth>> page) {
-               os::assert(is_page(), "Cannot access page physical pointer for a non-page.");
+               assert(is_page(), "Cannot access page physical pointer for a non-page.");
                if (depth == 0) {
                        data = (data & ~0x0000'FFFF'FFFF'F000) | page.get_phys_addr();
                } else {
@@ -89,7 +90,7 @@ template <amy::size depth> struct paging_entry {
                }
        }
        paging::paging_table_info paging_table_info() {
-               os::assert(!is_page(), "Cannot access paging table info for a page.");
+               assert(!is_page(), "Cannot access paging table info for a page.");
                return {
                        .RW = (data & (1ull << 1)) != 0,
                        .US = (data & (1ull << 2)) != 0,
@@ -103,12 +104,12 @@ template <amy::size depth> struct paging_entry {
                };
        }
        os::phys_ptr<os::paging::paging_table<depth - 1>> paging_table_ptr() {
-               os::assert(!is_page(), "Cannot access paging table physical pointer for a page.");
+               assert(!is_page(), "Cannot access paging table physical pointer for a page.");
                amy::ptr addr = data & 0x0000'FFFF'FFFF'F000;
                return os::phys_ptr<os::paging::paging_table<depth - 1>>(addr | ((addr & 0x0000'8000'0000'0000) != 0 ? 0xFFFF'8000'0000'0000 : 0));
        }
        void paging_table_ptr(os::phys_ptr<os::paging::paging_table<depth - 1>> table) {
-               os::assert(!is_page(), "Cannot access paging table physical pointer for a page.");
+               assert(!is_page(), "Cannot access paging table physical pointer for a page.");
                data = (data & ~0x0000'FFFF'FFFF'F000) | table.get_phys_addr();
        }
        void remove() {
@@ -220,7 +221,7 @@ template <amy::size depth, amy::size paging_depth>
 void map_page(paging_table<paging_depth>& paging_table, page<depth> const* vaddr, phys_ptr<page<depth>> paddr, os::paging::page_info page_info) {
        amy::size const index = (amy::ptr(vaddr) >> (12 + 9 * paging_depth)) & 0x1FF;
        if constexpr (depth == paging_depth) {
-               os::assert(!paging_table.contents[index].is_present(), "Virtual address 0x{} is already mapped.", vaddr);
+               assert(!paging_table.contents[index].is_present(), "Virtual address 0x{} is already mapped.", vaddr);
                paging_table.contents[index].page_info(page_info);
                paging_table.contents[index].page_ptr(paddr);
                invlpg(vaddr);
index 5df22c534f0110316c6f3690f507ce628b37ac64..f0716d596f5c729af4736ea8523a984eeed63cb3 100644 (file)
@@ -11,6 +11,7 @@
 // You should have received a copy of the GNU General Public License along with this program. If
 // not, see <https://www.gnu.org/licenses/>.
 
+#include <assert.hpp>
 #include "ring3.hpp"
 #include "utils.hpp"
 #include "serial.hpp"
@@ -51,19 +52,19 @@ void schedule_next_process() {
 
 // extern "C" int os::syscall_mount_kernel_device(amy::fd wd, char device, char const* path, amy::size path_len, int mount_type);
 extern "C" int os::syscall_mount_kernel_device(amy::fd, char, char const*, amy::size, int) {
-       os::assert(false, "mount_kernel_device not implemented yet.");
+       assert(false, "mount_kernel_device not implemented yet.");
        __builtin_unreachable();
 }
 
 // extern "C" amy::fd os::syscall_open(amy::fd wd, char const* path, amy::size path_len, int options);
 extern "C" amy::fd os::syscall_open(amy::fd, char const*, amy::size, int) {
-       os::assert(false, "open not implemented yet.");
+       assert(false, "open not implemented yet.");
        __builtin_unreachable();
 }
 
 extern "C" amy::size os::syscall_read(amy::fd file, char* data, amy::size len) {
-       os::assert(file == amy::fd(0), "Read isn't really implemented for now.");
-       os::assert(len >= 0, "Read expects a positive size.");
+       assert(file == amy::fd(0), "Read isn't really implemented for now.");
+       assert(len >= 0, "Read expects a positive size.");
        if (len == 0) {
                return 0;
        }
@@ -82,8 +83,8 @@ extern "C" amy::size os::syscall_read(amy::fd file, char* data, amy::size len) {
 }
 
 extern "C" amy::size os::syscall_write(amy::fd file, char const* data, amy::size len) {
-       os::assert(file == amy::fd(0), "Write isn't really implemented for now.");
-       os::assert(len >= 0, "Write expects a positive size.");
+       assert(file == amy::fd(0), "Write isn't really implemented for now.");
+       assert(len >= 0, "Write expects a positive size.");
        if (len == 0) {
                return 0;
        }
@@ -99,12 +100,12 @@ extern "C" amy::size os::syscall_write(amy::fd file, char const* data, amy::size
 
 // extern "C" int syscall_close(amy::fd file);
 extern "C" int os::syscall_close(amy::fd) {
-       os::assert(false, "Close isn't implemented for now.");
+       assert(false, "Close isn't implemented for now.");
        __builtin_unreachable();
 }
 
 extern "C" void os::syscall_rax_error_handler() {
-       os::assert(false, "Incorrect %rax for syscall.");
+       assert(false, "Incorrect %rax for syscall.");
        __builtin_unreachable();
 }
 
index 5f2f58a179c8b313caea791e2dcd7287bd72050c..2bd047793eefaf879eb303c63df35ed7f1c251e7 100644 (file)
 #include "interrupts.hpp"
 #include "serial.hpp"
 
+void amy::assert_handler(char const* cond, char const* file, int line) {
+       os::print("Assertion error in file '{}', at line {}: {}.\n", file, (unsigned)line, cond);
+       while (true) {
+               os::hlt();
+       }
+}
+
 bool os::init_serial_port() {
        outb(serial_port + 1, 0x00); // Disable interrupts.
        outb(serial_port + 3, 0x80); // Prepare to set baud rate divisor (38400 baud).
@@ -52,13 +59,13 @@ void os::printc(char c) {
        write_serial(c);
 }
 void os::print_formatted(const char* format, const char* val) {
-       os::assert(format[0] == '}', "Format string unsupported. TODO.");
+       assert(format[0] == '}', "Format string unsupported. TODO.");
        for (amy::size i = 0; val[i] != '\0'; i++) {
                os::printc(val[i]);
        }
 }
 void os::print_formatted(const char* format, amy::u64 val) {
-       os::assert(format[0] == '}', "Format string unsupported. TODO.");
+       assert(format[0] == '}', "Format string unsupported. TODO.");
        char data[20];
        char* curr = data + 19;
        while (val != 0) {
@@ -74,7 +81,7 @@ void os::print_formatted(const char* format, amy::u64 val) {
        }
 }
 void os::print_formatted(const char* format, amy::i64 val) {
-       os::assert(format[0] == '}', "Format string unsupported. TODO.");
+       assert(format[0] == '}', "Format string unsupported. TODO.");
        if (val < 0) {
                os::printc('-');
                os::print_formatted(format, amy::u64(-val));
@@ -84,7 +91,7 @@ void os::print_formatted(const char* format, amy::i64 val) {
        }
 }
 void os::print_formatted(const char* format, phys_ptr<void> val) {
-       os::assert(format[0] == '}', "Format string unsupported. TODO.");
+       assert(format[0] == '}', "Format string unsupported. TODO.");
        os::print("0x");
        for (int i = 60; i >= 0; i -= 4) {
                const int v = (val.get_phys_addr() >> i) & 0xF;
@@ -92,7 +99,7 @@ void os::print_formatted(const char* format, phys_ptr<void> val) {
        }
 }
 void os::print_formatted(const char* format, const void* val) {
-       os::assert(format[0] == '}', "Format string unsupported. TODO.");
+       assert(format[0] == '}', "Format string unsupported. TODO.");
        os::print("0x");
        for (int i = 60; i >= 0; i -= 4) {
                const int v = (reinterpret_cast<amy::ptr>(val) >> i) & 0xF;
index 479f1f0a903460a0994d77d8dc7328258262ea4e..908ab502a0b10be1968e801734566408fc32c30e 100644 (file)
 
 #pragma once
 
+#include <assert.hpp>
 #include "types.hpp"
 #include "lib/phys_ptr.hpp"
 
 namespace os {
 
-template<typename... Ts>
-void assert(bool cond, const char* format, const Ts&... vs);
-
 constexpr amy::u16 serial_port{0x3F8};
 
 bool init_serial_port();
@@ -72,24 +70,21 @@ void print(const char* format, const Ts&... vs) {
        for (amy::size 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] == '{') {
+                       assert(format[i] != '\0', "Error in format string: unterminated '{{}'.");
+                       if (format[i] == '{') {
                                printc('{');
                                continue;
                        } else {
                                amy::size format_spec_end = i;
                                while (format[format_spec_end] != '}') {
-                                       if (format[format_spec_end++] == '\0') {
-                                               os::assert(false, "Error in format string: unterminated '{{}'.");
-                                       }
+                                       assert(format[format_spec_end++] != '\0', "Error in format string: unterminated '{{}'.");
                                }
                                amy::size n = arg_n;
                                if ('0' <= format[i] && format[i] <= '9') {
                                        if (arg_n == 0) {
                                                arg_n_is_given = true;
                                        }
-                                       os::assert(arg_n_is_given, "Error in format string: either the arg_id is always given, or never.");
+                                       assert(arg_n_is_given, "Error in format string: either the arg_id is always given, or never.");
                                        amy::size n_ = 0;
                                        while ('0' <= format[i] && format[i] <= '9') {
                                                n_ = n_ * 10 + (format[i++] - '0');
@@ -99,20 +94,20 @@ void print(const char* format, const Ts&... vs) {
                                        if (arg_n == 0) {
                                                arg_n_is_given = false;
                                        }
-                                       os::assert(!arg_n_is_given, "Error in format string: either the arg_id is always given, or never.");
+                                       assert(!arg_n_is_given, "Error in format string: either the arg_id is always given, or never.");
                                }
                                if (format[i] == ':') {
                                        i++;
                                } else {
-                                       os::assert(format[i] == '}', "Error in format string: ':' required before format spec.");
+                                       assert(format[i] == '}', "Error in format string: ':' required before format spec.");
                                }
-                               os::assert(n < amy::size(sizeof...(vs)), "Error in format string: not enough arguments.");
+                               assert(n < amy::size(sizeof...(vs)), "Error in format string: not enough arguments.");
                                (print_nth_helper{n, &format[i]} % ... % get_more_general_type_helper_t<Ts>(vs));
                                i = format_spec_end;
                                arg_n++;
                        }
                } else if (format[i] == '}') {
-                       os::assert(format[i + 1] == '}', "Error in format string: unexpected '}'.");
+                       assert(format[i + 1] == '}', "Error in format string: unexpected '}'.");
                        i++;
                        printc('}');
                } else {
@@ -124,15 +119,4 @@ void print(const char* format, const Ts&... vs) {
 void cli();
 void hlt();
 
-template<typename... Ts>
-void assert(bool cond, const char* format, const Ts&... vs) {
-       if (!cond) {
-               print("Error: ");
-               print(format, vs...);
-               printc('\n');
-               cli();
-               while (true) { hlt(); }
-       }
-}
-
 } // namespace os
index 3ac872f3dcad0da034e8ece7707ed75160ab541c..2381c04cfff3842914d4af0750118c68ee1af8c6 100644 (file)
@@ -13,6 +13,7 @@
 
 #pragma once
 
+#include <assert.hpp>
 #include <types.hpp>
 #include <memory.hpp>
 #include "serial.hpp"
@@ -51,22 +52,22 @@ public:
                return 0 <= index && index < n && elems[index].present;
        }
        amy::i64 create() {
-               os::assert(has_room(), "Too many allocated elems in incrementing_int64_map.");
+               assert(has_room(), "Too many allocated elems in incrementing_int64_map.");
                elems[n].present = true;
                new(elems[n].buffer) T;
                return n++;
        }
        void remove(amy::i64 index) {
-               os::assert(present(index), "Tried removing non-existant element of incrementing_int64_map.");
+               assert(present(index), "Tried removing non-existant element of incrementing_int64_map.");
                get(index).~T();
                elems[index].present = false;
        }
        T& get(amy::i64 index) {
-               os::assert(present(index), "Tried getting non-existant element of incrementing_int64_map.");
+               assert(present(index), "Tried getting non-existant element of incrementing_int64_map.");
                return *amy::launder(reinterpret_cast<T*>(&elems[index].buffer[0]));
        }
        const T& get(amy::i64 index) const {
-               os::assert(present(index), "Tried getting non-existant element of incrementing_int64_map.");
+               assert(present(index), "Tried getting non-existant element of incrementing_int64_map.");
                return *amy::launder(reinterpret_cast<T*>(&elems[index].buffer[0]));
        }
 
diff --git a/libcpp/assert.hpp b/libcpp/assert.hpp
new file mode 100644 (file)
index 0000000..1e61440
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2023 Amélia COUTARD.
+//
+// This file from the program "voyage au centre des fichiers" is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with this program. If
+// not, see <https://www.gnu.org/licenses/>.
+
+#pragma once
+
+#define assert(cond, ...) if (!(cond)) amy::assert_handler(#cond ", " #__VA_ARGS__, __FILE__, __LINE__)
+
+namespace amy {
+       void assert_handler(char const* cond, char const* file, int line) __attribute__((noreturn));
+} // namespace amy