diff --git a/kernel/arch/x86/boot/boot.c b/kernel/arch/x86/boot/boot.c
index 60310c8..933e98e 100644
--- a/kernel/arch/x86/boot/boot.c
+++ b/kernel/arch/x86/boot/boot.c
@@ -19,14 +19,14 @@
void banner(void)
{
- tty_write("Welcome to MoonOS\n");
- tty_write(
- "\n"
- " _____ _____ _____ \n"
- "| |___ ___ ___| | __| \n"
- "| | | | . | . | | | |__ | \n"
- "|_|_|_|___|___|_|_|_____|_____| \n"
- "\n");
+ trace(TRACE_BOOT, "Welcome to MoonOS\n");
+ trace(TRACE_BOOT,
+ "\n"
+ " _____ _____ _____ \n"
+ "| |___ ___ ___| | __| \n"
+ "| | | | . | . | | | |__ | \n"
+ "|_|_|_|___|___|_|_|_____|_____| \n"
+ "\n");
}
NORETURN void boot(void)
diff --git a/kernel/arch/x86/devices/tty.c b/kernel/arch/x86/devices/tty.c
index 84fb6a5..bca077a 100644
--- a/kernel/arch/x86/devices/tty.c
+++ b/kernel/arch/x86/devices/tty.c
@@ -30,7 +30,7 @@ void arch_tty_init(uint64_t fb_addr, uint16_t fb_width, uint16_t fb_height,
// clang-format on
}
-void arch_tty_write(string_view str)
+void arch_tty_write(StringView str)
{
- flanterm_write(ft_ctx, str, strlen(str));
+ flanterm_write(ft_ctx, str.data, str.length);
}
diff --git a/kernel/arch/x86/devices/tty.h b/kernel/arch/x86/devices/tty.h
index e893006..7469eeb 100644
--- a/kernel/arch/x86/devices/tty.h
+++ b/kernel/arch/x86/devices/tty.h
@@ -9,6 +9,6 @@ void arch_tty_init(uint64_t fb_addr, uint16_t fb_width, uint16_t fb_height,
uint8_t fb_red_mask_shift, uint8_t fb_green_mask_size,
uint8_t fb_green_mask_shift, uint8_t fb_blue_mask_size,
uint8_t fb_blue_mask_shift);
-void arch_tty_write(string_view str);
+void arch_tty_write(StringView str);
#endif // TTY_H
\ No newline at end of file
diff --git a/kernel/arch/x86/int/interrupts.c b/kernel/arch/x86/int/interrupts.c
index 993f22d..38a9f3a 100644
--- a/kernel/arch/x86/int/interrupts.c
+++ b/kernel/arch/x86/int/interrupts.c
@@ -11,37 +11,37 @@
isr_t isr_handler_array[256] = {0};
bool can_return = false;
-static string_view exception_messages[] = {
- "Type: (#DE) Division Exception",
- "Type: (#DB) Debug Exception",
- "Type: (NONE) NMI interrupt (Non Maskable Interrupt)",
- "Type: (#BP) Breakpoint Exception",
- "Type: (#OF) Into detected Overflow Exception",
- "Type: (#BR) BOUND Range Exceeded",
- "Type: (#UD) Invalid Opcode (Undefined Opcode)",
- "Type: (#NM) Device Not Available (No Math Coprocessor)",
- "Type: (#DF) Double Fault",
- "Type: (NONE) Coprocessor Segment Overrun (reserved)",
- "Type: (#TS) Invalid TSS",
- "Type: (#NP) Segment Not Present",
- "Type: (#SS) Stack-Segment Fault",
- "Type: (#GP) General Protection Fault",
- "Type: (#PF) Page Fault",
- "Type: (NONE) Unknown interrupt",
- "Type: (#CF) Coprocessor fault",
- "Type: (#AC) Alignment check",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved",
- "Type: (NONE) Reserved"};
+static StringView exception_messages[] = {
+ str_literal("Type: (#DE) Division Exception"),
+ str_literal("Type: (#DB) Debug Exception"),
+ str_literal("Type: (NONE) NMI interrupt (Non Maskable Interrupt)"),
+ str_literal("Type: (#BP) Breakpoint Exception"),
+ str_literal("Type: (#OF) Into detected Overflow Exception"),
+ str_literal("Type: (#BR) BOUND Range Exceeded"),
+ str_literal("Type: (#UD) Invalid Opcode (Undefined Opcode)"),
+ str_literal("Type: (#NM) Device Not Available (No Math Coprocessor)"),
+ str_literal("Type: (#DF) Double Fault"),
+ str_literal("Type: (NONE) Coprocessor Segment Overrun (reserved)"),
+ str_literal("Type: (#TS) Invalid TSS"),
+ str_literal("Type: (#NP) Segment Not Present"),
+ str_literal("Type: (#SS) Stack-Segment Fault"),
+ str_literal("Type: (#GP) General Protection Fault"),
+ str_literal("Type: (#PF) Page Fault"),
+ str_literal("Type: (NONE) Unknown interrupt"),
+ str_literal("Type: (#CF) Coprocessor fault"),
+ str_literal("Type: (#AC) Alignment check"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved"),
+ str_literal("Type: (NONE) Reserved")};
void isr_handler(struct iframe *regs)
{
@@ -54,7 +54,7 @@ void isr_handler(struct iframe *regs)
serial_set_color(BASH_RED);
debug(true,
"ERROR: %s (err_code %ld) | %lx\n",
- exception_messages[regs->isr_number],
+ exception_messages[regs->isr_number].data,
regs->error_code,
cr2_read());
// for(;;);
@@ -137,8 +137,9 @@ void install_isr(uint8_t base, isr_t handler)
isr_handler_array[base] = handler;
}
else
- printk(
- "INT", "The interrupt ( %d ) has already been registered!\n", base);
+ trace(TRACE_INT,
+ "The interrupt (%d) has already been registered!\n",
+ base);
}
void uninstall_isr(uint8_t base)
diff --git a/kernel/panic.c b/kernel/panic.c
index 0188597..120b90c 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -1,3 +1,4 @@
+#define PR_MODULE "panic"
#include "panic.h"
#include
#include
@@ -17,8 +18,8 @@ NORETURN void __panic(size_t bp, size_t sp, string_view fmt, ...)
override_quiet_boot();
- printk("panic", "\n\033[31mA kernel panic has occurred\033[39m\n");
- tty_write("*** \033[97mReason: %s\033[39m ***\n", panic_buff);
+ trace(TRACE_ERROR, "\n\033[31mA kernel panic has occurred\033[39m\n");
+ trace(TRACE_ERROR, "*** \033[97mReason: %s\033[39m ***\n", panic_buff);
debug(false,
"A kernel panic has occurred\n*** \033[97mReason: %s\033[39m ***\n",
panic_buff);
@@ -29,11 +30,11 @@ NORETURN void __panic(size_t bp, size_t sp, string_view fmt, ...)
}
size_t frame_size = bp - sp;
- printk("stackdump",
- "Dumping %s's stackframe\nStackframe size: 0x%x\n",
- sym_lookup(res.trace_results[1]).name,
- frame_size);
- tty_write("\t\t \t \n");
+ trace(TRACE_ERROR,
+ "Dumping %s's stackframe\nStackframe size: 0x%x\n",
+ sym_lookup(res.trace_results[1]).name,
+ frame_size);
+ trace(TRACE_ERROR, "\t\t \t \n");
// The larger the stackframe the less likely the chance of seeing messages
// printed earlier due to the terminal scrolling. 0x18 was chosen randomly.
@@ -43,10 +44,11 @@ NORETURN void __panic(size_t bp, size_t sp, string_view fmt, ...)
// Dump stackframe of the function that called panic()
for (size_t i = 0; i < frame_size; i++)
{
- tty_write("%lx: %p %p\n",
- bp,
- *(size_t *)(bp),
- *(size_t *)(bp + sizeof(size_t)));
+ trace(TRACE_ERROR,
+ "%lx: %p %p\n",
+ bp,
+ *(size_t *)(bp),
+ *(size_t *)(bp + sizeof(size_t)));
bp += sizeof(size_t) * 2;
}
diff --git a/kernel/platform/acpi/x86/acpi.c b/kernel/platform/acpi/x86/acpi.c
index 8845fd8..2ce4c98 100644
--- a/kernel/platform/acpi/x86/acpi.c
+++ b/kernel/platform/acpi/x86/acpi.c
@@ -49,7 +49,7 @@ AcpiTable acpi_find_table(string_view identifier)
}
}
- printk("acpi", "Could not find table '%s'\n", identifier);
+ trace(TRACE_HARDWARE, "Could not find table '%s'\n", identifier);
return NULL;
}
diff --git a/kernel/platform/acpi/x86/madt/madt.c b/kernel/platform/acpi/x86/madt/madt.c
index 82258f9..8b4b62b 100644
--- a/kernel/platform/acpi/x86/madt/madt.c
+++ b/kernel/platform/acpi/x86/madt/madt.c
@@ -44,8 +44,8 @@ struct apic_device_info madt_init(void *madt_base)
pic_disable();
enumarate_apic_devices(&madt);
- trace(TRACE_MISC, "OEM String: '%s'\n", oem_str);
- trace(TRACE_MISC, "OEM Table ID: '%s'\n", oem_table_id);
+ trace(TRACE_HARDWARE, "OEM String: '%s'\n", oem_str);
+ trace(TRACE_HARDWARE, "OEM Table ID: '%s'\n", oem_table_id);
return apic_dev;
}
@@ -61,7 +61,7 @@ static void enumarate_apic_devices(madt_t **madt)
{
case 0 ... 5:
{
- trace(TRACE_MISC,
+ trace(TRACE_HARDWARE,
"Detected %s\n",
interrupt_device_id_map[*madt_interrupt_devices]);
@@ -84,12 +84,12 @@ static void enumarate_apic_devices(madt_t **madt)
}
case 9:
- printk("madt", "Detected x2APIC\n");
+ trace(TRACE_HARDWARE, "Detected x2APIC\n");
madt_interrupt_devices += madt_interrupt_devices[1];
break;
default:
- trace(TRACE_MISC,
+ trace(TRACE_HARDWARE,
"Invalid interrupt device detected, got %d, expected 0-5 "
"or 9\n",
*madt_interrupt_devices);
diff --git a/kernel/printk.c b/kernel/printk.c
index 9788bf1..2cca824 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -23,7 +23,7 @@ void printk_init(bool verbose_boot, HandoverFramebuffer fb)
is_verbose_boot = verbose_boot;
}
-void printk(string_view status, string_view fmt, ...)
+void printk(StringView status, StringView fmt, ...)
{
if (unlikely(!is_verbose_boot))
return;
@@ -31,21 +31,18 @@ void printk(string_view status, string_view fmt, ...)
char buffer[512];
va_list arg;
va_start(arg, fmt);
- vsnprintf((string)&buffer, (size_t)-1, fmt, arg);
+ vsnprintf(buffer, sizeof(buffer), fmt.data, arg);
va_end(arg);
- tty_write("[core#%d] %s: %s", current_cpu(), status, buffer);
-}
-
-void tty_write(string_view fmt, ...)
-{
- char buffer[512];
- va_list arg;
- va_start(arg, fmt);
- vsnprintf((string)&buffer, (size_t)-1, fmt, arg);
- va_end(arg);
+ char output[512];
+ snprintf(output,
+ sizeof(output),
+ "[core#%d] %s: %s",
+ current_cpu(),
+ status.data,
+ buffer);
- arch_tty_write((string_view)&buffer);
+ arch_tty_write(str(output));
}
// Note: This should only be called when information
diff --git a/kernel/printk.h b/kernel/printk.h
index 72d64b2..df1fcff 100644
--- a/kernel/printk.h
+++ b/kernel/printk.h
@@ -2,6 +2,7 @@
#define FMT_PRINTK_H
#include
+#include
#include
#include
@@ -16,39 +17,40 @@
debug(true, x, __VA_ARGS__); \
} while (0)
-#define trace(bitmask, ...) \
- do \
- { \
- if (bitmask & TRACE_MASK) \
- printk(PR_MODULE, __VA_ARGS__); \
+#define trace(bitmask, fmt, ...) \
+ do \
+ { \
+ if (bitmask & TRACE_MASK) \
+ printk(str(PR_MODULE), str(fmt), ##__VA_ARGS__); \
} while (0)
#define TRACE_MASK (TRACE_ALL)
enum
{
- TRACE_BOOT = (1 << 0),
- TRACE_INT = (1 << 1),
- TRACE_DEBUG = (1 << 2),
- TRACE_SYSCALL = (1 << 3),
- TRACE_MISC = (1 << 4), // For logs with no specific category
- TRACE_TASK = (1 << 5),
- TRACE_SERVICE = (1 << 6),
- TRACE_ELF = (1 << 7),
- TRACE_SLAB = (1 << 8),
- TRACE_BUDDY = (1 << 9),
- TRACE_TLSF = (1 << 10),
- TRACE_ALLOC = (1 << 11),
- TRACE_IPC = (1 << 12),
- TRACE_CAP = (1 << 13),
+ TRACE_BOOT = (1 << 0),
+ TRACE_INT = (1 << 1),
+ TRACE_DEBUG = (1 << 2),
+ TRACE_SYSCALL = (1 << 3),
+ TRACE_MISC = (1 << 4), // For logs with no specific category
+ TRACE_TASK = (1 << 5),
+ TRACE_SERVICE = (1 << 6),
+ TRACE_ELF = (1 << 7),
+ TRACE_SLAB = (1 << 8),
+ TRACE_BUDDY = (1 << 9),
+ TRACE_TLSF = (1 << 10),
+ TRACE_ALLOC = (1 << 11),
+ TRACE_IPC = (1 << 12),
+ TRACE_CAP = (1 << 13),
+ TRACE_ERROR = (1 << 14),
+ TRACE_HARDWARE = (1 << 15),
TRACE_ALL = ~0,
TRACE_NONE = 0,
};
-void printk(string_view status, string_view fmt, ...);
void printk_init(bool verbose_boot, HandoverFramebuffer fb);
-void tty_write(string_view fmt, ...);
+void printk(StringView status, StringView fmt, ...);
// Note: This should only be called when information
// must be shown, a kernel panic for example
diff --git a/kernel/trace/sym.c b/kernel/trace/sym.c
index 8888633..54c683d 100644
--- a/kernel/trace/sym.c
+++ b/kernel/trace/sym.c
@@ -1,16 +1,17 @@
+#define PR_MODULE "sym"
#if defined(__x86_64__)
#include "sym.h"
-#include
#include
#include
#include
+#include
extern SymbolTable symbol_table[];
SymbolTable sym_lookup(uint64_t address)
{
uint64_t corrected_address = 0;
- uint64_t index_new = 0;
+ uint64_t index_new = 0;
for (int i = 0;; i++)
{
@@ -24,15 +25,14 @@ SymbolTable sym_lookup(uint64_t address)
if (sym_addr > corrected_address)
{
corrected_address = sym_addr;
- index_new = i;
+ index_new = i;
}
}
if (sym_addr == 0xFFFFFFFF)
{
- return (SymbolTable){
- .addr = corrected_address,
- .name = symbol_table[index_new].name};
+ return (SymbolTable){.addr = corrected_address,
+ .name = symbol_table[index_new].name};
}
}
}
@@ -58,7 +58,7 @@ int64_t find_symbol_by_name(string name)
void backtrace_symbol(uint64_t address)
{
SymbolTable sym = sym_lookup(address);
- printk("backtrace", "%llx - %s\n", sym.addr, sym.name);
+ trace(TRACE_MISC, "%llx - %s\n", sym.addr, sym.name);
debug(false, "%llx - %s\n", sym.addr, sym.name);
}
#endif
\ No newline at end of file
diff --git a/libs/base/cstring.h b/libs/base/cstring.h
new file mode 100644
index 0000000..6c4cf04
--- /dev/null
+++ b/libs/base/cstring.h
@@ -0,0 +1,14 @@
+#ifndef LIB_KERNEL_CSTRING_H
+#define LIB_KERNEL_CSTRING_H
+
+#include
+
+int strcmp(const char *str1, const char *str2);
+int strncmp(string_view str1, string_view str2, size_t n);
+char *strcpy(char *dest, string_view src);
+char *strcat(char *a, char *b);
+uint64_t strlen(string_view s);
+char *strrev(char *src);
+bool isdigit(int c);
+
+#endif // LIB_KERNEL_CSTRING_H
\ No newline at end of file
diff --git a/libs/base/sources/assert.c b/libs/base/sources/assert.c
index eb2ff37..bda11c0 100644
--- a/libs/base/sources/assert.c
+++ b/libs/base/sources/assert.c
@@ -1,12 +1,25 @@
+#define PR_MODULE "assert"
#include "assert.h"
+#include
#include
#include
-#include
-void __assert_impl(string_view file, uint64_t line, string_view func, string_view desc)
+void __assert_impl(string_view file, uint64_t line, string_view func,
+ string_view desc)
{
- printk("ASSERT", "%s:%d: %s: Assertion `%s' failed", (char *)file, line, func, desc);
- debug(true, "ASSERT: %s:%d: %s: Assertion `%s' failed", (char *)file, line, func, desc);
-
+ trace(TRACE_ERROR,
+ "%s:%d: %s: Assertion `%s' failed",
+ (char *)file,
+ line,
+ func,
+ desc);
+
+ debug(true,
+ "ASSERT: %s:%d: %s: Assertion `%s' failed",
+ (char *)file,
+ line,
+ func,
+ desc);
+
arch_halt_cpu();
}
\ No newline at end of file
diff --git a/libs/base/sources/cstring.c b/libs/base/sources/cstring.c
new file mode 100644
index 0000000..3a1c648
--- /dev/null
+++ b/libs/base/sources/cstring.c
@@ -0,0 +1,111 @@
+#include "cstring.h"
+
+// Compare two strings.
+/* Returns:
+ -1 if ( len(str1) > len(str2) ) or ( len(str2) > len(str1) )
+ 0 if str1 == str2
+ 1 otherwise
+*/
+int strcmp(const char *str1, const char *str2)
+{
+ int i = 0;
+ int failed = 0;
+
+ while (str1[i] != '\0' && str2[i] != '\0')
+ {
+ if (str1[i] != str2[i])
+ {
+ failed = 1;
+
+ break;
+ }
+
+ i++;
+ }
+
+ // did loop exit due to unequal lengths?
+ if ((str1[i] == '\0' && str2[i] != '\0') || // len( str2 ) > len( str1 )
+ (str1[i] != '\0' && str2[i] == '\0')) // len( str1 ) > len( str2 )
+ {
+ failed = -1;
+ }
+
+ return failed;
+}
+
+int strncmp(const char *str1, const char *str2, size_t n)
+{
+ for (size_t i = 0; i < n && str1; i++)
+ {
+ if (str1[i] != str2[i])
+ return -1;
+ }
+ return 0;
+}
+
+// Copy the NULL-terminated string src into dest, and return dest
+char *strcpy(char *dest, const char *src)
+{
+ int n = -1;
+ int len = strlen(src);
+ do
+ {
+ ++n;
+ memcpy((uint8_t *)dest, (uint8_t *)src, n);
+ } while (n < len);
+
+ dest[n] = 0; // Null terminate the stri
+ return dest;
+}
+
+char *strcat(char *a, char *b)
+{
+ char *ptr = a + strlen(a);
+
+ while (*b != '\0')
+ *ptr++ = *b++;
+
+ // null terminate destination string
+ *ptr = '\0';
+
+ return a;
+}
+
+// Get the string length
+uint64_t strlen(const char *s)
+{
+ uint64_t len = 0;
+
+ while (*s++ != '\0')
+ {
+ len++;
+ }
+
+ return len;
+}
+
+char *strrev(char *src)
+{
+ static char temp;
+ int src_string_index = 0;
+ int last_char = strlen(src) - 1;
+
+ for (; src_string_index < last_char; src_string_index++)
+ {
+ temp = src[src_string_index]; // Save current character
+ src[src_string_index] =
+ src[last_char]; // Swap out the current char with the last char
+ src[last_char] =
+ temp; // Swap out last character with the current character
+ last_char--;
+ }
+
+ src[strlen(src) - 1 + 1] = 0;
+
+ return src;
+}
+
+bool isdigit(int c)
+{
+ return (c >= '0' && c <= '9');
+}
diff --git a/libs/base/sources/string.c b/libs/base/sources/string.c
index aec072b..319a9d1 100644
--- a/libs/base/sources/string.c
+++ b/libs/base/sources/string.c
@@ -1,111 +1,42 @@
#include "base/string.h"
+#include "base/assert.h"
-// Compare two strings.
-/* Returns:
- -1 if ( len(str1) > len(str2) ) or ( len(str2) > len(str1) )
- 0 if str1 == str2
- 1 otherwise
-*/
-int strcmp(string_view str1, string_view str2)
+StringView make_string_view(const char *str)
{
- int i = 0;
- int failed = 0;
-
- while (str1[i] != '\0' && str2[i] != '\0')
- {
- if (str1[i] != str2[i])
- {
- failed = 1;
-
- break;
- }
-
- i++;
- }
-
- // did loop exit due to unequal lengths?
- if ((str1[i] == '\0' && str2[i] != '\0') || // len( str2 ) > len( str1 )
- (str1[i] != '\0' && str2[i] == '\0')) // len( str1 ) > len( str2 )
- {
- failed = -1;
- }
-
- return failed;
-}
-
-int strncmp(string_view str1, string_view str2, size_t n)
-{
- for (size_t i = 0; i < n && str1; i++)
- {
- if (str1[i] != str2[i])
- return -1;
- }
- return 0;
+#if defined(HEAVY_ASSERTS)
+ assert(str != NULL && "Bad string pointer");
+ assert(strlen(str) > 0 && "Bad length");
+#else
+ if (str == NULL)
+ return (StringView){0};
+#endif
+
+ return (StringView){
+ .length = strlen(str),
+ .data = str,
+ };
}
-// Copy the NULL-terminated string src into dest, and return dest
-char *strcpy(char *dest, string_view src)
+StringView make_string_view_from_string(const String *str)
{
- int n = -1;
- int len = strlen(src);
- do
- {
- ++n;
- memcpy((uint8_t *)dest, (uint8_t *)src, n);
- } while (n < len);
-
- dest[n] = 0; // Null terminate the stri
- return dest;
+ return (StringView){
+ .length = str->length,
+ .data = str->data,
+ };
}
-char *strcat(char *a, char *b)
+StringView make_string_view_from_array(const char arr[], size_t len)
{
- char *ptr = a + strlen(a);
-
- while (*b != '\0')
- *ptr++ = *b++;
-
- // null terminate destination string
- *ptr = '\0';
-
- return a;
-}
-
-// Get the string length
-uint64_t strlen(string_view s)
-{
- uint64_t len = 0;
-
- while (*s++ != '\0')
- {
- len++;
- }
-
- return len;
-}
-
-char *strrev(char *src)
-{
- static char temp;
- int src_string_index = 0;
- int last_char = strlen(src) - 1;
-
- for (; src_string_index < last_char; src_string_index++)
- {
- temp = src[src_string_index]; // Save current character
- src[src_string_index] =
- src[last_char]; // Swap out the current char with the last char
- src[last_char] =
- temp; // Swap out last character with the current character
- last_char--;
- }
-
- src[strlen(src) - 1 + 1] = 0;
-
- return src;
-}
-
-bool isdigit(int c)
-{
- return (c >= '0' && c <= '9');
-}
+#if defined(HEAVY_ASSERTS)
+ assert(arr != NULL && "Bad string pointer");
+ assert(len > 0 && "Bad length");
+#else
+ if (arr == NULL)
+ return (StringView){0};
+#endif
+
+ return (StringView){
+ .length = len,
+ .data = arr,
+ };
+}
\ No newline at end of file
diff --git a/libs/base/string.h b/libs/base/string.h
index 5b785c2..6d4a8d8 100644
--- a/libs/base/string.h
+++ b/libs/base/string.h
@@ -2,14 +2,36 @@
#define LIB_KERNEL_STRING_H
#include
+#include
+#include
-int strcmp(string_view str1, string_view str2);
-int strncmp(string_view str1, string_view str2, size_t n);
-char *strcpy(char *dest, string_view src);
-char *strcat(char *a, char *b);
-uint64_t strlen(string_view s);
-char *strrev(char *src);
+#define str(expression) \
+ _Generic((expression), \
+ char *: make_string_view, \
+ const char *: make_string_view, \
+ String *: make_string_view_from_string, \
+ default: make_string_view_from_array)(expression)
-bool isdigit(int c);
+#define str_literal(literal) \
+ (StringView) \
+ { \
+ .length = sizeof(literal) - 1, .data = literal \
+ }
+
+typedef struct
+{
+ size_t length;
+ char *data;
+} String;
+
+typedef struct
+{
+ const size_t length;
+ const char *const data;
+} StringView;
+
+StringView make_string_view(const char *str);
+StringView make_string_view_from_string(const String *str);
+StringView make_string_view_from_array(const char arr[], size_t len);
#endif // LIB_KERNEL_STRING_H
\ No newline at end of file
diff --git a/meta/build/make/Makefile.x86.acpi.conf b/meta/build/make/Makefile.x86.acpi.conf
index 355c737..610e808 100644
--- a/meta/build/make/Makefile.x86.acpi.conf
+++ b/meta/build/make/Makefile.x86.acpi.conf
@@ -1,3 +1,5 @@
+DEV_FLAGS := -DHEAVY_ASSERTS
+
# Kernel compiler / linker flags
CFLAGS := \
-I ../libs/ \
@@ -18,7 +20,8 @@ CFLAGS := \
-mno-sse2 \
-Wall \
-fno-omit-frame-pointer \
- -mno-red-zone
+ -mno-red-zone \
+ $(DEV_FLAGS)
ASMFLAGS := -felf64 -g -F dwarf -I arch/$(ARCH)/