feat: hello, world!
This commit is contained in:
parent
c1da9bc218
commit
14ab06110b
|
@ -2,21 +2,24 @@
|
||||||
-Wall
|
-Wall
|
||||||
-Wextra
|
-Wextra
|
||||||
-Werror
|
-Werror
|
||||||
-D__ck_loader_limine__
|
-Isrc/libs
|
||||||
|
-Isrc/kernel/klibs
|
||||||
|
-Isrc/kernel/archs
|
||||||
-D__ck_toolchain_value=clang
|
-D__ck_toolchain_value=clang
|
||||||
-D__ck_encoding_utf8__
|
|
||||||
-D__ck_sys_kernel__
|
|
||||||
-D__ck_freestanding__
|
|
||||||
-D__ck_loader_value=limine
|
-D__ck_loader_value=limine
|
||||||
-D__ck_encoding_value=utf8
|
-D__ck_encoding_value=utf8
|
||||||
-D__ck_arch_x86_64__
|
-D__ck_bits_64__
|
||||||
-D__ck_toolchain_clang__
|
-D__ck_toolchain_clang__
|
||||||
-D__ck_bits_value=64
|
|
||||||
-D__ck_abi_sysv__
|
|
||||||
-D__ck_abi_value=sysv
|
-D__ck_abi_value=sysv
|
||||||
-D__ck_sys_value=kernel
|
-D__ck_sys_value=kernel
|
||||||
|
-D__ck_loader_limine__
|
||||||
|
-D__ck_sys_kernel__
|
||||||
|
-D__ck_encoding_utf8__
|
||||||
|
-D__ck_abi_sysv__
|
||||||
|
-D__ck_freestanding__
|
||||||
-D__ck_arch_value=x86_64
|
-D__ck_arch_value=x86_64
|
||||||
-D__ck_bits_64__
|
-D__ck_bits_value=64
|
||||||
|
-D__ck_arch_x86_64__
|
||||||
-ffreestanding
|
-ffreestanding
|
||||||
-fno-stack-protector
|
-fno-stack-protector
|
||||||
-mno-80387
|
-mno-80387
|
||||||
|
@ -26,3 +29,4 @@
|
||||||
-mno-sse2
|
-mno-sse2
|
||||||
-mno-red-zone
|
-mno-red-zone
|
||||||
-Dauto=__auto_type
|
-Dauto=__auto_type
|
||||||
|
-Isrc/kernel/klibs
|
||||||
|
|
19
src/kernel/archs/hal.h
Normal file
19
src/kernel/archs/hal.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <io/stream.h>
|
||||||
|
|
||||||
|
void hal_setup(void);
|
||||||
|
|
||||||
|
/* --- Assembly function --------------------------------------------------- */
|
||||||
|
|
||||||
|
void hal_disable_interrupts(void);
|
||||||
|
|
||||||
|
void hal_enable_interrupts(void);
|
||||||
|
|
||||||
|
void hal_pause(void);
|
||||||
|
|
||||||
|
void hal_panic(void);
|
||||||
|
|
||||||
|
/* --- I/O ---------------------------------------------------------------- */
|
||||||
|
|
||||||
|
Stream hal_dbg_stream(void);
|
19
src/kernel/archs/x86_64/asm.c
Normal file
19
src/kernel/archs/x86_64/asm.c
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
void hal_disable_interrupts(void)
|
||||||
|
{
|
||||||
|
asm volatile("cli");
|
||||||
|
}
|
||||||
|
|
||||||
|
void hal_enable_interrupts(void)
|
||||||
|
{
|
||||||
|
asm volatile("sti");
|
||||||
|
}
|
||||||
|
|
||||||
|
void hal_pause(void)
|
||||||
|
{
|
||||||
|
asm volatile("pause");
|
||||||
|
}
|
||||||
|
|
||||||
|
void hal_panic(void)
|
||||||
|
{
|
||||||
|
asm volatile("int $1");
|
||||||
|
}
|
19
src/kernel/archs/x86_64/e9.c
Normal file
19
src/kernel/archs/x86_64/e9.c
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include <res.h>
|
||||||
|
|
||||||
|
#include "e9.h"
|
||||||
|
|
||||||
|
Res e9_putc(char c)
|
||||||
|
{
|
||||||
|
asm volatile("outb %0, $0xe9" : : "a"(c) : "memory");
|
||||||
|
return ok$();
|
||||||
|
}
|
||||||
|
|
||||||
|
Res e9_puts(size_t n, char const *s)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
e9_putc(s[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok$();
|
||||||
|
}
|
7
src/kernel/archs/x86_64/e9.h
Normal file
7
src/kernel/archs/x86_64/e9.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <res.h>
|
||||||
|
|
||||||
|
Res e9_putc(char c);
|
||||||
|
|
||||||
|
Res e9_puts(size_t n, char const *s);
|
16
src/kernel/archs/x86_64/manifest.json
Normal file
16
src/kernel/archs/x86_64/manifest.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
|
"type": "lib",
|
||||||
|
"id": "arch (x86_64)",
|
||||||
|
"enableIf": {
|
||||||
|
"arch": [
|
||||||
|
"x86_64"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"provides": [
|
||||||
|
"arch"
|
||||||
|
],
|
||||||
|
"requires": [
|
||||||
|
"dbg"
|
||||||
|
]
|
||||||
|
}
|
14
src/kernel/archs/x86_64/mod.c
Normal file
14
src/kernel/archs/x86_64/mod.c
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include <io/stream.h>
|
||||||
|
|
||||||
|
#include "e9.h"
|
||||||
|
|
||||||
|
Stream hal_dbg_stream(void)
|
||||||
|
{
|
||||||
|
return (Stream){
|
||||||
|
.write = e9_puts,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void hal_setup(void)
|
||||||
|
{
|
||||||
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
|
#include <dbg/log.h>
|
||||||
|
|
||||||
_Noreturn int _start()
|
_Noreturn int _start()
|
||||||
{
|
{
|
||||||
|
log$("Hello, world!");
|
||||||
for (;;)
|
for (;;)
|
||||||
;
|
;
|
||||||
}
|
}
|
|
@ -1,5 +1,17 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
"type": "exe",
|
"type": "exe",
|
||||||
"id": "core"
|
"id": "core",
|
||||||
|
"requires": [
|
||||||
|
"arch",
|
||||||
|
"dbg",
|
||||||
|
"stdc-shim"
|
||||||
|
],
|
||||||
|
"tools": {
|
||||||
|
"cc": {
|
||||||
|
"args": [
|
||||||
|
"-Isrc/kernel/klibs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
46
src/kernel/klibs/dbg/log.c
Normal file
46
src/kernel/klibs/dbg/log.c
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#include <fmt/fmt.h>
|
||||||
|
#include <hal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <sync/spinlock.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
static Spinlock _lock = SPINLOCK_INIT;
|
||||||
|
|
||||||
|
static char const *level_names[LOG_EVENT_LENGTH] = {
|
||||||
|
[LOG_NONE] = "",
|
||||||
|
[LOG_INFO] = "INFO",
|
||||||
|
[LOG_WARN] = "WARN",
|
||||||
|
[LOG_ERROR] = "ERROR",
|
||||||
|
[LOG_CRIT] = "CRITIC",
|
||||||
|
};
|
||||||
|
|
||||||
|
static char const *level_colors[LOG_EVENT_LENGTH] = {
|
||||||
|
[LOG_NONE] = "",
|
||||||
|
[LOG_INFO] = "\e[1;34m",
|
||||||
|
[LOG_WARN] = "\e[1;33m",
|
||||||
|
[LOG_ERROR] = "\e[1;31m",
|
||||||
|
[LOG_CRIT] = "\e[1;35m",
|
||||||
|
};
|
||||||
|
|
||||||
|
void _log(LogEvent event, Loc loc, char const *format, ...)
|
||||||
|
{
|
||||||
|
spinlock_acquire(&_lock);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
if (event != LOG_NONE)
|
||||||
|
{
|
||||||
|
fmt(hal_dbg_stream(), "%s%s\e[0m %s:%d ", level_colors[event], level_names[event], loc.file, loc.line);
|
||||||
|
}
|
||||||
|
|
||||||
|
vfmt(hal_dbg_stream(), format, args);
|
||||||
|
|
||||||
|
if (event != LOG_NONE)
|
||||||
|
{
|
||||||
|
hal_dbg_stream().write(1, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
spinlock_release(&_lock);
|
||||||
|
}
|
24
src/kernel/klibs/dbg/log.h
Normal file
24
src/kernel/klibs/dbg/log.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <io/stream.h>
|
||||||
|
|
||||||
|
#include "loc.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
LOG_NONE,
|
||||||
|
LOG_INFO,
|
||||||
|
LOG_WARN,
|
||||||
|
LOG_ERROR,
|
||||||
|
LOG_CRIT,
|
||||||
|
|
||||||
|
LOG_EVENT_LENGTH
|
||||||
|
} LogEvent;
|
||||||
|
|
||||||
|
#define log$(...) _log(LOG_INFO, loc$(), __VA_ARGS__)
|
||||||
|
#define warn$(...) _log(LOG_WARN, loc$(), __VA_ARGS__)
|
||||||
|
#define error$(...) _log(LOG_ERROR, loc$(), __VA_ARGS__)
|
||||||
|
#define critical$(...) _log(LOG_CRIT, loc$(), __VA_ARGS__)
|
||||||
|
#define print$(...) _log(LOG_NONE, (Loc){}, __VA_ARGS__)
|
||||||
|
|
||||||
|
void _log(LogEvent event, Loc loc, char const *format, ...);
|
14
src/kernel/klibs/dbg/manifest.json
Normal file
14
src/kernel/klibs/dbg/manifest.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
|
"type": "lib",
|
||||||
|
"id": "dbg",
|
||||||
|
"enableIf": {
|
||||||
|
"freestanding": [
|
||||||
|
true
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"requires": [
|
||||||
|
"sync",
|
||||||
|
"fmt"
|
||||||
|
]
|
||||||
|
}
|
13
src/kernel/klibs/stdc-shim/manifest.json
Normal file
13
src/kernel/klibs/stdc-shim/manifest.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
|
"type": "lib",
|
||||||
|
"id": "stdc-shim",
|
||||||
|
"props": {
|
||||||
|
"cpp-root-include": true
|
||||||
|
},
|
||||||
|
"enableIf": {
|
||||||
|
"freestanding": [
|
||||||
|
true
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
51
src/kernel/klibs/stdc-shim/string.c
Normal file
51
src/kernel/klibs/stdc-shim/string.c
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
size_t strlen(char const str[static 1])
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
while (*str++)
|
||||||
|
{
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memcpy(void *restrict dst, void const *restrict src, size_t n)
|
||||||
|
{
|
||||||
|
char *restrict d = dst;
|
||||||
|
char const *restrict s = src;
|
||||||
|
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memset(void *dest, int c, size_t n)
|
||||||
|
{
|
||||||
|
char *d = dest;
|
||||||
|
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
*d++ = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memcmp(const void *s1, const void *s2, size_t n)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
if (((const char *)s1)[i] != ((const char *)s2)[i])
|
||||||
|
{
|
||||||
|
return ((const char *)s1)[i] - ((const char *)s2)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
11
src/kernel/klibs/stdc-shim/string.h
Normal file
11
src/kernel/klibs/stdc-shim/string.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
size_t strlen(char const s[static 1]);
|
||||||
|
|
||||||
|
void *memcpy(void *restrict dest, void const *restrict src, size_t n);
|
||||||
|
|
||||||
|
void *memset(void *dest, int c, size_t n);
|
||||||
|
|
||||||
|
int memcmp(void const *s1, void const *s2, size_t n);
|
10
src/kernel/klibs/sync/manifest.json
Normal file
10
src/kernel/klibs/sync/manifest.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
|
"type": "lib",
|
||||||
|
"id": "sync",
|
||||||
|
"enableIf": {
|
||||||
|
"freestanding": [
|
||||||
|
true
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
30
src/kernel/klibs/sync/spinlock.c
Normal file
30
src/kernel/klibs/sync/spinlock.c
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include <hal.h>
|
||||||
|
|
||||||
|
#include "spinlock.h"
|
||||||
|
|
||||||
|
static _Atomic int retain_count = 0;
|
||||||
|
|
||||||
|
static void retain_interrupts(void)
|
||||||
|
{
|
||||||
|
retain_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void release_interrupt(void)
|
||||||
|
{
|
||||||
|
retain_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spinlock_acquire(Spinlock spinlock[static 1])
|
||||||
|
{
|
||||||
|
retain_interrupts();
|
||||||
|
while (atomic_flag_test_and_set(&spinlock->lock))
|
||||||
|
{
|
||||||
|
hal_pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spinlock_release(Spinlock spinlock[static 1])
|
||||||
|
{
|
||||||
|
atomic_flag_clear(&spinlock->lock);
|
||||||
|
release_interrupt();
|
||||||
|
}
|
17
src/kernel/klibs/sync/spinlock.h
Normal file
17
src/kernel/klibs/sync/spinlock.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
volatile atomic_flag lock;
|
||||||
|
} Spinlock;
|
||||||
|
|
||||||
|
#define SPINLOCK_INIT \
|
||||||
|
(Spinlock) { .lock = ATOMIC_FLAG_INIT }
|
||||||
|
|
||||||
|
Spinlock spinlock_new(void);
|
||||||
|
|
||||||
|
void spinlock_acquire(Spinlock spinlock[static 1]);
|
||||||
|
|
||||||
|
void spinlock_release(Spinlock spinlock[static 1]);
|
191
src/libs/fmt/fmt.c
Normal file
191
src/libs/fmt/fmt.c
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "fmt.h"
|
||||||
|
|
||||||
|
static char *strrev(char *str)
|
||||||
|
{
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
char tmp;
|
||||||
|
|
||||||
|
end = strlen(str) - 1;
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
while (start < end)
|
||||||
|
{
|
||||||
|
tmp = str[start];
|
||||||
|
str[start] = str[end];
|
||||||
|
str[end] = tmp;
|
||||||
|
start++;
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *itoa(int64_t value, char *str, int base)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
bool isNegative = false;
|
||||||
|
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
str[i++] = '0';
|
||||||
|
str[i] = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 0 && base == 10)
|
||||||
|
{
|
||||||
|
isNegative = true;
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (value != 0)
|
||||||
|
{
|
||||||
|
int rem = value % base;
|
||||||
|
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
|
||||||
|
value = value / base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNegative)
|
||||||
|
{
|
||||||
|
str[i++] = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
str[i] = '\0';
|
||||||
|
|
||||||
|
return strrev(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *utoa(uint64_t value, char *str, int base)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
str[i++] = '0';
|
||||||
|
str[i] = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (value != 0)
|
||||||
|
{
|
||||||
|
int rem = value % base;
|
||||||
|
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
|
||||||
|
value = value / base;
|
||||||
|
}
|
||||||
|
|
||||||
|
str[i] = '\0';
|
||||||
|
|
||||||
|
return strrev(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
Res fmt(Stream stream, char const fmt[static 1], ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
Res res = vfmt(stream, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Res vfmt(Stream stream, char const fmt[static 1], va_list args)
|
||||||
|
{
|
||||||
|
const char *s = fmt;
|
||||||
|
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
if (*s == '%')
|
||||||
|
{
|
||||||
|
switch (*++s)
|
||||||
|
{
|
||||||
|
case 'd':
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
char buf[100];
|
||||||
|
int64_t value = va_arg(args, int64_t);
|
||||||
|
|
||||||
|
itoa(value, buf, 10);
|
||||||
|
stream.write(strlen(buf), buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'u':
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
char buf[100];
|
||||||
|
uint64_t value = va_arg(args, int64_t);
|
||||||
|
|
||||||
|
utoa(value, buf, 10);
|
||||||
|
stream.write(strlen(buf), buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
char buf[100];
|
||||||
|
uint64_t value = va_arg(args, uint64_t);
|
||||||
|
|
||||||
|
utoa(value, buf, 16);
|
||||||
|
stream.write(2, "0x");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 16 - strlen(buf); i++)
|
||||||
|
{
|
||||||
|
stream.write(1, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.write(strlen(buf), buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
char buf[100];
|
||||||
|
uint64_t value = va_arg(args, uint64_t);
|
||||||
|
|
||||||
|
utoa(value, buf, 16);
|
||||||
|
stream.write(strlen(buf), buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
char *value = va_arg(args, char *);
|
||||||
|
stream.write(strlen(value), value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
char value = va_arg(args, int);
|
||||||
|
stream.write(1, &value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '%':
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
stream.write(1, "%");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return err$(RES_INVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char sub[2] = {*s++, '\0'};
|
||||||
|
stream.write(1, sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uok$(0);
|
||||||
|
}
|
8
src/libs/fmt/fmt.h
Normal file
8
src/libs/fmt/fmt.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <io/stream.h>
|
||||||
|
#include <res.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
Res fmt(Stream stream, char const fmt[static 1], ...);
|
||||||
|
Res vfmt(Stream stream, char const fmt[static 1], va_list args);
|
5
src/libs/fmt/manifest.json
Normal file
5
src/libs/fmt/manifest.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
|
"type": "lib",
|
||||||
|
"id": "fmt"
|
||||||
|
}
|
5
src/libs/io/manifest.json
Normal file
5
src/libs/io/manifest.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1",
|
||||||
|
"type": "lib",
|
||||||
|
"id": "io"
|
||||||
|
}
|
9
src/libs/io/stream.h
Normal file
9
src/libs/io/stream.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "res.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Res (*write)(size_t n, char const buf[static n]);
|
||||||
|
Res (*read)(size_t n, char buf[static n]);
|
||||||
|
} Stream;
|
18
src/libs/loc.h
Normal file
18
src/libs/loc.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char const *file;
|
||||||
|
const char *full;
|
||||||
|
const char *func;
|
||||||
|
size_t line;
|
||||||
|
} Loc;
|
||||||
|
|
||||||
|
#define loc$() ((Loc){ \
|
||||||
|
.file = __FILE_NAME__, \
|
||||||
|
.full = __FILE__, \
|
||||||
|
.func = __func__, \
|
||||||
|
.line = __LINE__, \
|
||||||
|
})
|
56
src/libs/res.h
Normal file
56
src/libs/res.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "loc.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#define RES_TYPE(F) \
|
||||||
|
F(RES_OK) \
|
||||||
|
F(RES_INVAL) \
|
||||||
|
F(RES_NOMEM) \
|
||||||
|
F(RES_BADALIGN) \
|
||||||
|
F(RES_NOENT)
|
||||||
|
|
||||||
|
enum res_type
|
||||||
|
{
|
||||||
|
RES_TYPE(make_enum$)
|
||||||
|
};
|
||||||
|
|
||||||
|
static char const *res_type_str[] = {RES_TYPE(make_str$)};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
enum res_type type;
|
||||||
|
Loc loc;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
size_t uvalue;
|
||||||
|
ptrdiff_t ivalue;
|
||||||
|
};
|
||||||
|
} Res;
|
||||||
|
|
||||||
|
#define ok$() \
|
||||||
|
(Res) { .type = RES_OK, .uvalue = 0, .loc = loc$() }
|
||||||
|
|
||||||
|
#define uok$(u) \
|
||||||
|
(Res) { .type = RES_OK, .uvalue = (u), .loc = loc$() }
|
||||||
|
|
||||||
|
#define iok$(i) \
|
||||||
|
(Res) { .type = RES_OK, .ivalue = (i), .loc = loc$() }
|
||||||
|
|
||||||
|
#define err$(t) \
|
||||||
|
(Res) { .type = (t), .uvalue = 0, .loc = loc$() }
|
||||||
|
|
||||||
|
#define try$(EXPR) \
|
||||||
|
({ \
|
||||||
|
Res __result = (Res)(EXPR); \
|
||||||
|
if (__result.type != RES_OK) \
|
||||||
|
return __result; \
|
||||||
|
__result.ivalue; \
|
||||||
|
})
|
||||||
|
|
||||||
|
static inline char const *res_to_str(Res res)
|
||||||
|
{
|
||||||
|
return res_type_str[res.type];
|
||||||
|
}
|
9
src/libs/utils.h
Normal file
9
src/libs/utils.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define max$(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#define min$(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#define make_enum$(enum) enum,
|
||||||
|
|
||||||
|
#define make_str$(str) #str,
|
Loading…
Reference in a new issue