about summary refs log tree commit diff
path: root/boot/common.c
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-03-11 22:34:40 +0100
committerMel <mel@rnrd.eu>2025-03-11 22:34:40 +0100
commitbed8e60da8d8ebc3d367872bacd64137414e7ae9 (patch)
tree993198cc1bca0a3873f997f0f2a764899e121d82 /boot/common.c
parent03dd7d175cbfb728e0c9708b515a5b0435eaa29a (diff)
downloadcatskill-bed8e60da8d8ebc3d367872bacd64137414e7ae9.tar.zst
catskill-bed8e60da8d8ebc3d367872bacd64137414e7ae9.zip
Add common library for basic types, functions and macros
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/common.c')
-rw-r--r--boot/common.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/boot/common.c b/boot/common.c
new file mode 100644
index 0000000..67e13eb
--- /dev/null
+++ b/boot/common.c
@@ -0,0 +1,146 @@
+/*
+ * a small library of types, functions and macros that
+ * are used throughout the bootstrap compiler.
+ * allocation done purely statically.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define uint8 uint8_t
+#define uint16 uint16_t
+#define uint32 uint32_t
+#define uint64 uint64_t
+
+#define int8 int8_t
+#define int16 int16_t
+#define int32 int32_t
+#define int64 int64_t
+
+#define float32 float
+#define float64 double
+#define real float64
+
+#define uint uint64
+#define integer int64
+#define flags int32
+
+#define ascii char
+#define byte char
+
+#define bool _Bool
+#define true 1
+#define false 0
+#define nil NULL
+#define unknown void
+
+// call on irrecoverable failure.
+// prints a very sad, apologetic message for
+// the user and aborts program with failure status.
+void
+failure(const ascii* message)
+{
+    const ascii* format =
+        "\\e[0;31m"
+        ";( sorry, a failure has occurred...\n"
+        "-> %s!\n"
+        "\\e[0m";
+    fprintf(stderr, format, message);
+
+    exit(EXIT_FAILURE);
+}
+
+// check a condition, triggering a failure if it's false.
+void
+check(bool condition, const ascii* message)
+{
+    if (!condition) failure(message);
+}
+
+// the common size of region memory blocks.
+#define REGION_SIZE 65536
+
+// statically allocates a region of memory of a given size
+// for a single type.
+#define REGION_OF_SIZE(type, of, size) \
+    type region_##of[size];            \
+    uint region_##of##_cursor = 0;
+
+// statically allocates a region of memory for a type.
+#define REGION(type, of) REGION_OF_SIZE(type, of, REGION_SIZE)
+
+// the global string region.
+REGION(ascii, string)
+
+// a string.
+struct String
+{
+    ascii* data;
+    uint length;
+};
+
+#define STRING_ITERATE(index, c, str) \
+    ascii c = string_at(str, 0);      \
+    for (uint index = 0; index < str.length; c = string_at(str, ++index))
+
+// allocates a new string in the global string region.
+struct String
+string_new(const ascii* data, uint length)
+{
+    // for compatibility, we include an additional null byte at the end.
+    uint allocation_length = length + 1;
+    check(region_string_cursor + allocation_length < REGION_SIZE, "out of string memory");
+
+    ascii* at = region_string + region_string_cursor;
+    region_string_cursor += allocation_length;
+
+    for (uint i = 0; i < length; ++i) at[i] = data[i];
+    at[length] = '\0';
+
+    return {
+        .data = at,
+        .length = length,
+    };
+}
+
+// allocates a new string in the global string region,
+// taking the data from a null-terminated C string.
+struct String
+string_from_c_string(const char* c_string)
+{
+    uint length = strlen(c_string);
+    return string_new(c_string, length);
+}
+
+// allocates a new string in the global string region,
+// taking the data from a static null-terminated C string.
+//
+// NOTE: The string is not copied, so it MUST have a lifetime
+// spanning the entire program.
+struct String
+string_from_static_c_string(const char* c_string)
+{
+    uint length = strlen(c_string);
+    return {
+        .data = (ascii*)c_string,
+        .length = length,
+    };
+}
+
+// returns the character at a given index.
+// does bounds-checking.
+ascii
+string_at(struct String s, uint index)
+{
+    check(index < s.length, "index out of bounds");
+    return s.data[index];
+}
+
+uint
+string_length(struct String s)
+{
+    return s.length;
+}